2016-07-29 15 views
0

Ich habe diesen Code und was ich versuche zu tun ist, sich selbst lebendig in dem Block zu halten, dass es auf dem Hauptthread ausgeführt wird. Das Ergebnis ist zufällig und druckt manchmal null.iOS - GCD und __starke Referenz

- (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); 

} 

Dieser Code funktioniert:

- (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); 

} 

Gibt es eine Möglichkeit, das zweite Stück Code zu konvertieren mit dem Aufbau des ersten Stückes Code zu arbeiten? Ich habe viele Variationen ausprobiert, aber es ist immer zufällig. Kann ich irgendwie versichern, dass der self.postGCDBlock kein self to nil haben wird?

Update: Eigenschaftsdeklaration:

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

Wie sieht die Eigenschaftsdeklaration im View Controller aus? –

+0

Die Antwort wurde aktualisiert! – BlackM

Antwort

3

Ich denke, Ihr Problem mit dieser Linie liegt (ich mit diesem Code den Fehlerfall nicht reproduzieren kann):

dispatch_async(dispatch_get_main_queue(),strongSelf.postGCDBlock); 

An diesem Punkt in Ihrem addObjectsBlockstrongSelf enthält einen Verweis auf self, der jedoch endet, wenn Sie den Bereich dieses Blocks verlassen. dispatch_async kopiert die postGCDBlock, aber dieser Block enthält keine starke Referenz auf self.

dispatch_async Um einen starken Bezug auf self zu halten, würden Sie so etwas wie dies tun wollen:

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

strongSelf im Block Wrapping dispatch_async verursachen strongSelf (und damit self) lange genug zu halten für es zu rufen postGCDBlock.

+0

Das hat das Problem gelöst. Ich dachte, dass durch die Verwendung von 'strongSelf.postGCDBlock' als Parameter der strongSelf beibehalten würde – BlackM