Xcode 10 - 实例将立即解除分配,因为属性为"弱"



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

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

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

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

编辑:原始示例

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
}

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

下面是一个用于创建保留周期的示例:

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保留周期就不会发生。

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

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

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

问题是,"该引用是否在其他地方被强烈引用? 如果是这样,它将不会被解除分配。

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

原因如下。

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

但是为什么?好吧,当我们来到代码中对变量的弱引用部分时,其他代码已经导致该变量的保留计数为 3。这意味着即使它很弱,can't立即被解雇。

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

所以,我认为苹果需要改写这个警告,因为它肯定是误导性的。

此外,鉴于 Swift 属性没有相应的实例变量,当您为弱属性赋值时,它会立即被解除分配,这是有道理的。我在这里遇到了类似的问题,我的场景委托要求这个应用程序协调员的rootViewController:

class AppCoordinator {
private weak var navigationController : UINavigationController!
var rootViewController : UIViewController {
navigationController = UINavigationController()
return navigationController    // <-- here the app crashes: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value
}
}

相关内容

  • 没有找到相关文章

最新更新