2015-07-22 5 views
8

Ich habe gelesen, dass, wenn ein Block wie folgt ausgeführt:weakSelf (das gute), strongSelf (das schlechte) und Blöcke (die hässliche)

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

es sollte auf diese Weise geschehen:

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

Also ich möchte eine Situation replizieren, in der weakSelf mitten in einer Blockausführung Null bekommt.

So habe ich den folgenden Code erstellt:

* 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 

Damit ich erwartete createBlockWeakyfy das Szenario generieren Ich wollte replizieren, aber ich habe es nicht geschafft.

Der Ausgang ist für createBlockWeakyfy und createBlockStrongify

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

Jemand kann mir sagen, was ich falsch mache?

+0

Versuchen Sie, '[[NSGarbageCollector defaultCollector] collectIfNeeded];' hinzuzufügen, nachdem Sie es auf null gesetzt haben, um den GC zu erzwingen. Macht oder macht vielleicht gar nichts. –

+0

Möglicherweise verwandt ... http://stackoverflow.com/questions/24093802/objective-c-block-lifetime-arc – CrimsonChris

Antwort

3

Ihr dispatch_async Block ist eine starke Referenz. Wenn dieser Block auf MyBlockContainer zugreift, um seine Eigenschaft myBlock zu erhalten, erstellt er einen starken Verweis darauf für die Lebensdauer dieses Blocks.

Wenn Sie Ihren Code dies zu ändern:

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

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

Sie sollten die Ergebnisse sehen Sie erwarten.

+0

Vielen Dank für Ihre Antwort! – agy

Verwandte Themen