Question

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:

  1. the block always return YES (strings are different)
  2. 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?
  3. I am calling a method "getString" inside the block. Is it OK?
  4. 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.
  5. I have setup a debugging point on the first line of the block but it is not stopping there;
  6. NSlog line inside the block do not prints anything. Isn't the block being called?

Can you guys help me with this?

Was it helpful?

Solution

You're misunderstanding how blocks work. (Okay, so that's kinda obvious.) In the same way that previousString is a variable pointing to an NSString, differentStrings is a variable pointing to a block. Not the result of running the block, but rather, the block itself. That is, after you do this:

__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;
    }
};

differentStrings is a variable pointing to the block.Thus, when you do this:

if (differentStrings)

…you're simply checking whether differentStrings contains something other than 0 or NULL. Since it contains a block, it is not empty, so it evaluates to true.

Remember: differentStrings is 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:

differentStrings();

or, in your case:

if (differentStrings()) {
    NSLog (@"strings are different");
}

Edit: As pointed out in the comments, since differentStrings is an instance variable, you need to copy it, just like you'd call retain on any other object assigned to an instance variable. (For technical reasons I won't go into now, you should always use copy with blocks instead of retain.) Likewise, you'll need to call release on it at some point later, perhaps in your dealloc method.

OTHER TIPS

I don't believe you're actually executing the block. I think your code should be

if (differentStrings())
{
    NSLog (@"strings are different);
}

Treat a block like a function. I think you were just checking to see whether the block had been defined, not executing it.

Also, if you don't need to access an NSString outside of the block, you could get rid of the __block qualifier and move the currentString declaration inside of the block.

If you need another resource on blocks, I cover them in the fall session of my advanced iOS development course on iTunes U. I describe block syntax in the Understanding Cocoa session, and their use in Grand Central Dispatch within the multithreading session. The course notes also have links to some sample applications that use blocks in different ways.

I also can't recommend highly enough that you watch the WWDC 2010 video sessions 206 - Introducing Blocks and Grand Central Dispatch on iPhone and 211 - Simplifying iPhone App Development with Grand Central Dispatch.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top