2016-07-29 2 views
0

私はこのコードを持っていますが、私がしようとしているのは、メインスレッド上で実行されるブロック内で自己を生かし続けることです。結果は一種のランダムなもので、時にはヌルを出力することもあります。iOS - GCDと__strongリファレンス

- (void)viewDidLoad { 
    [super viewDidLoad]; 
    // Do any additional setup after loading the view. 
    self.proArray = [[NSMutableArray alloc]init]; 

    GCDVC2* __weak weakSelf = self; 

    self.postGCDBlock = ^{ 

     GCDVC2* __strong strongSelf2 = weakSelf; 

     [strongSelf2.proArray removeObject:@"3"]; 
     NSLog(@"%@",strongSelf2.proArray); 
     [strongSelf2.activityIndicator stopAnimating]; 
    }; 

    self.addObjectsBlock = ^{ 

     GCDVC2* __strong strongSelf = weakSelf; 

     [strongSelf.proArray addObject:@"2"]; 
     [strongSelf.proArray addObject:@"3"]; 
     [NSThread sleepForTimeInterval:5]; 

     dispatch_async(dispatch_get_main_queue(),strongSelf.postGCDBlock); 
    }; 

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), self.addObjectsBlock); 

} 

このコードは正常に動作します:

- (void)viewDidLoad { 
    [super viewDidLoad]; 
    // Do any additional setup after loading the view. 
    self.proArray = [[NSMutableArray alloc]init]; 

    GCDVC2* __weak weakSelf = self; 


    //self.postGCDBlock = ; 

    self.addObjectsBlock = ^{ 

     GCDVC2* __strong strongSelf = weakSelf; 

     [strongSelf.proArray addObject:@"2"]; 
     [strongSelf.proArray addObject:@"3"]; 
     [NSThread sleepForTimeInterval:5]; 

     GCDVC2* __weak weakSelf2 = strongSelf; 

     dispatch_async(dispatch_get_main_queue(),^{ 

      GCDVC2* __strong strongSelf = weakSelf2; 

      [strongSelf.proArray removeObject:@"3"]; 
      NSLog(@"%@",strongSelf.proArray); 
      [strongSelf.activityIndicator stopAnimating]; 
     }); 
    }; 

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), self.addObjectsBlock); 

} 

は、コードの最初の部分の構造と連携するためのコードの第二の部分を変換する方法はありますか?私は多くのバリエーションを試しましたが、常にランダムです。どういうわけかself.postGCDBlockがselfにnilを持たないことを保証できますか?

更新: プロパティ宣言:あなたのaddObjectsBlockにこの時点で

dispatch_async(dispatch_get_main_queue(),strongSelf.postGCDBlock); 

typedef void(^CustomBlock)(void); 

@interface GCDVC2() 
@property (weak, nonatomic) IBOutlet UIActivityIndicatorView *activityIndicator; 
@property(nonatomic,strong)NSMutableArray *proArray; 
@property (nonatomic, copy) CustomBlock addObjectsBlock; 
@property (nonatomic, copy) CustomBlock postGCDBlock; 
@end 
+0

プロパティの宣言はどのようにビューコントローラ内に見えますか? –

+0

答えを更新しました! – BlackM

答えて

3

私はあなたの問題は(私はこのコードで失敗ケースを再現することはできません)この行であると思いますstrongSelfselfへの参照を保持していますが、ブロックの有効範囲を離れると終了します。 dispatch_asyncpostGCDBlockをコピーしますが、そのブロックにはselfという強い参照が含まれていません。

dispatch_asyncselfへの強い参照を保持するために取得するには、あなたがこのような何かをしたいと思う:

dispatch_async(dispatch_get_main_queue(), ^{ 
    strongSelf.postGCDBlock(); 
}); 

ブロックでstrongSelfをラップすることは十分な長さのためdispatch_asyncstrongSelf(およびそれによって、self)を保持するようになりますそれはpostGCDBlockと呼ぶべきです。

+0

それが問題を解決しました。私は、 'strongSelf.postGCDBlock'をパラメータとして使用することによって、strongSelf – BlackM