Swift Framework не включает символы из расширений в общие структуры

У меня возникли проблемы с привязкой моей структуры к коду, который использует эту инфраструктуру. В частности, компоновщик не может найти символы для расширений для генерических структур.

Это то, что одно из расширений выглядит как Необязательно:

extension Optional {
    /// Unwrap the value returning 'defaultValue' if the value is currently nil
    func or(defaultValue: T) -> T {
        switch(self) {
            case .None:
                return defaultValue
            case .Some(let value):
                return value
        }
    }
}

Этот метод отлично работает на игровой площадке или в приложении, если код скомпилирован в основной части приложения. Однако, когда я пытаюсь скомпилировать это в Framework, приложения (и даже тесты для фреймворка) создают следующую ошибку компоновщика:

Undefined символы для архитектуры i386: "__TFSq2orU__fGSqQ__FQQ", ссылка:       __TFC18SwiftPlusPlusTests27Optional_SwiftPlusPlusTests13testOrWithNilfS0_FT_T_ в необязательном + SwiftPlusPlusTests.o

Аналогичные методы, подобные приведенным ниже, связаны штрафом (обратите внимание, что он не является общим)

extension String {
    /// Returns a string by repeating it 'times' times
    func repeat(times: Int) -> String {
        var result = ""
        for i in 0..times {
            result += self
        }
        return result
    }
}

В моем репозитории github есть два других расширения: SwiftPlusPlus, которые также не связаны (как с общими строками). Вы будете воспроизводить ошибки, если вы вытащите последнюю фиксацию, создайте фреймворк и затем попытайтесь выполнить модульные тесты.

До сих пор я пытался запускать "строки" в выводимых фреймворках и промежуточных файлах, и я не вижу символов для этих расширений, но я вижу символы для расширения метода repeat на String. Таким образом, он даже не компилирует их в библиотеку.

Кто-нибудь знает, почему символы не определены в рамках?

Edit

  • Здесь есть ссылка на мое дополнительное расширение
  • Здесь - ссылка на тестовый файл, который вызывает ошибку компоновщика при попытке скомпилировать тестовую цель.

Ответы

Ответ 1

I размещен на форумах разработчиков Apple, и сотрудник Apple ответил, что это известная ошибка.

Похоже, что компилятор получает искаженные символьные имена методов в общих расширениях неправильно, когда они живут в другой структуре.

Ответ 2

Если вы ищете временное исправление, вы можете обернуть расширение в методе класса:

// In your framework
public class OptionalOperator {
    public class func or<T>(optional:Optional<T>,defaultValue:T) ->T {
        return optional.or(defaultValue)
    }
}

// Outside the framework
var maybeText:String?
let text = OptionalOperator.or(maybeText, defaultValue: "Apple, please fix this")

Конечно, это не идеальное решение, и он поражает цель расширений. Поэтому, если вы планируете часто называть этот метод, мы могли бы перегрузить/определить оператор.

// In your framework
infix operator ||| {}

public func |||<T>(left:Optional<T>, right:T) -> T {
    return left.or(right)
}

// Outside the framework
var maybeText:String?
let text = maybeText ||| "Apple, please fix this"

В моем случае у меня есть несколько приложений, использующих фреймворк, поэтому я хочу сохранить реализацию метода внутри фреймворка. Однако перегрузка оператора (или просто использование глобальной функции) была бы неудобной, поэтому мне нужно перейти с первым параметром до тех пор, пока ошибка не будет исправлена.

Надеюсь, что это поможет.

ОБНОВЛЕНИЕ

Забавно, что у Swift уже есть оператор для этого (?).

var maybeText:String?
let text = maybeText ?? "Nice!"

Он назвал - Nil Coalescing Operator