在Swift中混淆deinit行为

时间:2016-01-07 11:06:33

标签: ios swift networking memory-management nsurlsession

在我的代码中,我已经实现了APIManager

这两个类中的ArticleAPIManager及其子类deinit { print("deinit className") }

我试图查看以下代码是否会立即解除分配:

ArticleManager().fetchArticlesWithParameters(ArticlesParameters.defaultParameters()) { (articlesData, error) -> Void in

        print("Done")
    }

控制台显示以下内容:

deinit ArticleAPIManager

deinit APIManager

Done

如果之前已取消分配管理器,完成处理程序如何仍然存在?

func fetchArticleWithParameters<R:xxxProtocol>(parameters:R , completionHandler: ArticleCompletionHandler) {

        if let articleURLWithParamsURL = params.endPointURL() {

        fetchURL(articleURLWithParameters) { (jsonData, error) -> Void in

            guard let jsonData = jsonData else {
                completionHandler(articlesData: nil, error: error)
                return
            }

            if let rawArray = jsonData["data"] as? [APIJSON] {
                let articles = APIGenericResponceParser<T>().parseArray(rawArray)

                completionHandler(articlesData: articles, error:nil)

            }

            }//fetchURL
        }//iflet-NSURL

}

2 个答案:

答案 0 :(得分:1)

试图通过一个简单的例子来解释:

class Test {

    let someProperty = "Very nice property"

    func printWithDelay() {

        //Prints done after 3 seconds
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(NSEC_PER_SEC * 3)), dispatch_get_main_queue()) {
            print("Done")
        }
    }

    deinit {
        print("\(self) is deinited")
    }
}

并使用此代码:

var test: Test? = Test()
test?.printWithDelay()
test = nil

在此示例中,dispatch_after块不引用任何 Test属性所以它不保留,这就是为什么你会看到

Test is deinited
Done
在控制台中

,就像在你的例子中一样。但是,如果您在someProperty中打印printWithDelay,例如:

func printWithDelay() {

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(NSEC_PER_SEC * 3)), dispatch_get_main_queue()) {
        print(self.someProperty)
    }
}

然后你会看到

Very nice property
Test is deinited

在控制台中,因为dispatch_after的块保留self并且在块执行之前不会让它被删除。

答案 1 :(得分:0)

闭包是Swift中的引用类型。您可以像其他任何“常用”对象一样将它们从一个地方传递到另一个地方。

来自documentation

  

每当你为一个常量或一个变量赋一个函数或一个闭包时,你实际上是将该常量或变量设置为函数或闭包的引用 ...这也意味着如果你为两个不同的常量或变量分配一个闭包,这些常量或变量都将引用相同的闭包:

在您的情况下,您可以completionHandler并将其传递给fetchURL(通过endPointURL),然后由fetchURL捕获并保持活跃,即使{的对象为{通过它的{1}}已经死了。完成提取后,将执行完成处理程序。在您的情况下,它在ArticleAPIManager的对象被取消初始化之后就已经发生了。