在网络呼叫的通知与回调关闭之间进行选择时,是否关注内存?

时间:2016-04-25 03:06:56

标签: ios swift uiviewcontroller delegates nsnotificationcenter

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

假设自定义视图控制器内部是一个函数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

选项1似乎是可取的,因为人们提醒NSNotification的所有原因(例如,编译器检查,可追溯性),但不使用回调会产生潜在的问题,CustomViewController被不必要地保留,因此可能会造成内存问题?

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

2 个答案:

答案 0 :(得分:0)

我总是选择选项1 你只需要记住使用[weak self]或者你需要'弱化'以避免内存问题。

真实世界的例子:

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 :(得分:0)

在这种情况下,我代表关闭。为了避免不必要的保留,您只需要确保关闭具有正确的capture list定义。