RSSChannel and completionBlocks


#1

Hi there,

I really read your boook and I have to say it’s awesome. Really really useful. But I have a doubt I’d like to solve now I’m still rounding it.

In Chapter 27, page 498 (3rd edition), you say: “When capturing a pointer to an object, you can always change the properties of that object, but you cannot change what object the pointer points to. When declaring a pointer with the __block modifier, you can change the pointer to point at another object within the block”.

However, in Chapter 28, page 509, the completion code passed to the method fetchRSSFeedWithCompletion: does the following: channel = obj;
Channel is just an ivar without the __block modifier, why can we do it?

Bye and thanks!


#2

I had the same sorts of questions when I saw that line: channel = obj;
In fact it got me quite distracted from the lesson.
On pg 493 it says "Thus, a block has access to all of the local variables of the method, arguments passed to the method, and instance variables that belong to the object running the method."
On the next page, it says “… the values of the captured variables remain the same …”, and “… its arguments can change each time it is called.” The issue of local vs instance variables is not mentioned there.

We saw proof that local variables are captured when the block is defined, and that arguments are passed when the block is invoked. What about instance variables? Apparently they are not captured (after all the compiler really has no choice but to capture local variables, because they will vanish when the method that constructs the block is popped off the stack, but the object that created the block has to be kept). They appear to be completely accessible by the block at the time it executes (as if they were global variables). The ‘channel = obj;’ statement is proof enough. However, I went back into Blocky from Chapter 28, and did an experiment.

I created an instance variable in BNRAppDelegate.h:

And synthesized it in BNRAppDelegate.m:

Then when we assigned values to “multiplier” I also assigned the same values to “factor”

int multiplier = 3; factor = 3; ... multiplier = 100; factor = 100;

Finally, I ran Blocky switching the return value between

and

When I used multiplier, the result was 21. When I used factor, the result was 700. The block was executed later due to the Operation Queue stuff, so, we proved that the post-block-definition value of factor was used.

This may have answered another question that has been bugging me. C has always had the concept of a pointer to a function, and the way that you declare them looks just like a block declaration (except with a * instead of a ^). So why did objective C create the concept of blocks, instead of just using pointers to functions. I now suspect the answer is that blocks have a concept of the “self” pointer, which makes this question more profound than the nit-picky issue that it initially appeared to be. The direct accessibility within a block at execution time of the instance variables of the object within which the block was defined is (I suspect) a big part of what makes a block special.