Ответ 1
I размещен на форумах разработчиков Apple, и сотрудник Apple ответил, что это известная ошибка.
Похоже, что компилятор получает искаженные символьные имена методов в общих расширениях неправильно, когда они живут в другой структуре.
У меня возникли проблемы с привязкой моей структуры к коду, который использует эту инфраструктуру. В частности, компоновщик не может найти символы для расширений для генерических структур.
Это то, что одно из расширений выглядит как Необязательно:
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
I размещен на форумах разработчиков Apple, и сотрудник Apple ответил, что это известная ошибка.
Похоже, что компилятор получает искаженные символьные имена методов в общих расширениях неправильно, когда они живут в другой структуре.
Если вы ищете временное исправление, вы можете обернуть расширение в методе класса:
// 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