ios - 理解为什么在函数内部实例化后使用弱释放存储的属性

标签 ios swift automatic-ref-counting xctest

即使在阅读了 Swift 关于 ARC 的文档之后,我仍然无法理解为什么一个属性被设置为 nil,即使它是在函数中实例化的。我有以下示例代码:

import UIKit

class ItemListViewController: UIViewController {

    @IBOutlet weak var tableView: UITableView!

    override func viewDidLoad() {
        super.viewDidLoad()
        tableView = UITableView()

    }


}

下面是测试运行的示例代码:

import XCTest
@testable import PassionProject

class ItemListViewControllerTests: XCTestCase {

    override func setUp() {
        super.setUp()
        // Put setup code here. This method is called before the invocation of each test method in the class.
    }

    override func tearDown() {
        // Put teardown code here. This method is called after the invocation of each test method in the class.
        super.tearDown()
    }
    func tests_TableViewIsNotNil_AfterViewDidLoad(){

        let storyboard = UIStoryboard.init(name: "Main", bundle: nil)
        let viewController = storyboard.instantiateViewController(withIdentifier: "ItemListViewController")
        let sut = viewController as! ItemListViewController
        _ = sut.view
        XCTAssertNotNil(sut.tableView)
    }

    func tests_loadingView_SetsUITableViewDataSource(){

    }

}

在被测试的函数中,我们已经创建了正确的实例,我知道调用 view 属性会触发 viewDidLoad() 方法。我不确定为什么测试在运行测试时声明 tableView 属性为 nil。我想从这个角度理解 ARC,并了解当测试表明 tableView 属性为 nil 时发生了什么。我们已经在 viewDidLoad() 中清楚地实例化了 UITableView 对象。我知道从 tableView 属性中删除“weak”时这个测试通过了,但我不明白为什么。任何解释都将不胜感激,以便更好地理解这一点。

最佳答案

I'm still having trouble understanding why a property was set to nil even when it's instantiated within a function

@IBOutlet weak var tableView: UITableView!

override func viewDidLoad() {
    super.viewDidLoad()
    tableView = UITableView()
}

那你还没有明白weak是什么意思。这意味着:this 引用没有能力让这个对象保持事件状态。因此,如果没有其他东西使该对象保持事件状态(即保留它),则无论如何实例化该对象,它都将消亡。

您的代码创建 TableView :UITableView()。它将 TableView 分配给一个变量:tableView = UITableView()。但是这个变量很弱。它没有能力让这个 TableView 保持事件状态。而且您没有做任何else 来保持此 TableView 的事件。因此,表格 View 立即死亡,在一阵烟雾中消失,留下 tableView 指向任何东西——因此 tableView 被重置为

然而,通常的事情是这样说话:

super.viewDidLoad()
let tv = UITableView(frame:someRect)
self.view.addSubview(tv)
tableView = tv

这让世界变得与众不同。 tableView 变量仍然很弱,仍然不能使 TableView 保持事件状态。但是我们将 TableView 作为 subview 添加到 self.view,现在它的 superview 让它保持事件状态

这就是为什么网点往往很弱的原因。这是因为它们引用的 View 具有已经使它们保持事件状态的父 View ,因此不需要第二个 引用(outlet 属性)来使它们也保持事件状态。

关于ios - 理解为什么在函数内部实例化后使用弱释放存储的属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41687591/

相关文章:

ios - CoreLocation 线程崩溃崩溃 : com. apple.CoreLocation.ConnectionClient.0x16fcb870.events

ios - 选择一个后从通知中心清除推送通知

ios - 当用户平移 map 时,iOS 6 中的 map 注释不会保持旋转

swift - 现场级自定义解码器

objective-c - Objective-C/ARC 中的 dealloc 会释放局部静态变量吗?

objective-c - 为什么我不能分配/初始化 - 得到 "Assigning retained object to unsafe property"警告?

objective-c - Objective-C ARC 中的(非原子、读写、保留)和(非原子、强)

ios - RxSwift DisposeBag 和 UITableViewCell

swift - iOS 12 模拟器中 TextView XCUIElement 值为 nil

swift - swift中各种类型变量声明的区别