Xcode 10-实例将立即释放,因为属性为“弱”

时间:2018-08-10 05:23:47

标签: swift xcode xcode10

我最近下载了Xcode 10,使用weakunowned变量时发现一个明显的错误。我设法创建了一个简单的示例来展示问题,以便人们可以重新创建它。

class MainClass {
    weak var weakClass: SomeClass!

    init() {

        // WARNING: Instance will be immediately deallocated because property 'weakClass' is 'weak'

        self.weakClass = SomeClass()
    }
}

class SomeClass {}

如错误所述,weakClass会在MainClass初始化后立即取消分配,并且始终为nil。

我已经使用Xcode 9.3打开了一个游乐场,并且可以确认该代码可以正常工作,没有错误或警告

这是Xcode 10中的bug还是我没有得到什么?如果是,是否有任何解决方法?

编辑:原始示例

class LoginCoordinator {

    var viewModel: LoginViewModel?
    var viewController: LoginViewController?

    init() {
        viewModel = LoginViewModel()
        viewModel?.coordinator = self
        viewController = LoginViewController(viewModel: viewModel!)
    }
}


class LoginViewModel: ViewModelDelegate {
    weak var coordinator: LoginCoordinator?
}

coordinatorLoginViewModel中始终为空

AppDelegate.swift

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    func setupView() {
        let coordinator = LoginCoordinator()
        let navigationController = UINavigationController(rootViewController: coordinator.create)

        navigationController.isNavigationBarHidden = true
        navigationController.navigationBar.isTranslucent = false

        window = UIWindow(frame: UIScreen.main.bounds)
        window?.rootViewController = navigationController
        window?.makeKeyAndVisible()
        window?.layer.cornerRadius = 6
        window?.layer.masksToBounds = true
    }

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        setupView()
        return true
    }

3 个答案:

答案 0 :(得分:7)

要了解这一点,您必须了解ARC的概念。 ARC概念是自动引用计数,这意味着ARC将在内存中保留某些内容,只要某个变量强烈引用了分配的内存即可。如果它(ARC)发现某些分配的内存没有任何强引用,它将对其进行分配。因此,weakClass初始化后,警告deallocates立即MainClass,并且始终为零。因为它没有强大的参考。请发表任何疑问。

以下是创建保留周期的示例:

class A {
var classBObject: B?

  init() {
     classBObject = B()
     classBObject.classAObject = self // Creates a retain cycle
 }
}

class B {
   var classAObject: A? // Strong(by default all are strong) variable create retain cycle
}

因此,在class B中,如果我们采取weak var classAObject,则保留周期不会发生。

答案 1 :(得分:4)

这是weak的目的。 Swift使用引用计数来管理内存。强指针将指向的对象的引用计数增加1,弱指针不会增加引用计数。引用计数为0的对象将被释放。

您的SomeClass实例仅由弱指针指向,因此其引用计数为0。因此,该实例将立即释放。

弱可用于避免保留周期。例如,在转义转义和委托设计模式中。

答案 2 :(得分:0)

问题是,“是否在其他地方强烈引用了该引用?如果是,则不会取消分配。”

我认为Apple的警告信息具有误导性。我认为应该声明,当包含对象的对象被释放或对其的其他强引用被释放时,它将立即被释放。

这就是原因。

我们在视图控制器中的实例上收到此警告,并且弱var不会立即释放。视图控制器出现,弱变量被实例化,我们等待,单击击断点的按钮,是的,弱变量仍然不为零。但是,当视图控制器消失并被释放时,弱var 会立即被释放。

但是为什么呢?好吧,等到我们的代码部分对变量的引用很弱时,其他代码的保留计数已经为3,即使它很弱,它can't也会被立即丢弃。

您可以使用po myObject.retainCount进行检查。它保证准确无误,但这会给您一个想法。如果对象的retaincount> 1并且在其他位置强烈链接(请在代码中添加注释以指示强烈引用的位置),则弱将起作用。为了避免编译器警告,请不要直接引用该对象,而应在另一个对象中强引用。

因此,我认为Apple需要重新表达此警告,因为它肯定会误导人。