关于应该把[无主自我]放在哪里的困惑

时间:2018-02-11 21:53:35

标签: swift strong-references unowned-references

我有一个保留周期,所以我的viewcontroller的deinit将不会被调用,我正在尝试解决这个问题,我添加[unowned self],但是我不太确定在我的情况下将无主的放在哪里:< / p>

案例1

public class QueryStringHandler : IHttpHandler 
{
    public void ProcessRequest (HttpContext context) 
    {

 //set the content type, you can either return plain text, html text, or json or other type    
        context.Response.ContentType = "text/plain";

        //deserialize the object
        UserInfo objUser = Deserialize<HandlerModel>(context);

        //now we print out the value, we check if it is null or not
        if (objUser != null) {
            context.Response.Write("Go the Objects");
        } else {
            context.Response.Write("Sorry something goes wrong.");
        }
}

public T Deserialize<T>(HttpContext context) {
        //read the json string
        string jsonData = new StreamReader(context.Request.InputStream).ReadToEnd();

        //cast to specified objectType
        var obj = (T)new JavaScriptSerializer().Deserialize<T>(jsonData);

        //return the object
        return obj;
    }
}

案例2

class YADetailiViewController: UIViewController {
 var subscription: Subscription<YAEvent>?

 override func viewDidLoad() {
    super.viewDidLoad()
    if let query = self.event.subscribeQuery() {
        self.subscription = Client.shared.subscribe(query)
        self.subscription?.handle(Event.updated) {
            query, object in
            DispatchQueue.main.async {
                [unowned self] in// Put unowned here won't break the cycle, but it does compile and run 
                self.pageViewLabel.text = String(object.pageViews) + " VIEW" + ((object.pageViews > 1) ? "S" : "")
            }
        }
    }
 }
}

我很好奇这两种情况之间的差异是什么,为什么一种有效而另一种无效

1 个答案:

答案 0 :(得分:1)

确实,正如@matt正确提到的那样,问题与捕获self的时间有关。实际上,此代码self被捕获两次:

  • 当外部闭包传递给handle方法
  • 当内部闭包传递给async方法时(在handle闭包执行期间)

外部封闭物需要self将它传递到内部封闭物,否则内部封闭物将无法捕获它。

性质或保留周期如下:self(YADetailiViewController) - &gt; subscription - &gt;闭包(handle参数) - &gt; self。为了打破这个循环,它足以不在该(外部)闭包中保留self。这就是第二个代码示例有效的原因。

self的第二次捕获(在内部闭包中)仅在执行外部闭包时发生并持续到执行async块为止 - 通常它的时间很短。

在第一个代码示例中,您没有打破循环。 self的第二次捕获不会发生,但第一次捕获(导致你的周期)仍然存在。

如果在视图控制器已被删除/释放时仍然可以调用handle闭包,那么根据@AdrianBobrowski的建议,您应该使用weak而不是unowned来防止可能的崩溃

相关问题