Swift Closes[无主单身汉]
Swift中存在递归内存泄漏问题,其中一个单例在另一个单例的闭包内被调用Swift Closes[无主单身汉],swift,memory-management,closures,Swift,Memory Management,Closures,Swift中存在递归内存泄漏问题,其中一个单例在另一个单例的闭包内被调用 NetworkManager.sharedInstance.doThingWithCompletion(urlString) { [unowned self] (complete) -> Void in if complete == true { if self.fetchedResultsController.fetchedObjects?.count > 0 {
NetworkManager.sharedInstance.doThingWithCompletion(urlString) { [unowned self] (complete) -> Void in
if complete == true {
if self.fetchedResultsController.fetchedObjects?.count > 0 {
CoreDataManager.sharedInstance.save(self.dictionary, completion: { (complete) -> Void in
})
}
}
}
如何将未拥有的单例添加到捕获列表中?我应该这样做吗
编辑
Quantaliinuxite发现核心数据管理器出现问题。。。这种架构绝对没有问题
static let sharedInstance = BFSCoreDataManager()
deinit {
NSNotificationCenter.defaultCenter().removeObserver(self)
}
// MARK: - Saving
func observeContext(context:NSManagedObjectContext) {
NSNotificationCenter.defaultCenter().addObserver(
self,
selector:"mergeChangesFromNotification:",
name: NSManagedObjectContextDidSaveNotification,
object: nil) // ** PROBLEM WAS HERE **
}
func mergeChangesFromNotification(notification:NSNotification) {
dispatch_async(dispatch_get_main_queue()) {
self.managedObjectContext.mergeChangesFromContextDidSaveNotification(notification)
}
}
也许值得看看你是如何定义你的单身汉的。一般来说,我会这样做:
class MySingleton {
static let sharedInstance = MySingleton() //The singleton
}
NetworkManager.sharedInstance.doThingWithCompletion(urlString) {
[unowned self, unowned dataManager = CoreDataManager.sharedInstance] (complete) -> Void in
if complete {
if self.fetchedResultsController.fetchedObjects?.count > 0 {
dataManager.save(self.dictionary, completion: { (complete) -> Void in
})
}
}
}
这会留下一个干净的堆栈跟踪,并且不会引起混淆。供参考:
编辑:
该bug似乎位于BFSCoreDataManager
类中。
在observerContext:
中,您忘记了听上下文。该功能应为:
func observeContext(context:NSManagedObjectContext) {
NSNotificationCenter.defaultCenter().addObserver(
self,
selector:"mergeChangesFromNotification:",
name: NSManagedObjectContextDidSaveNotification,
object: context) //context instead of nil
}
我不知道这是否能解决内存管理问题,但将单例包含在捕获列表中的方法如下:
class MySingleton {
static let sharedInstance = MySingleton() //The singleton
}
NetworkManager.sharedInstance.doThingWithCompletion(urlString) {
[unowned self, unowned dataManager = CoreDataManager.sharedInstance] (complete) -> Void in
if complete {
if self.fetchedResultsController.fetchedObjects?.count > 0 {
dataManager.save(self.dictionary, completion: { (complete) -> Void in
})
}
}
}
还要注意,当检查
Bool
值时,不需要将其与true
进行比较if complete==true{…}
可以缩短为if complete{…}
我们如何准确地将单例定义为“泄漏”?根据他们的本性,他们永远不会被释放…是的,很好。。为了定义它,调用内部单例方法会使内存呈指数级增长,直到崩溃。即使方法为空,CDM单例也不会在任何时候调用NetworkManager?您可以为调试做一些事情,看看堆栈跟踪,看看整个递归shenanigan是关于什么的。对于子孙后代来说,CDM总是NetworkManager的下风。让我们来看看。如果我学究的话,应该是静态的。对于子孙后代来说,两者都是这样定义的。再次感谢Quantalinuxiteok,这太棒了。。。我会看看如何添加这些内容,看看效果如何。谢谢你的帮助,知道这些很方便