【问题标题】:Swift arrays/collections memory managementSwift 数组/集合内存管理
【发布时间】:2014-11-26 16:35:16
【问题描述】:

我已经花了一个多星期的时间在线阅读各种文章和 StackOverflow Q&A 关于 UIViewController 中 Swift 数组的内存管理的问题,但我的应用程序仍然出现崩溃。我希望你能帮忙。

我有一个父类控制器和多个从父类继承的子类(使用示例简化),就像这样。

class ParentViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
    lazy var results: [AnyObject] = [AnyObject]()  //can contain various classes, such as Product, User, etc.

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return results.count
    }

        ...       
}


class SubViewController: ParentViewController {

   ... loads results Array via REST API, then then appends to array using 
   results.append(Product())

}

随机地,我会遇到这样的崩溃:

EXC_BAD_ACCESS KERN_INVALID_ADDRESS at 0x0000000a1abb4b17
Thread : Crashed: com.apple.main-thread
0  libobjc.A.dylib                0x000000019478fe10 cache_getImp + 16
1  libobjc.A.dylib                0x0000000194784a6c lookUpImpOrForward + 540
2  libobjc.A.dylib                0x000000019478fdb8 _objc_msgSend_uncached_impcache + 56
3  libswiftCore.dylib             0x00000001004d4e40 _ZN5swift12metadataimpl14ValueWitnessesINS0_17ObjCRetainableBoxEE18initializeWithCopyEPNS_11OpaqueValueES5_PKNS_8MetadataE + 24
4  libswiftCore.dylib             0x000000010036e3cc _TFSa6appendU__fRGSaQ__FQ_T_ + 92

根据我的理解,我认为这是因为在调用 results.append() 时,results 已不在内存中。

在 UIViewController 中实例化数组/集合的最佳实践是什么,尤其是当有子类时?这是我的一些想法,任何反馈将不胜感激。

1.在父类中使用lazy。这是基本情况并导致崩溃

lazy var results: [AnyObject] = [AnyObject]()

2.Init in SubViewController,这仍然会导致崩溃,另外,我应该使用deinit()释放内存吗?

in ParentViewController
var results: [AnyObject]

in SubViewController
    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        self.results = [Product]()
    }

3.在父类中使results 可选,这将要求父类中的所有方法检查可选。我应该在子类中的init 中还是在viewDidLoad() 中初始化数组?另外,我应该deinit 结果吗?在父类中为零?

in ParentViewController
var results: [AnyObject]?

deinit {
    results = nil
}

in SubViewController
    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        self.results = [Product]()
    }

任何建议将不胜感激!

【问题讨论】:

    标签: ios objective-c arrays memory-management swift


    【解决方案1】:

    我不知道您的视图控制器的生命周期和关系是什么,但我可靠地做到这一点的一种方法是将“结果”数组放置到您的 AppDelegate 中。当您使用视图控制器并且可以从它们访问时,这保证存在。

    let appDelegate = UIApplication.sharedApplication().delegate as AppDelegate
    appDelegate.results.append(...)
    

    【讨论】:

    • 谢谢。不幸的是,生命周期不是应用程序范围的,只是在实际控制器的生命周期中
    【解决方案2】:

    你是否在主线程中添加从其余 api 获取的结果?如果不试试这个:

    dispatch_async(dispatch_get_main_queue(), {
       results.append(objectsFromApi)
    })
    

    【讨论】:

    • 我正在使用“AFNetworking”,因此将其加载到单独的线程中。我应该在主线程中执行附加操作吗?
    • 抱歉,我仔细检查了AFNetworking 代码。成功完成块自动调用dispatch_get_main_queue,所以它在主线程中完成。我仔细检查了崩溃报告,发现results.append() 是在主线程中完成的。
    • 好的。在您的完成闭包中,您是否使用 self 关键字访问结果:self.results? Xcode 应该要求你这样做。此外,您确定包含该数组的 ViewController 仍然存在吗?您可以使用仪器分配工具来找出答案。您可能已经在另一个 ViewController 的视图中手动插入了 SubViewController 视图,并且没有对保持它活动的 SubViewController 的引用。
    猜你喜欢
    • 1970-01-01
    • 2015-03-13
    • 2016-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-29
    相关资源
    最近更新 更多