【问题标题】:Swift Closures [unowned singleton]Swift 闭包 [无主单例]
【发布时间】:2016-07-12 08:31:14
【问题描述】:

在 Swift 中遇到递归内存泄漏问题,其中一个单例在另一个单例的闭包内被调用。

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 发现,Core Data Manager 有一个问题……这种架构绝对没有问题。

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)
    }
}

【问题讨论】:

  • 我们如何将单例定义为“泄漏”?就其性质而言,它们永远不会被释放......
  • 是的,好点。要定义它,调用内部单例方法会使内存呈指数级增长,直到崩溃。即使方法为空。
  • 并且 CDM 单例在任何时候都不会调用您的 NetworkManager?您可以为调试做的事情是查看堆栈跟踪,看看整个递归恶作剧是关于什么的。
  • 只是为了后代 CDM 总是 NetworkManager 的下风。

标签: swift memory-management closures


【解决方案1】:

可能值得看看你如何定义你的单例。作为一般规则,我会这样做:

class MySingleton {
    static let sharedInstance = MySingleton() //The singleton
}

这会留下干净的堆栈跟踪并且不会造成混淆。以供参考: http://krakendev.io/blog/the-right-way-to-write-a-singleton

编辑:

该错误似乎在 BFSCoreDataManager 类中。 在observerContext: 中,您忘记听上下文。函数应该是:

func observeContext(context:NSManagedObjectContext) {

    NSNotificationCenter.defaultCenter().addObserver(
        self,
        selector:"mergeChangesFromNotification:",
        name: NSManagedObjectContextDidSaveNotification,
        object: context) //context instead of nil
}

【讨论】:

  • 如果我学究,应该是静态的。
  • 再次为后人定义,都是这样定义的。
  • 再次感谢Quantaliinuxite
【解决方案2】:

不知道这样能不能解决内存管理问题,但是在捕获列表中包含单例的方法是这样的:

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 { ... }

【讨论】:

  • 好的,太好了...我会看看添加它,看看我的进展如何。
  • 谢谢,知道了很方便
猜你喜欢
  • 2017-08-12
  • 2015-03-11
  • 1970-01-01
  • 1970-01-01
  • 2017-05-19
  • 1970-01-01
  • 1970-01-01
  • 2018-05-02
  • 1970-01-01
相关资源
最近更新 更多