即使在阅读了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属性中删除"弱"时通过,但我不明白为什么.任何解释都会非常感激,以便更好地理解这一点.
我仍然无法理解为什么属性设置为nil,即使它在函数中被实例化
@IBOutlet weak var tableView: UITableView! override func viewDidLoad() { super.viewDidLoad() tableView = UITableView() }
那你还没明白是什么weak
意思.这意味着:此引用无法使此对象保持活动状态.因此,如果不出意外保持这个对象还活着(即保留了它),对象将不管死如何被实例化.
您的代码创建表视图:UITableView()
.它将表视图分配给变量:tableView = UITableView()
.但这个变量很弱.它没有能力使这个表视图保持活力.并且你没有做任何其他会使这个表视图保持活力的东西.因此,桌子视图立即死亡,在一阵烟雾中消失,并且tableView
一言不发 - 因此tableView
被重置为nil
.
然而,通常的事情就是这样说:
super.viewDidLoad() let tv = UITableView(frame:someRect) self.view.addSubview(tv) tableView = tv
这使世界变得与众不同.该tableView
变量仍然较弱,仍然无法跟上表视图活着.但我们将表视图添加为子视图self.view
,现在它的superview使其保持活跃状态.
这就是为什么网点往往很薄弱的原因.这是因为它们引用的视图具有已经使它们保持活动状态的超视图,因此不需要第二个引用(出口属性)来保持它们的存活.