Ios 在网络调用的通知和回调关闭之间进行选择时,是否考虑内存问题?

Ios 在网络调用的通知和回调关闭之间进行选择时,是否考虑内存问题?,ios,swift,uiviewcontroller,delegates,nsnotificationcenter,Ios,Swift,Uiviewcontroller,Delegates,Nsnotificationcenter,许多帖子似乎建议在尝试同步函数时不要通知,但也有其他帖子警告不要关闭回调,因为可能会无意中保留对象并导致内存问题 假设在自定义视图控制器中有一个函数,foo,它使用Bar类从服务器获取数据 class CustomViewController : UIViewController { function foo() { // Do other stuff // Use Bar to get data from server Bar.getServ

许多帖子似乎建议在尝试同步函数时不要通知,但也有其他帖子警告不要关闭回调,因为可能会无意中保留对象并导致内存问题

假设在自定义视图控制器中有一个函数,
foo
,它使用
Bar
类从服务器获取数据

class CustomViewController : UIViewController {

    function foo() {
       // Do other stuff
       // Use Bar to get data from server
       Bar.getServerData()
     }

}
选项1:定义
getServerData
以接受回调。将回调定义为
CustomViewController
中的闭包

选项2:使用
NSNotifications
而不是回调。在
getServerData
内部,当服务器返回数据时发布
NSNotification
,并确保注册了
CustomViewController
通知

出于人们对
NSNotification
(例如编译器检查、可跟踪性)的所有警告理由,选项1似乎是可取的,但使用回调是否会在不必要地保留
CustomViewController
的情况下产生潜在问题,从而可能产生内存问题


如果是这样,使用回调而不是闭包是否是降低风险的正确方法?换句话说,在
CustomViewController
中定义一个函数,其签名与
getServerData
回调匹配,并将指向该函数的指针传递给
getServerData

我总是使用选项1您只需要记住使用
[弱自我]
或任何需要“加密”以避免内存问题的内容

现实世界的例子:

filterRepository.getFiltersForType(filterType) { [weak self] (categories)  in
    guard let strongSelf = self, categories = categories else { return }
    strongSelf.dataSource           = categories
    strongSelf.filteredDataSource   = strongSelf.dataSource
    strongSelf.tableView?.reloadData()
}
因此,在这个例子中,您可以看到我将对
self
的引用传递给完成闭包,但作为
weak
引用。然后我使用
guard
语句和展开
weak
值检查对象是否仍然存在-如果它尚未释放

具有完成关闭的网络呼叫的定义:

class func getFiltersForType(type: FilterType, callback: ([FilterCategory]?) -> ()) {
    connection.getFiltersCategories(type.id).response { (json, error) in
        if let data = json {
            callback(data.arrayValue.map { FilterCategory(attributes: $0) } )
        } else {
            callback(nil)
        }
    }
}

我总是选择选项1你只需要记住使用
[弱自我]
或任何你需要“弱自我”的东西,以避免内存问题

现实世界的例子:

filterRepository.getFiltersForType(filterType) { [weak self] (categories)  in
    guard let strongSelf = self, categories = categories else { return }
    strongSelf.dataSource           = categories
    strongSelf.filteredDataSource   = strongSelf.dataSource
    strongSelf.tableView?.reloadData()
}
因此,在这个例子中,您可以看到我将对
self
的引用传递给完成闭包,但作为
weak
引用。然后我使用
guard
语句和展开
weak
值检查对象是否仍然存在-如果它尚未释放

具有完成关闭的网络呼叫的定义:

class func getFiltersForType(type: FilterType, callback: ([FilterCategory]?) -> ()) {
    connection.getFiltersCategories(type.id).response { (json, error) in
        if let data = json {
            callback(data.arrayValue.map { FilterCategory(attributes: $0) } )
        } else {
            callback(nil)
        }
    }
}

在那种情况下,我支持闭包。为了避免不必要的保留,您只需确保已正确定义闭包。

在这种情况下,我支持闭包。为了避免不必要的保留,您只需要确保正确定义了闭包。

弱自我的需求往往被夸大了。您需要有一个循环引用来生成保留周期,从而产生内存泄漏。在您的示例中,闭包捕获了
self
,但是
FilterRepository
没有将闭包捕获到强属性中,因此只要
getFiltersForType
调用闭包,它对闭包的保持就会被释放。这意味着释放闭包,释放调用对象(
self
)上的闭包,因此所有内容都被清除nicely@Paulw11感谢您的评论,我复制代码时出错,
filterRepository
是我的数据源对象中的一个属性,因此,
filterRepository
无关-只有在
getFiltersForType
中执行类似于
self.closureProperty=callback
的操作时,才有可能发生泄漏,一般来说,这并不正确。也就是说,有两种有效的用例,您有时需要
,有时需要
。对
弱自我
的需求往往被夸大了。您需要有一个循环引用来生成保留周期,从而产生内存泄漏。在您的示例中,闭包捕获了
self
,但是
FilterRepository
没有将闭包捕获到强属性中,因此只要
getFiltersForType
调用闭包,它对闭包的保持就会被释放。这意味着释放闭包,释放调用对象(
self
)上的闭包,因此所有内容都被清除nicely@Paulw11感谢您的评论,我复制代码时出错,
filterRepository
是我的数据源对象中的一个属性,因此,
filterRepository
无关-只有在
getFiltersForType
中执行类似于
self.closureProperty=callback
的操作时,才有可能发生泄漏,一般来说,这并不正确。也就是说,有两种有效的用例,您有时需要
,有时需要
。选项1更简洁、更容易理解,也更容易获得正确答案。因此,首选方案1。不过,你似乎被其他一些答案误导了:内存管理和同步是正交的概念,它们有自己的问题根源。嗯,这两种方法都是有效的。选项1更简洁、更容易理解,也更容易获得正确答案。因此,首选方案1。不过,您似乎被其他一些答案误导了:内存管理和同步是正交的概念,它们有自己的问题根源。