Calling [self methodName] from inside a block? - objective-c

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.

Related

"Capturing 'self' strongly in this block is likely to lead to a retain cycle" using Reachability

I'm trying to edit a variable inside the Reachability block using Objective-C, this is the code:
- (void)testInternetConnection
{
internetReachableFoo = [Reachability reachabilityWithHostname:#"www.google.com"];
// Internet is reachable
internetReachableFoo.reachableBlock = ^(Reachability*reach)
{
// Update the UI on the main thread
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(#"Connessione ad Internet disponibile");
checkConnection = YES;
if(!lastConnectionState)
{
lastConnectionState = YES;
if(doItemsDownload)
[self displayChoice];
}
});
};
// Internet is not reachable
internetReachableFoo.unreachableBlock = ^(Reachability*reach)
{
// Update the UI on the main thread
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(#"Connessione ad Internet non disponibile");
checkConnection = NO;
lastConnectionState = NO;
});
};
[internetReachableFoo startNotifier];
}
Where checkConnection; & lastConnectionState; are 2 bool declared on my #interface;
The problem is that accessing these variables and calling [self displayChoice]; inside this block gives me the warning: Capturing 'self' strongly in this block is likely to lead to a retain cycle
How can I possibly avoid this error?
I tried declaring a WeakSelf and declaring self but I don't know how to do it for the bool variables
Capturing self strongly in a block is not always bad. If a block is being executed right away (UIView animate block for example) there is generally no risk.
The problem arises when self captures a block strongly and the block in turn captures self strongly. In this case self retains the block and the block retains self so neither can be released --> retain cycle!
To avoid this you need to capture self weakly in the block.
__weak typeof(self) = self; // CREATE A WEAK REFERENCE OF SELF
__block BOOL blockDoItemsDownload = doItemsDownload; // USE THIS INSTEAD OF REFERENCING ENVIRONMENT VARIABLE DIRECTLY
__block BOOL blockCheckConnection = checkConnection;
internetReachableFoo.reachableBlock = ^(Reachability*reach)
{
// Update the UI on the main thread
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(#"Connessione ad Internet disponibile");
blockCheckConnection = YES;
if(!lastConnectionState)
{
lastConnectionState = YES;
if(blockDoItemsDownload) // Use block variable here
[weakSelf displayChoice]; // Use weakSelf in place of self
}
});
};
There is a cocoapod called libextobjc and what it allows you to do is quickly and cleanly weakify and strongify objects.
#weakify(self)
[someblock:^{
#strongify(self)
}];
As long as you handle self you should be ok. I'm not 100% sure the BOOL values aren't an issue but I think you could do something like this:
BOOL x = YES;
#weakify(self, x)
[someblock:^{
#strongify(self, x)
}];

Idiom to hide `self` in Objective C blocks?

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?

capturing self strongly in this block is likely to lead to a retain cycle

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.

iphone ARC - how to set an object to nil?

I have some logic that test if an object is nil or not, how can I set it to nil?
Like:
// in some method
if (true){
[self myObj] = [[myObj alloc]init];
} else{
[self myObject] = nil; //??? How to do this with Automatic Ref. Counting
}
// elsewhere
if([self myObj]){
}
Your code is incorrect.
You need to use properties and assign values to them, like [self setMyObject:nil]; or [self setMyObj:[[myObj alloc] init]];.
Your code is wrong. Try:
self.myObject=nil;
//or
[self setMyObject:nil];
Also, make sure that myObject is a property in your class, otherwise using self won't work.
[self myObj] is not assignable, as it is not a lvalue. To fix this, either reference the underlying variable, e.g. self->myObj, or use [self setMyObj:] if you are using properties.
You are using a getter as a setter. That isn't going to work. It should be
[self setMyObj:[myObj alloc]init]];
And
[self setMyObj:nil];
Assuming you have implemented the setters. Under ARC you don't really need to if you are just accessing an ivar - you can access it directly and the reference counting will be done for you:
myObj = [MyObj alloc] init];
And
myObj = nil;
Will set and remove everything for you.

Objective-c Async memory management

I've had a look around but have been unable to find a definitive answer to this question.
If I have a class that performs an async operation, when and how do I release it?
-(void)main
{
AsyncObject *async = [[AsyncObject alloc] initWithDelegate:self];
[async goDoSomething];
}
-(void)didSomething:(Result*)result
{
}
When do I release *async?
You could keep a private property to save the value, or, if you have control over the AsyncObject, pass the instance in the didSomething: selector.
I think the first option is better since you know the object will be retained until you get your delegate call.
Option 1:
ClassName.m
#interface ClassName ()
#property (nonatomic, retain) AsyncObject* async;
#end
#interface
//...
-(void)main
{
async = [[AsyncObject alloc] initWithDelegate:self];
[async goDoSomething];
}
-(void)didSomething:(Result*)result
{
[async release];
async = nil;
}
Option 2:
-(void)aysncObject:(AsyncObject*)async didSomething:(Result*)result {
[async release];
}
If your object runs its asynchronous task on a background thread, or is the target of a timer, or uses GCD and is referenced within the scope of the dispatched block (the ^ {} kerjigger) then it will be retained for you for the lifetime of that background operation.
So the normal use case would be:
AsyncObject *async = [[AsyncObject alloc] initWithDelegate:self];
[async goDoSomething];
[async release];
Now, it's possible to work in the background with an object that is not retained (e.g. by using a __block-scoped reference to the object with GCD, or by detaching your worker thread with pthreads instead of NSThread/NSOperation) but there are no typical use cases I can think of offhand where that would happen. In such a case, you should ensure that -goDoSomething internally retains and releases self for the duration of the operation.
(If somebody can think of a case where the object is not retained for you, please post in the comments and I'll update my answer.)
Thanks for the help guys, I did a bit of experimenting with NSURLConnection to see how it handled it (As you autorelease that and it will continue on with it's async operations).
Turns out at the beginning of every async step it internally bumps its retain count and at the end of every async step it internally releases itself.
This means that it can be sent autorelease/release and it won't actually be release until it has completed it's current operation.
// MAIN.M
-(void)main
{
AsyncObject *async = [[[AsyncObject alloc] initWithDelegate:self] autorelease];
[async goDoSomething];
}
-(void)didSomething:(Result*)result
{
}
// ASYNCOBJECT.M
-(void) goDoSomething
{
[self retain];
}
-(void) finishedDoingSomething
{
[delegate didSomething:result];
[self release]
}