我最近下载了Xcode 10,使用weak
或unowned
变量时发现一个明显的错误。我设法创建了一个简单的示例来展示问题,以便人们可以重新创建它。
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?
}
coordinator
在LoginViewModel
中始终为空
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
}
答案 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需要重新表达此警告,因为它肯定会误导人。