Swift Framework不包含从泛型结构扩展的符号

时间:2014-06-12 02:31:33

标签: ios generics frameworks linker swift

我无法将我的框架与利用该框架的代码相关联。具体来说,链接器无法找到泛型结构扩展的符号。

这是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方法扩展的符号。所以它似乎甚至没有将它们编译到库中。

有谁知道为什么框架中没有定义符号?

修改

  • Here是指向我的可选扩展程序的链接
  • Here是测试文件的链接,在尝试编译测试目标时导致链接器错误

2 个答案:

答案 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