I am trying to understand how to use blocks on iOS. I have read Apple’s docs but, as usual, they are vague and incomplete and several essential bits of information are not mentioned. I have also googled around without success. This is what I am trying to do as an exercise to understand that.
I have created a block to read a string and compare the string to the previous read. If the strings are not the same, return YES, if they are the same, return NO.
This is how I did:
I declared this on .h
BOOL (^differentStrings)(void);
I declared this on .m, inside viewDidLoad in a viewController
__block NSString * previousString;
__block NSString * currentString;
differentStrings = ^(void){
currentString = [self getString];
NSLog(@"%@", currentString); // not printing anything on console
if (![currentString isEqualToString:previousString]) {
previousString = currentString;
return YES;
} else {
return NO;
}
};
This is how I use: I have a thread that does this:
if (differentStrings)
NSLog (@"strings are different);
These are the problems I have:
- the block always return YES (strings are different)
- I am not comfortable declaring this inside videDidLoad. How should I declare this, so I can use it globally as a method? Should I put this like I would with a method?
- I am calling a method “getString” inside the block. Is it OK?
- I find strange to declare the block variables on .m. As I see, I should declare the block variables on .h and then just use them on .m. I have tried to do that, but received an error.
- I have setup a debugging point on the first line of the block but it is not stopping there;
- NSlog line inside the block do not prints anything. Isn’t the block being called?
Can you guys help me with this?
You’re misunderstanding how blocks work. (Okay, so that’s kinda obvious.) In the same way that
previousStringis a variable pointing to an NSString,differentStringsis a variable pointing to a block. Not the result of running the block, but rather, the block itself. That is, after you do this:differentStringsis a variable pointing to the block.Thus, when you do this:…you’re simply checking whether
differentStringscontains something other than 0 or NULL. Since it contains a block, it is not empty, so it evaluates to true.Remember:
differentStringsis a block variable, not a BOOL variable. It contains a block (a function, if you will), which when called will return a bool. Thus, in order to actually run the block, you need to call it. Like this:or, in your case:
Edit: As pointed out in the comments, since
differentStringsis an instance variable, you need tocopyit, just like you’d callretainon any other object assigned to an instance variable. (For technical reasons I won’t go into now, you should always usecopywith blocks instead ofretain.) Likewise, you’ll need to callreleaseon it at some point later, perhaps in yourdeallocmethod.