Swift 弱惰性变量无法编译

Swift weak lazy variable won't compile

为了演示这个问题,我做了一个普通的 Cocoa 项目。这是 AppDelegate.swift:

import Cocoa

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {

    weak lazy var isGood : NSNumber? = {
        return true
    }()

    func doSomething() {
        let result = isGood!
    }

    func applicationDidFinishLaunching(aNotification: NSNotification) {
        // Insert code here to initialize your application
    }

    func applicationWillTerminate(aNotification: NSNotification) {
        // Insert code here to tear down your application
    }
}

Xcode 给出这个:

unkown :0: error: cannot convert return expression of type 'NSNumber?' (aka 'Optional') to return type 'NSNumber?'

unkown :0: cannot assign value of type 'NSNumber?' to type 'NSNumber??'

unkown :0: cannot assign value of type 'NSNumber?' to type 'NSNumber??'

在我的实际项目中,它是MyCustomClass的另一个对象(而不是NSNumber)。除了类型是 MyCustomClass.

之外,错误是相同的

如果我从声明中删除 weaklazy,就没问题了。但是我想避免引用计数为 +1,因为 MyCustomClass 是一个 NSViewController,它肯定会一直存在。

知道如何使用弱惰性变量吗?

尝试使用弱计算属性代替...

import Foundation

class C {
    weak var d : NSDate? {
        return NSDate()
    }
}

let c = C()
print(NSDate())
sleep(1)
print(c.d)

这会给你想要的行为(如果我理解你的问题:-))

2016-07-03 16:49:04 +0000
Optional(2016-07-03 16:49:05 +0000)

如果 d 必须只初始化一次,那么

import Foundation

class C {
    weak var d : NSDate? {
        return d0
    }
    lazy var d0: NSDate? = {
        return NSDate()
    }()
}

let c = C()
print(NSDate())
sleep(1)
print(c.d)
sleep(1)
print(c.d)

这正是您所需要的

2016-07-03 16:57:24 +0000
Optional(2016-07-03 16:57:25 +0000)
Optional(2016-07-03 16:57:25 +0000)

软弱和懒惰混在一起不好。错误消息在解释发生了什么方面完全没有用,但本质上 lazyweak 彼此不一致:

  • lazy 告诉 Swift 您不想在第一次访问变量之前创建它,但是一旦创建,您希望无限期地保留它以供将来参考,而
  • weak 告诉 Swift 你不希望你的变量成为最后一个 link 来阻止你的变量被释放,这对 "keep indefinitely" lazy 个变量的目标。

你可以通过模拟 lazy 来解决这个问题,像这样:

class Foo {

    weak var isGoodCache : NSNumber?

    private var makeIsGood : NSNumber {
        isGoodCache = true
        return isGoodCache!
    }

    var isGood:NSNumber? {
        return isGoodCache ?? makeIsGood
    }
}

lazy 和 weak 不兼容的原因是每次使用都会创建一个新实例,除非你有另一个地方持有强引用。如果您有另一个地方可以保存强引用,那么您不需要 class 成员成为创建实例的成员。

假设我们有:

weak lazy var myVariable: MyClass? = createMyClassInstance()

当您第一次使用它时,假设您只是在某处的函数调用中引用它...

myFunction(myVariable)

在下一行,myVariable 再次为空。

这是为什么?因为,一旦 myFunction 完成,就不再有对 myVariable 的引用,并且由于它很弱,相应的对象超出范围并消失。

惰性弱变量和任何函数调用结果之间没有区别。因此,您的变量也可能是一个函数或一个计算变量(这会使查看您的代码的任何人都更清楚)。

引用的创建者不必是负责保留它的人。我有一些 classes 有意保留自己,并自己决定何时应该通过释放对自己的强烈引用来回收它们。

我用另一个class作为这样的工厂。有时我必须调整构造函数的参数,使这个泛型 class 更像是一个模板,而不是实际的实现。但是,虽然它们存在,但工厂被设计为 return 已经存在的实例。

class Factory<T> {
private weak var refI: T?
var ref: T {
    if refI != nil {
        return refI
    }
    let r = T()
    refI = r
    return r
}

}