我无法将我的框架与利用该框架的代码相关联。具体来说,链接器无法找到泛型结构扩展的符号。
这是Optional的扩展名之一:
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时,apps(甚至是框架的测试)会产生以下链接器错误:
架构i386的未定义符号:" __ TFSq2orU__fGSqQ__FQQ", 引自: __TFC18SwiftPlusPlusTests27Optional_SwiftPlusPlusTests13testOrWithNilfS0_FT_T_ 在Optional + 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也没有链接(两者都在通用的strucs上)。如果您提取最新的提交,构建框架,然后尝试运行单元测试,您将重现错误。
到目前为止,我试图运行"字符串"在输出的框架和中间文件上,我没有看到这些扩展的符号,但我确实在repeat
上看到String
方法扩展的符号。所以它似乎甚至没有将它们编译到库中。
有谁知道为什么框架中没有定义符号?
修改
答案 0 :(得分:9)
我posted on the Apple Developer forums并且Apple员工回答说这是一个已知错误。
当它们生活在不同的框架中时,编译器看起来像通用扩展中的方法的错位符号名称是错误的。
答案 1 :(得分: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")
当然,这并不理想,并且违背了扩展的目的。因此,如果您打算经常调用此方法,我们可以overload/define an operator。
// 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"
就我而言,我有多个使用框架的应用程序,所以我想将方法实现保留在框架内。但是,重载一个操作符(或者只是使用一个全局函数)会很尴尬,所以我必须先使用第一个选项,直到修复了这个bug。
希望这有帮助。
更新
有趣的是,Swift已经有了一个运算符(??)。
var maybeText:String?
let text = maybeText ?? "Nice!"
它被称为 - Nil Coalescing Operator