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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/51779484/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 10:44:05  来源:igfitidea点击:

Xcode 10 - Instance will be immediately deallocated because property is 'weak'

swiftxcodexcode10

提问by Nader Besada

I recently downloaded Xcode 10 and I noticed an apparent bug when using weakor unownedvariables. I managed to create a simple example that showcases the problem so that people can recreate it.

我最近下载了 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 {}

As the error says, weakClassimmediately deallocates once MainClassis initialized and is always nil.

正如错误所说,weakClass立即解除分配一旦MainClass被初始化并且始终为零。

I have opened up the same playground with Xcode 9.3 and I can confirm that the code works fine with no errors or warnings

我用 Xcode 9.3 打开了同一个操场,我可以确认代码工作正常,没有错误或警告

Is this a bug in Xcode 10 or am I not getting something. If it is, is there any workarounds?

这是 Xcode 10 中的错误还是我没有得到任何东西。如果是,是否有任何解决方法?

EDIT: Original Example

编辑:原始示例

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?
}

coordinatoris always nil in LoginViewModel

coordinator始终为零 LoginViewModel

AppDelegate.swift

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
    }

回答by vivekDas

To understand this you must know the concept of ARC. ARCconcept is automatic reference count means ARCwill keep something in memory, as long as an allocated memory is strongly referenced by some variable. If it(ARC) found some allocated memory doesn't have any strong reference it will dealloc it. So the warning weakClassimmediately deallocatesonce MainClassis initialized and is always nil. Because it doesn't have any strong reference.Please comment any doubt.

要理解这一点,您必须了解ARC. ARC概念是自动引用计数意味着ARC只要分配的内存被某个变量强烈引用,就会在内存中保留一些东西。如果它(ARC)发现一些分配的内存没有任何强引用,它将释放它。因此,警告weakClass立即初始化deallocates一次MainClass并且始终为零。因为它没有任何强引用。请评论任何疑问。

One example below for retain cycle creation:

下面是保留循环创建的一个示例:

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
}

So, in class Bif we take weak var classAObjectretain cycle will not happen.

所以,class B如果我们采取weak var classAObject保留循环就不会发生。

回答by ukim

This is the purpose of weak. Swift uses reference count to manage memory. A strong pointer increases the reference count of the pointed object by 1, a weak pointer does not increase reference count. An object with 0 reference count will be deallocated.

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

Your instance of SomeClassonly pointed by a weak pointer, so its reference count is 0. As a result it is deallocated immediately.

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

Weak is useful to avoid retain cycles. For example, in escaping closure and in delegation design pattern.

弱对于避免保留循环很有用。例如,在转义闭包和委托设计模式中。

回答by Alex Zavatone

The question is, "is that reference strongly referenced elsewhere? If so, it will not be deallocated."

问题是,“该引用是否在其他地方被强烈引用?如果是,它不会被释放。”

I propose that Apple's warning message is misleading. I think that it should state that it will be deallocated immediately when its containing object is deallocated or when other strong references to it are deallocated.

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

Here's why.

这是为什么。

We have this warning on an instance in a view controller and the weak var is not deallocated immediately. The view controller appears, the weak var is instantiated, we wait, click a button that hits a breakpoint and yup, the weak var is still not nil. Yet when the view controller disappears and is deallocated, the weak var isdeallocated immediately.

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

But why? Well, by the time we come the part of code that has a weak reference to the variable, other code has already has a retain count of 3 and even though it's weak, it can'tbe immediately dismissed.

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

You can check this with po myObject.retainCount. It's notguaranteed to be accurate, but it will give you an idea. If the object's retaincount > 1 and it's strongly linked somewhere else, (please put a comment in your code to indicate where it is strongly referenced), weak will work. To avoid a compiler warning, don't reference the object directly, but the strong reference in the other object.

您可以使用po myObject.retainCount. 它不能保证准确,但它会给你一个想法。如果对象的保留计数 > 1 并且它在其他地方强链接(请在代码中添加注释以指示它被强引用的位置),弱将起作用。为了避免编译器警告,不要直接引用对象,而是引用另一个对象中的强引用。

So, I think that Apple needs to reword this warning because it's surely misleading.

因此,我认为 Apple 需要重新措辞此警告,因为它肯定具有误导性。