【问题标题】:Weak and strong self usage, blocks memory management强弱自用,阻塞内存管理
【发布时间】:2014-07-17 13:59:22
【问题描述】:

关于所有这些弱者和强者有很多问题,但我希望你们看看我的具体例子:

- (void)getItemsWithCompletionHandler:(void (^)(NSArray*items))completionHandler {
 __weak __typeof__(self) weakSelf = self;
 [self doWorkWithCompletionHandler:^(Response *response) {
     // this completion is not on main thread
     dispatch_async(dispatch_get_main_queue(), ^{
         ...
         [weakSelf doAnotherWorkWithCompletionHandler:^(Response *response) {
             // this completions is not on main thread either
             dispatch_async(dispatch_get_main_queue(), ^{
                 __typeof__(self) strongSelf = weakSelf;
                 NSArray *itemsIds = [strongSelf doWorkOnMainThread1];
                 NSArray *items = [strongSelf doWorkOnMainThread2];
                 completionHandler(items);
             });
         }]; 
     });
 }];
}

这里的一切都正确吗?也欢迎您提出重构建议

【问题讨论】:

  • 这个问题在Codereview上排序可能会更好
  • 在外部本地范围内声明 itemsIdsitems 有什么意义?在异步操作中分配这两个变量时,范围并不存在。
  • 是什么让你觉得这里需要弱引用?
  • 问题主要是关于块内存管理而不是重构!

标签: ios objective-c memory-management objective-c-blocks


【解决方案1】:

如果你打开所有警告,那么你会收到一个警告

[weakSelf doAnotherWorkWithCompletionHandler... ];

您不应该向弱对象发送消息。当被调用的方法正在运行时,弱对象可能会消失。将弱对象存储到强对象中,结果要么为零,要么不存在。如果你再打电话

[strongSelf doAnotherWorkWithCompletionHandler... ];

您知道 strongSelf == nil 并且没有任何反应,或者 strongSelf 在方法执行时是并且不保持为 nil。

【讨论】:

    【解决方案2】:

    你应该检查completionHandler是否不为NULL,然后调用它。

    if (completionHandler) {
      completionHandler(items);
    }
    

    否则如果completionHandler为NULL你会崩溃


    如果您在任何时候都想致电completionHandler(items),您也可以重新考虑是否要致电self == nil。我这么说,是因为有一点点不一致。
    排队

    [weakSelf doAnotherWorkWithCompletionHandler:^(Response *response) {
    

    如果weakSelf 已经为nil,那么它的completionHandler 将不会被调用,结果completionHandler(items) 也不会被调用。

    但是在这里:

    __typeof__(self) strongSelf = weakSelf;
    NSArray *itemsIds = [strongSelf doWorkOnMainThread1];
    NSArray *items = [strongSelf doWorkOnMainThread2];
    completionHandler(items);
    

    如果self == nil 那么completionHandler 实际上会被调用。

    当然,我看不到全貌,也许这完全无关紧要,但您可能需要考虑一下。

    更进一步,我假设您宁愿在每个场景中调用completionHandler,即使self == nil 在任何时候。或者添加一个错误参数以防出现任何问题。


    如果你想超级迂腐,你可能想把 __weak 放在类型之后,这样:

    __typeof__(self) __weak weakSelf = self;
    

    这是首选方式:https://developer.apple.com/library/ios/releasenotes/objectivec/rn-transitioningtoarc/Introduction/Introduction.html#//apple_ref/doc/uid/TP40011226-CH1-SW4(查找“您应该正确装饰变量。”)

    【讨论】:

      猜你喜欢
      • 2015-11-01
      • 1970-01-01
      • 2014-02-12
      • 2011-04-15
      • 1970-01-01
      • 2016-03-25
      • 2013-02-14
      • 2014-03-16
      • 2017-09-08
      相关资源
      最近更新 更多