2015-07-22 10 views
8

Ho letto che quando viene eseguito un blocco come questo:weakSelf (il bene), strongSelf (il cattivo) e blocca (il brutto)

__weak typeof(self) weakSelf = self; 
[self doSomethingInBackgroundWithBlock:^{ 
     [weakSelf doSomethingInBlock]; 
     // weakSelf could possibly be nil before reaching this point 
     [weakSelf doSomethingElseInBlock]; 
}]; 

dovrebbe essere fatto in questo modo:

__weak typeof(self) weakSelf = self; 
[self doSomethingInBackgroundWithBlock:^{ 
    __strong typeof(weakSelf) strongSelf = weakSelf; 
    if (strongSelf) { 
     [strongSelf doSomethingInBlock]; 
     [strongSelf doSomethingElseInBlock]; 
    } 
}]; 

Quindi voglio replicare una situazione in cui weakSelf ottiene nil nel mezzo di un'esecuzione di blocco.

Così ho creato il seguente codice:

* ViewController *

@interface ViewController() 

@property (strong, nonatomic) MyBlockContainer* blockContainer; 
@end 

@implementation ViewController 

- (IBAction)caseB:(id)sender { 
    self.blockContainer = [[MyBlockContainer alloc] init]; 
    [self.blockContainer createBlockWeakyfy]; 
    [self performBlock]; 
} 


- (IBAction)caseC:(id)sender { 
    self.blockContainer = [[MyBlockContainer alloc] init]; 
    [self.blockContainer createBlockStrongify]; 
    [self performBlock]; 
} 


- (void) performBlock{ 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
     self.blockContainer.myBlock(); 
    }); 
    [NSThread sleepForTimeInterval:1.0f]; 
    self.blockContainer = nil; 
    NSLog(@"Block container reference set to nil"); 
} 
@end 

* MyBlockContainer *

@interface MyBlockContainer : NSObject 

@property (strong) void(^myBlock)(); 

- (void) createBlockWeakyfy; 
- (void) createBlockStrongify; 

@end 

@implementation MyBlockContainer 

- (void) dealloc{ 
    NSLog(@"Block Container Ey I have been dealloc!"); 
} 

- (void) createBlockWeakyfy{ 
    __weak __typeof__(self) weakSelf = self; 
    [self setMyBlock:^() { 
     [weakSelf sayHello]; 
     [NSThread sleepForTimeInterval:5.0f]; 
     [weakSelf sayGoodbye]; 
    }]; 
} 

- (void) createBlockStrongify{ 

    __weak __typeof__(self) weakSelf = self; 
    [self setMyBlock:^() { 
     __typeof__(self) strongSelf = weakSelf; 
     if (strongSelf){ 
      [strongSelf sayHello]; 
      [NSThread sleepForTimeInterval:5.0f]; 
      [strongSelf sayGoodbye]; 
     } 
    }]; 
} 

- (void) sayHello{ 
    NSLog(@"HELLO!!!"); 
} 

- (void) sayGoodbye{ 
    NSLog(@"BYE!!!"); 
} 


@end 

Quindi mi aspettavo che createBlockWeakyfy genererà lo scenario Volevo replicare ma non sono riuscito a farlo.

L'uscita è la stessa per createBlockWeakyfy e createBlockStrongify

HELLO!!! 
Block container reference set to nil 
BYE!!! 
Block Container Ey I have been dealloc! 

Qualcuno può dirmi quello che sto facendo male?

+0

Prova ad aggiungere '[[NSGarbageCollector defaultCollector] collectIfNeeded];' dopo averlo impostato su nil per forzare il GC. Potrebbe o potrebbe non fare nulla. –

+0

Forse correlato ... http://stackoverflow.com/questions/24093802/objective-c-block-lifetime-arc – CrimsonChris

risposta

3

Il blocco dispatch_async crea un riferimento forte. Quando quel blocco accede al tuo MyBlockContainer per ottenere la sua proprietà myBlock, crea un forte riferimento ad esso per la vita di quel blocco.

Se si modifica il codice a questo:

__weak void (^block)() = self.blockContainer.myBlock; 

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
    block(); 
}); 

Dovreste vedere i risultati che si aspettano.

+0

Grazie per la risposta! – agy

Problemi correlati