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。不过,您似乎被其他一些答案误导了:内存管理和同步是正交的概念,它们有自己的问题根源。