菜鸟教程小白 发表于 2022-12-12 18:02:33

ios - block 不捕获 self


                                            <p><p>我想尝试了解 block 捕获逻辑,但现在我对此有疑问。我有 <code>MeRequest</code> 和 <code>NSNumber</code> 属性。</p>

<pre><code>@property (nonatomic) MeRequest *request;
@property (nonatomic) NSNumber *number;
</code></pre>

<p>然后,在 <code>viewDidLoad</code> 我调用请求方法</p>

<pre><code>self.request = [ init];
[self.request meInfoSuccessBlock:^(NSDictionary *response) {

} failureBlock:^(Error *error) {
    self.number = @5;
}];

- (void)meInfoSuccessBlock:(RequestSuccessBlock)success failureBlock:(RequestFailureBlock)failure {

    self.method = @&#34;GET&#34;;
    self.parameters = @{};
    [self performWithCompletion:^(id responseObject) {
      NSDictionary *response = (NSDictionary *)responseObject;
      if (success) {
            success(response);
      }
    } onFailure:^(Error *error) {
      if (failure) {
            failure(error);
      }
    }];
}

- (AFHTTPRequestOperation *)performWithCompletion:(void(^)(id responseObject))completion
                                        onFailure:(void(^)(Error *error))failure {

    NSURLRequest *request = [ requestWithMethod:self.method path:self.path parameters:self.parameters];

    if (_operation) {
      ;
    }

    _operation = [ HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject) {
      _operation = nil;
      dispatch_semaphore_signal(_semaphore);

      if (completion) {
            completion(responseObject);
      }
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
      _operation = nil;
      dispatch_semaphore_signal(_semaphore);
      if (failure) {
            failure(_error);
      }
    }];

    ;
    return _operation;
}
</code></pre>

<p>并且在 <code>failureBlock</code> 我将数字设置为属性。当我离开此 Controller 时,我在控制台中看到了 dealloc 消息,该 Controller 已被释放。</p>

<pre><code>- (void)dealloc {
    NSLog(@&#34;%s&#34;, __PRETTY_FUNCTION__);
}
</code></pre>

<p>为什么 Controller 会解除分配?我不使用对 <code>self</code></p> 的弱引用</p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>要明确知道,您必须发布 <code>MeRequest</code> 类的实现。 </p>

<p>在不知不觉中,这是一个有根据的猜测。</p>

<p>通过 <code>meInfoSuccessBlock:failureBlock:</code> 传递给 <code>self.request</code> 的 block 在事务完成时可能会被清空。也就是说,它可能是这样的:</p>

<pre><code>- (void)meInfoSuccessBlock:... sB failureBlock:... fB {
   _sB = sB; // put ref in ivar
   _fB = fB; // because this is probably broken up across methods
   dispatch_async(_queue, ^{
      .... think hard ...
      if (success) _sB(...);
      else _fB(...);
      _sB = nil;
      _fB = nil;
   };
}
</code></pre>

<p>所以,首先,您不是在创建直接循环引用,而是——也许——<code>self -> request -> _sB -> self</code> 的循环引用。其次,通过在计算完成并进行回调后分配 <code>_sB = nil</code> 来打破循环。</p>

<hr/>

<p>或者,在您的情况下,您对仅在范围内存在的 block 具有强引用。 IE。有点像这样:</p>

<pre><code>- (void)meInfoSuccessBlock:... sB failureBlock:... fB {
   dispatch_async(_queue, ^{
      .... think hard ...
      if (success) sB(...);
      else fB(...);
      // when the block finishes execution, fB and sB will be released
   };
   // when execution gets to here, the block above is the only strong references to sB and fB
}
</code></pre>

<p>也就是说,当您有一个保留循环时,该循环中的一个引用明确地与回调 block 的生命周期相关联,并且由于这些引用仅在回调完成之前存在,它们会被销毁并破坏循环。</p></p>
                                   
                                                <p style="font-size: 20px;">关于ios -block 不捕获 self ,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/34555049/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/34555049/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: ios - block 不捕获 self