Ios 保持对使用闭包[Swift]的本地对象的强引用

Ios 保持对使用闭包[Swift]的本地对象的强引用,ios,swift,memory,closures,strong-parameters,Ios,Swift,Memory,Closures,Strong Parameters,我有一个关于保持对使用闭包的本地对象的强引用的问题。 我有下面的代码,其中对象B使用一个闭包类型为a的本地对象的方法。 对象A中的方法使用异步操作执行一些网络任务,然后将闭包返回给对象b。 由于对象A在B中的方法中是本地的,并且由于我在对象A异步任务中使用了[weak self](以防止保留循环),所以对象被释放 我应该在下面的代码中更改什么,以确保只有在完成闭包时才会释放本地对象 这是重要代码的一部分: class A { var restAPI: RestAPI? func

我有一个关于保持对使用闭包的本地对象的强引用的问题。 我有下面的代码,其中对象B使用一个闭包类型为a的本地对象的方法。 对象A中的方法使用异步操作执行一些网络任务,然后将闭包返回给对象b。 由于对象A在B中的方法中是本地的,并且由于我在对象A异步任务中使用了[weak self](以防止保留循环),所以对象被释放

我应该在下面的代码中更改什么,以确保只有在完成闭包时才会释放本地对象

这是重要代码的一部分:

class A {
    var restAPI: RestAPI?

    func fetchNews(completion: (_ json: [String:Any])->()) {
        // .....
        self.restAPI.fetch(url: url, results: { [weak self] (json) in // 
            completion(json)
        })
        // .....
    }
}

class B {
    // .... 
    // ... call to updateNews()

    func updateNews() {
        let aFetcher: A() 
        aFetcher.fetchNews(completion : { 
            // <<<< // aFetcher gets released and closue never called
            // parse...
        }
    }
}
A类{
var restAPI:restAPI?
func fetchNews(完成:(json:[String:Any])->()){
// .....
self.restAPI.fetch(url:url,结果:{[weak self](json)in//
完成(json)
})
// .....
}
}
B类{
// .... 
//…调用updateNews()
func updateNews(){
让阿费彻:A()
aFetcher.fetchNews(完成:{
//您将aFetcher声明为func updateNews()范围内的let
当updateNews()的作用域结束时,将释放一个蚀刻器。 您的内部获取函数中有[弱自我]。 在此阶段,将释放一个Etcher,因为updateNews()完成其执行,并且没有对此对象的强引用

您只需要将变量aFetcher添加到类B中,以确保对aFetcher有强引用

在func updateNews()的作用域中将aFetcher声明为let
当updateNews()的作用域结束时,将释放一个蚀刻器。 您的内部获取函数中有[弱自我]。 在此阶段,将释放一个Etcher,因为updateNews()完成其执行,并且没有对此对象的强引用

您只需要将变量aFetcher添加到类B中,以确保对aFetcher有强引用


你需要在班级的顶层有一个强有力的参考

但是,为了不永久保留引用,并可靠地保留和释放引用,请在
B类
中添加可选存储属性,并在完成关闭时将其设置为
nil

class B {

    var fetcher : A?

    // MARK: - Public
    func updateNews() {
        fetcher = A()
        fetcher!.fetchNews(completion : { [unowned self] in
            // parse...

            self.fetcher = nil
        }
    }
}

你需要在班级的顶层有一个强有力的参考

但是,为了不永久保留引用,并可靠地保留和释放引用,请在
B类
中添加可选存储属性,并在完成关闭时将其设置为
nil

class B {

    var fetcher : A?

    // MARK: - Public
    func updateNews() {
        fetcher = A()
        fetcher!.fetchNews(completion : { [unowned self] in
            // parse...

            self.fetcher = nil
        }
    }
}

谢谢大家,但是如果我想让变量是局部的而不是类属性呢?那我该怎么办?事实上,它不是类属性,而是实例属性。然而,你需要一个对类AIMHO的实例的强引用(不能是局部的),这不是一个好的模式。它还带有一个微妙的问题:如果完成处理程序保留对对象的最后一个强引用,当完成处理程序执行时,它将在此线程上被销毁。由于创建它的线程(其中
updateNews()
将被调用)可能是另一个线程,这将产生数据争用。为了使它工作,您需要“线程限制”(另一个错误模式),但无论如何,你不需要类B中的var fetcher。谢谢各位,但如果我希望变量是局部的而不是类属性呢?那我该怎么办?实际上它不是类属性,而是实例属性。不过,你需要一个强引用(不能是局部的)来引用类AIMHO的实例,这不是一个好方法它还存在一个微妙的问题:如果完成处理程序保留对对象的最后一个强引用,那么当完成处理程序执行时,它将在此线程上被销毁。因为创建它的线程(其中
updateNews()
将被调用)可能是另一个问题,这会产生一场数据竞争。为了让它正常工作,你需要“线程限制”(另一种糟糕的模式),但你无论如何也不需要类B中的var fetcher。实际上,这个问题没有好的解决方案。主要问题是线程安全。你最好定义并初始化变量
restAPI
“外面“在必须超过B类实例的A类实例中。您还需要在创建它的同一线程上销毁它。最好在A类实例中再次执行此操作。实际上,此问题没有很好的解决方案。主要问题是线程安全。最好定义并初始化变量
restAPI
类实例中的“外部”必须超过类B实例。您还需要在创建它的同一线程上销毁它。最好在类A实例中再次执行此操作。