所以我在Swift中玩懒惰实例化并试图在swift中完全复制以下Objective C范例
//A Getter for a strong property
- (SomeObject)lazilyLoadedObject {
if (!_lazilyLoadedObject) {
_lazilyLoadedObject = [[SomeObject alloc] init];
__weak typeOf(self) weakSelf = self;
_lazilyLoadedObject.blockProperty = ^(){//Some block which relies on weakSelf};
}
return _lazilyLoadedObject;
}
然后我尝试执行以下操作,并惊讶地发现编译失败了Global is external, but doesn't have external or weak linkage!
lazy var lazilyLoadedObject: SomeObject = {
var instance = SomeObject()
instance.closureProperty = {[weak self] in
//Do something with weak self
}
return instance
}()
所以我的第一个问题是,当我们需要对self进行引用时,上面的lazy实例化片段有什么问题?
我决定使用下面的片段(主要是由于代码完成)。
lazy var lazilyLoadedObject: SomeObject = instantiateLazilyLoadedObject(self)()
func instantiateLazilyLoadedObject() -> SomeObject {
var instance = SomeObject()
instance.closureProperty = {[weak self] in
//Do something with weak self
}
return instance
}
究竟是什么^(自我)()?一个小小的谷歌搜索表明它是一个“咖喱功能”,但我真的不明白。将self作为参数并返回函数的方法是什么?是抽象出来的东西,还有另一层我没有看到(也许有更冗长的方式来写这个?)。最后,这是将目标C的顶部剪切转换为swift的正确方法吗?
答案 0 :(得分:4)
这看起来很像编译器错误(特别是因为它显示为链接失败而不是编译器失败)。我会开雷达。您应该得到编译器错误(而不是链接错误),或者它应该编译。你现在可能无法将此翻译成Swift。
但我可以回答第二个问题。正如你所说,这是一个咖喱的功能。
每个方法实际上都是一个需要"对象"作为它的第一个参数(等待它;我将解释)。
考虑一下:
struct X {
func doit() { println("Yes") }
}
简单。现在让我们做一个:
let x = X()
x.doit()
那输出"是"正如你所期待的那样。但x.doit()
完全以下内容:
X.doit(x)()
疯狂,什么是双parens?方法doit
实际上是具有以下签名的函数:
func doit(self: X) -> (() -> Void)
这是一个函数,它接受X
并返回一个不带任何东西并且什么都不返回的函数。再读一遍。它是一个返回函数的函数。
Currying(以Haskell Curry命名)是将带有多个参数的函数转换为只接受一个参数并返回接受下一个参数的函数的实践。在许多情况下,这非常方便,构建方法就是其中之一。
所以,x.doit
(注意没有parens;我的意思是实际的方法本身)与<{1}}(返回函数)完全相同。我可以将其中任何一个分配给另一个名字:
X.doit(x)
这两个是相同的。我可以将它们中的任何一个用作:
let doitMethod = x.doit
let doitFunc = X.doit(x)
因此,我们回到了这个问题。 doitMethod()
doitFunc()
是一种方法。或者它是一个获取对象并返回一个函数的函数。这两个陈述完全相同。也就是说,instantiateLazilyLoadedObject
几乎肯定是一个私有的实现细节,因为它不在Swift头中(而且它确实听起来像是一个内部实现细节)。最后,你几乎肯定会遇到一个编译错误,应该打开一个雷达。