When I have an Objective C instance create a block that needs to refer to the instance, I frequently do so through a weak pointer that won't keep the instance alive and produce a retain cycle, like this:
__weak MyType *const weakSelf = self;
void (^aBlock)() = ^(){
// Do things with weakSelf instead of self.
}
I'd like to have an idiom that prevents me from making use of the strong self in the block. Ideally, when using the idiom, I'd get a compile error if I try to use self in the block instead of weakSelf. A run time error would also be okay.
I've got a solution for this that I don't especially like, but it might provoke a better answer. I'll leave this unanswered in the hope of a better solution arriving.
Here's one way to do it:
// Here's a method definition…
-(void) aMethod
{
// Want to create a block in which its impossible to refer to strong "self".
// Begin a new scope to do this in.
{
// Within this scope, cover the existing "self" with a weak variant.
__weak STWeatherTableViewController const *weakSelf = self;
__weak STWeatherTableViewController const *self = weakSelf;
// Sadly it's _not_ possible to simply do:
// __weak STWeatherTableViewController const *self = self;
// … it gives a warning about initialisation of a variable form its own
// uninitialised value, which makes sense, though you might hope the
// compiler would work out what's going on.
// Make a block that captures the covered self and does something with it.
void (^exampleBlock)() = ^(){ [self lineHeight]; };
exampleBlock();
}
// Now, back in the scope of the original method, "self" is non weak
// again.
[self doSomething];
}
I guess, if you really cared a lot about this, you could use a macro. It would at least abstract the idea and make uses easy to find and notice in code:
#define WEAKEN_SELF(classType) \
__weak classType const *weakSelf = self; \
__weak classType const *self = weakSelf
Or even:
#define WEAKEN_SELF(classType) \
__weak classType const *weakSelfTemporary##__LINE__ = self; __weak classType const *self = weakSelfTemporary##__LINE__;
Which you'd use it like this:
-(void) testMethod
{
// You still need that scope or you cover the original "self".
{
WEAKEN_SELF(STWeatherTableViewController)
void (^exampleBlock)() = ^(){ [self someMethodOrOther]; };
exampleBlock();
}
}
I'm unconvinced it is worth the effort though. Having the compiler warnings is probably good enough and they can presumably be turned in to errors?
Related
every time I have to use a global var or property inside a block like this:
self.save = ^(){
if (isItSaving == NO) {
[self saveMyFile];
}
};
I have to rewrite this like
BOOL *iis = isItSaving;
id myself = self;
self.save = ^(){
if (iis == NO) {
[myself saveMyFile];
}
};
or Xcode will complain "capturing self strongly in this block is likely to lead to a retain cycle...
It complains even about BOOL variables?
Redeclaring everything before a block appears to be a lame solution.
Is this the correctly way? Is there an elegant way?
This stuff is ugly. I am using ARC.
The problem only occurs when referencing self from within the block, explicitly or implicitly. There's no warning emitted when accessing global variables.
In your case you probably accessed a (boolean) ivar. Accessing the ivar implicitly uses self, that's why the compiler is warning you (correctly) about a retain cycle.
The common way to fix the retain cycle is:
typeof(self) __weak weakSelf = self;
self.save = ^() {
typeof(weakSelf) __strong strongSelf = weakSelf;
if (strongSelf != nil && ! strongSelf->isItSaving) {
[strongSelf saveMyFile];
}
};
... and, yes, that's a bit of an ugly part of blocks.
Use __unsafe_unretained typeof(self) weakSelf = self;
In addition to #NikolaiRuhe's response, in your example when declaring the properties
BOOL *iis = isItSaving;
id myself = self;
implies strong references, so use __weak self to prevent the retain cycle. Then you might wonder why you need to declare a __strong reference to weak self within the block, and that's to make sure it doesn't get released during the life of the block, otherwise weakSelf->isItSaving would break if self was released.
How can I avoid this warning in xcode. Here is the code snippet:
[player(AVPlayer object) addPeriodicTimeObserverForInterval:CMTimeMakeWithSeconds(0.1, 100)
queue:nil usingBlock:^(CMTime time) {
current+=1;
if(current==60)
{
min+=(current/60);
current = 0;
}
[timerDisp(UILabel) setText:[NSString stringWithFormat:#"%02d:%02d",min,current]];///warning occurs in this line
}];
The capture of self here is coming in with your implicit property access of self.timerDisp - you can't refer to self or properties on self from within a block that will be strongly retained by self.
You can get around this by creating a weak reference to self before accessing timerDisp inside your block:
__weak typeof(self) weakSelf = self;
[player addPeriodicTimeObserverForInterval:CMTimeMakeWithSeconds(0.1, 100)
queue:nil
usingBlock:^(CMTime time) {
current+=1;
if(current==60)
{
min+=(current/60);
current = 0;
}
[weakSelf.timerDisp setText:[NSString stringWithFormat:#"%02d:%02d",min,current]];
}];
__weak MyClass *self_ = self; // that's enough
self.loadingDidFinishHandler = ^(NSArray *receivedItems, NSError *error){
if (!error) {
[self_ showAlertWithError:error];
} else {
self_.items = [NSArray arrayWithArray:receivedItems];
[self_.tableView reloadData];
}
};
And one very important thing to remember:
do not use instance variables directly in block, use it as a properties of weak object, sample:
self.loadingDidFinishHandler = ^(NSArray *receivedItems, NSError *error){
if (!error) {
[self_ showAlertWithError:error];
} else {
self_.items = [NSArray arrayWithArray:receivedItems];
[_tableView reloadData]; // BAD! IT ALSO WILL BRING YOU TO RETAIN LOOP
}
};
and don't forget to do:
- (void)dealloc {
self.loadingCompletionHandler = NULL;
}
another issue can appear if you will pass weak copy of not retained by anybody object:
MyViewController *vcToGo = [[MyViewCOntroller alloc] init];
__weak MyViewController *vcToGo_ = vcToGo;
self.loadingCompletion = ^{
[vcToGo_ doSomePrecessing];
};
if vcToGo will be deallocated and then this block fired I believe you will get crash with unrecognized selector to a trash which is contains vcToGo_ variable now. Try to control it.
Better version
__strong typeof(self) strongSelf = weakSelf;
Create a strong reference to that weak version as the first line in your block. If self still exists when the block starts to execute and hasn’t fallen back to nil, this line ensures it persists throughout the block’s execution lifetime.
So the whole thing would be like this:
// Establish the weak self reference
__weak typeof(self) weakSelf = self;
[player addPeriodicTimeObserverForInterval:CMTimeMakeWithSeconds(0.1, 100)
queue:nil
usingBlock:^(CMTime time) {
// Establish the strong self reference
__strong typeof(self) strongSelf = weakSelf;
if (strongSelf) {
[strongSelf.timerDisp setText:[NSString stringWithFormat:#"%02d:%02d",min,current]];
} else {
// self doesn't exist
}
}];
I have read this article many times. This is an excellent article by Erica Sadun on
How To Avoid Issues When Using Blocks And NSNotificationCenter
Swift update:
For example, in swift a simple method with success block would be:
func doSomeThingWithSuccessBlock(success: () -> ()) {
success()
}
When we call this method and need to use self in the success block. We'll be using the [weak self] and guard let features.
doSomeThingWithSuccessBlock { [weak self] () -> () in
guard let strongSelf = self else { return }
strongSelf.gridCollectionView.reloadData()
}
This so-called strong-weak dance is used by popular open source project Alamofire.
For more info check out swift-style-guide
In another answer, Tim said:
you can't refer to self or properties on self from within a block that will be strongly retained by self.
This isn’t quite true. It’s OK for you to do this so long as you break the cycle at some point. For example, let’s say you have a timer that fires that has a block that retains self and you also keep a strong reference to the timer in self. This is perfectly fine if you always know that you will destroy the timer at some point and break the cycle.
In my case just now, I had this warning for code that did:
[x setY:^{ [x doSomething]; }];
Now I happen to know that clang will only produce this warning if it detects the method starts with “set” (and one other special case that I won’t mention here). For me, I know there is no danger of there being a retain loop, so I changed the method name to “useY:” Of course, that might not be appropriate in all cases and usually you will want to use a weak reference, but I thought it worth noting my solution in case it helps others.
Many times, this is not actually a retain cycle.
If you know that it's not, you need not bring fruitless weakSelves into the world.
Apple even forces these warnings upon us with the API to their UIPageViewController, which includes a set method (which triggers these warnings–as mentioned elsewhere–thinking you are setting a value to an ivar that is a block) and a completion handler block (in which you'll undoubtedly refer to yourself).
Here's some compiler directives to remove the warning from that one line of code:
#pragma GCC diagnostic push
#pragma clang diagnostic ignored "-Warc-retain-cycles"
[self.pageViewController setViewControllers:#[newViewController] direction:navigationDirection animated:YES completion:^(BOOL finished) {
// this warning is caused because "setViewControllers" starts with "set…", it's not a problem
[self doTheThingsIGottaDo:finished touchThePuppetHead:YES];
}];
#pragma GCC diagnostic pop
Adding two cents on improving precision and style. In most cases you will only use one or a couple of members of self in this block, most likely just to update a slider. Casting self is overkill. Instead, it's better to be explicit and cast only the objects that you truly need inside the block. For example, if it's an instance of UISlider*, say, _timeSlider, just do the following before the block declaration:
UISlider* __weak slider = _timeSlider;
Then just use slider inside the block. Technically this is more precise as it narrows down the potential retain cycle to only the object that you need, not all the objects inside self.
Full example:
UISlider* __weak slider = _timeSlider;
[_embeddedPlayer addPeriodicTimeObserverForInterval:CMTimeMake(1, 1)
queue:nil
usingBlock:^(CMTime time){
slider.value = time.value/time.timescale;
}
];
Additionally, most likely the object being cast to a weak pointer is already a weak pointer inside self as well minimizing or eliminating completely the likelihood of a retain cycle. In the example above, _timeSlider is actually a property stored as a weak reference, e.g:
#property (nonatomic, weak) IBOutlet UISlider* timeSlider;
In terms of coding style, as with C and C++, variable declarations are better read from right to left. Declaring SomeType* __weak variable in this order reads more naturally from right to left as: variable is a weak pointer to SomeType.
I ran into this warning recently and wanted to understand it a bit better. After a bit of trial and error, I discovered that it originates from having a method start with either "add" or "save". Objective C treats method names starting with "new", "alloc", etc as returning a retained object but doesn't mention (that I can find) anything about "add" or "save". However, if I use a method name in this way:
[self addItemWithCompletionBlock:^(NSError *error) {
[self done]; }];
I will see the warning at the [self done] line. However, this will not:
[self itemWithCompletionBlock:^(NSError *error) {
[self done]; }];
I will go ahead and use the "__weak __typeof(self) weakSelf = self" way to reference my object but really don't like having to do so since it will confuse a future me and/or other dev. Of course, I could also not use "add" (or "save") but that's worse since it takes away the meaning of the method.
I have been looking around online, doing research into how to use blocks. I have also decided to set up a basic example to try and understand the way in which they work.
Essentially what I want to do is have a 'block variable' (no sure if thats the correct term) in which I can store a block of code. I then want to be able to set the code in this block at pointX (methodA or methodB) in my code, then run the block of code at pointY (methodX).
So to be specific, my question is 3-fold
Using the example below is the setup / usage of blocks correct and valid?
In methodX how do I execute the code inside the block (self.completionBlock)?
When creating the block in methodA and methodB will the code be called there and then? If so how can I stop this from happening (all I want to do is set up the code in the block to be called later)?
I may have completely misunderstood how blocks are used, apologies if this is the case, however I'm relatively new to Objective-C and I'm trying to learn.
Here is my code so far:
.h
typedef void (^ CompletionBlock)();
#interface TestClass : NSObject
{
CompletionBlock completionBlock;
NSString *stringOfText;
NSString *otherStringOfText;
}
#property(nonatomic, copy)CompletionBlock completionBlock;
#property(nonatomic, retain)NSString *stringOfText;
#property(nonatomic, retain)NSString *otherStringOfText;
- (void)methodA:(NSString *)myText;
- (void)methodB:(NSString *)myText and:(NSString *)myOtherText;
- (void)methodX;
#end
.m
- (void)methodA:(NSString *)myText;
{
if ([self.stringOfText isEqualToString:#""])
{
// Set the variable to be used by the completion block
self.stringOfText = #"I visited methodA"; // normally make use of myText
// Create the completion block
__block TestClass *blocksafeSelf = self;
self.completionBlock = ^()
{
[blocksafeSelf methodA:blocksafeSelf.stringOfText];
blocksafeSelf.stringOfText = nil;
};
}
else
{
// Do some other stuff with self.stringOfText
}
}
- (void)methodB:(NSString *)myText and:(NSString *)myOtherText;
{
if ([self.stringOfText isEqualToString:#""] || [self.otherStringOfText isEqualToString:#""])
{
// Set the variable to be used by the completion block
self.stringOfText = #"I visited methodB"; // normally make use of myText
self.otherStringOfText = #"I also visited methodB"; // normally make use of myOtherText
// Create the completion block
__block TestClass *blocksafeSelf = self;
self.completionBlock = ^()
{
[blocksafeSelf methodB:blocksafeSelf.stringOfText and:blocksafeSelf.otherStringOfText];
blocksafeSelf.stringOfText = nil;
blocksafeSelf.otherStringOfText = nil;
};
}
else
{
// Do some other stuff with self.stringOfText and self.otherStringOfText
}
}
- (void)methodX
{
// At this point run the block of code in self.completionBlock...how?!
}
In my example either methodA or methodB will be called first. Then some time later (perhaps from a different class) methodX will be called (only ever after methodA or methodB have been called).
It's worth noting that the methods methodA, methodB and methodX are all in a singleton class.
NOTE: This is just a dummy example to try and understand the workings of blocks, I'm fully aware there are other ways to achieve the same result.
Here's the code, just to be clear:
- (void)methodX
{
if(self.completionBlock)
self.completionBlock();
}
I think you want to do self.completionBlock(); in methodX.
I've just run into blocks and I think they are just what I'm looking for, except for one thing: is it possible to call a method [self methodName] from within a block?
This is what I'm trying to do:
-(void)someFunction{
Fader* fader = [[Fader alloc]init];
void (^tempFunction)(void) = ^ {
[self changeWindow:game];
//changeWindow function is located in superclass
};
[fader setFunction:tempFunction];
}
I've been searching for a couple of days and I can't find any evidence that this is possible.
Is this at all possible, or am I trying to use blocks for something they aren't meant for?
The reason I'm using blocks is that I've created a Fader class, and I want to store a block for it to execute when it finishes fading out.
Thank you
EDIT:
Okay, I added in the suggestion, but I'm still getting an EXC_BAD_ACCESS error...
-(void)someFunction{
Fader* fader = [[Fader alloc]init];
__block MyScreen* me = self;
void (^tempFunction)(void) = ^ {
[me changeWindow:game];
//changeWindow function is located in superclass
};
[fader setFunction:tempFunction];
[fader release];
}
Maybe I'm not allowed to give fader the function...?
Yes, you can do this.
Note, however, that the block will retain self. If you end up storing this block in an ivar, you could easily create a retain cycle, which means neither would ever get deallocated.
To get around this, you can do:
- (void) someMethodWithAParameter:(id)aParameter {
__block MySelfType *blocksafeSelf = self;
void (^tempFunction)(void) = ^ {
[blocksafeSelf changeWindow:game];
};
[self doSomethingWithBlock:tempFunction];
}
The __block keyword means (among other things) that the referenced object will not be retained.
The accepted answer is outdated. Using __block in that case can cause errors!
To avoid this problem, it’s best practice to capture a weak reference to self, like this:
- (void)configureBlock {
XYZBlockKeeper * __weak weakSelf = self;
self.block = ^{
[weakSelf doSomething]; // capture the weak reference
// to avoid the reference cycle
}
}
Please, look at Apple Documentation - Avoid Strong Reference Cycles when Capturing self
for more details.
__block CURRENTViewController *blocksafeSelf = self;
[homeHelper setRestAsCheckIn:strRestId :^(NSObject *temp) {
[blocksafeSelf YOURMETHOD:params];
}];
Is it possible to call a method [self methodName] from within a block?
Yes, why not. If your tempFunction is an instance method, you can do it. The called method should be accessible is the only restriction.
Consider this (which I think is the best practice)
#implementaion ViewController
- (void) viewDidLoad {
__weak typeof(self) wself = self;
[xxx doSomethingUsingBlock: ^{
__strong typeof(wself) self = wself;
[self anotherMessage];
}];
}
#end
Moreover, You can define wrapper macros.
#define MakeWeakSelf __weak typeof(self) wself = self
#define MakeStrongSelf __strong typeof(wself) self = wself
I wonder whether you [fader setFunction:tempFunction]; then is synchronous or asynchronous.
blocks push onto stack.so in MRR,if you don't retain it,it will pop off.
-(void)someFunction{
Fader* fader = [[Fader alloc]init];
void (^tempFunction)(void) = ^ {
[self changeWindow:game];
//changeWindow function is located in superclass
};
[fader setFunction:tempFunction];
//if the tempFunction execute there will be right.
}//there the tempFunction pop off
//....some thing go on
//execute the tempFunction will go wrong.
I'd like to recursively call a block from within itself. In an obj-c object, we get to use "self", is there something like this to refer to a block instance from inside itself?
Fun story! Blocks actually are Objective-C objects. That said, there is no exposed API to get the self pointer of blocks.
However, if you declare blocks before using them, you can use them recursively. In a non-garbage-collected environment, you would do something like this:
__weak __block int (^block_self)(int);
int (^fibonacci)(int) = [^(int n) {
if (n < 2) { return 1; }
return block_self(n - 1) + block_self(n - 2);
} copy];
block_self = fibonacci;
It is necessary to apply the __block modifier to block_self, because otherwise, the block_self reference inside fibonacci would refer to it before it is assigned (crashing your program on the first recursive call). The __weak is to ensure that the block doesn't capture a strong reference to itself, which would cause a memory leak.
The following recursive block code will compile and run using ARC, GC, or manual memory management, without crashing, leaking, or issuing warnings (analyzer or regular):
typedef void (^CountdownBlock)(int currentValue);
- (CountdownBlock) makeRecursiveBlock
{
CountdownBlock aBlock;
__block __unsafe_unretained CountdownBlock aBlock_recursive;
aBlock_recursive = aBlock = [^(int currentValue)
{
if(currentValue >= 0)
{
NSLog(#"Current value = %d", currentValue);
aBlock_recursive(currentValue-1);
}
} copy];
#if !__has_feature(objc_arc)
[aBlock autorelease];
#endif
return aBlock;
}
- (void) callRecursiveBlock
{
CountdownBlock aBlock = [self makeRecursiveBlock];
// You don't need to dispatch; I'm doing this to demonstrate
// calling from beyond the current autorelease pool.
dispatch_async(dispatch_get_main_queue(), ^
{
aBlock(10);
});
}
Important considerations:
You must copy the block onto the heap manually or else it will try to access a nonexistent stack when you call it from another context (ARC usually does this for you, but not in all cases. Better to play it safe).
You need TWO references: One to hold the strong reference to the block, and one to hold a weak reference for the recursive block to call (technically, this is only needed for ARC).
You must use the __block qualifier so that the block doesn't capture the as-yet unassigned value of the block reference.
If you're doing manual memory management, you'll need to autorelease the copied block yourself.
You have to declare the block variable as __block:
typedef void (^MyBlock)(id);
__block MyBlock block = ^(id param) {
NSLog(#"%#", param);
block(param);
};
There is no self for blocks (yet). You can build one like this (assuming ARC):
__block void (__weak ^blockSelf)(void);
void (^block)(void) = [^{
// Use blockSelf here
} copy];
blockSelf = block;
// Use block here
The __block is needed so we can set blockSelf to the block after creating the block. The __weak is needed because otherwise the block would hold a strong reference to itself, which would cause a strong reference cycle and therefore a memory leak. The copy is needed to make sure that the block is copied to the heap. That may be unnecessary with newer compiler versions, but it won't do any harm.