Re: __block __weak - am I doing this right?

2012-02-22 Thread Matt Neuburg
On Sat, 18 Feb 2012 16:45:56 -0800, Greg Parker  said:

>Precisely. clang now warns about this case (or will soon; I don't know which 
>release of Xcode has this).
>
>test.m:9:33: warning: variable 'x' is uninitialized when captured by block 
>[-Wuninitialized]
>id x = [Foo methodWithBlock:^{ return x; }];

Yes, the static analyzer catches that now (even in an Xcode as old as Snow 
Leopard Xcode 4.2). That was a *huge* help to me in arriving at the correct 
formulation. m.

--
matt neuburg, phd = m...@tidbits.com, 
A fool + a tool + an autorelease pool = cool!
Programming iOS 5! http://shop.oreilly.com/product/0636920023562.do
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: __block __weak - am I doing this right?

2012-02-18 Thread Greg Parker
On Feb 18, 2012, at 9:23 AM, Fritz Anderson wrote:
> On 18 Feb 2012, at 7:41 AM, steven Hooley wrote:
>> Matt Neuburg wrote:
>>> The same issue came up again later the same day:
>>> 
>>>  __block UIBackgroundTaskIdentifier bti = [[UIApplication sharedApplication]
>>>  beginBackgroundTaskWithExpirationHandler: 
>>> ^{
>>>  [[UIApplication sharedApplication] endBackgroundTask:bti];
>>>  }];
>>> 
>>> Without __block, bti is invalid, and you won't find that out easily because 
>>> it's unlikely that you'll actually expire. :) m.
>> 
>> Can this be right?
> 
> If I understand why you're mystified, consider this, without the __block 
> declaration.
> 
> - bti starts as junk.
> 
> - The block is instantiated, and captures the junk _value_ (because it's not 
> a __block variable) of bti.
> 
> - The beginBackgroundTask… method creates the background task identifier.
> 
> - That identifier is then assigned to bti. bti is no longer junk, but that 
> does the block no good, because it's already captured the junk value.

Precisely. clang now warns about this case (or will soon; I don't know which 
release of Xcode has this).

test.m:9:33: warning: variable 'x' is uninitialized when captured by block 
[-Wuninitialized]
id x = [Foo methodWithBlock:^{ return x; }];


-- 
Greg Parker gpar...@apple.com  Runtime Wrangler



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: __block __weak - am I doing this right?

2012-02-18 Thread steven Hooley
> That's exactly *why* I've been asking about it - so I can fix it (and explain 
> the fix) for the new edition:

Sorry, I did not mean to imply 'many people have done it wrong because
of this book'. What i Failed at saying was "but.. I've seen this
pattern everywhere, even in Apple sample code, it can't be a bug!". I
thought this because i'd never seen the taskId declared as __block in
the sample code or docs.

Of course, i'd made an error not noticing that in the sample code/docs
the UIBackgroundTaskIdentifier is always an iVar and not realising
that this was critical to it's operation (and why i'd never seen it
declared __block).

I really appreciate you finding my bugs for me.
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: __block __weak - am I doing this right?

2012-02-18 Thread Matt Neuburg

On Feb 18, 2012, at 12:00 PM, cocoa-dev-requ...@lists.apple.com wrote:

> Date: Sat, 18 Feb 2012 18:39:55 +
> From: steven Hooley 
> To: Fritz Anderson 
> Cc: cocoa-dev@lists.apple.com
> Subject: Re: __block __weak - am I doing this right?
> Message-ID:
>   
> Content-Type: text/plain; charset=windows-1252
> 
> Thanks, I'm just surprised that this common, often cited example is broken.
> 
> http://books.google.co.uk/books?id=bwQY3_5FMg8C&pg=PA775&lpg=PA775&dq=beginBackgroundTaskWithExpirationHandler&source=bl&ots=aMuw5-hiP6&sig=NFKFDhaPw41KnfOo1n7Z_OaJflM&hl=en&sa=X&ei=T-s_T76JEaOl0AW0y-iPDw&ved=0CGoQ6AEwCTgK#v=onepage&q=beginBackgroundTaskWithExpirationHandler&f=false
> 
> That's an awful lot of broken code.

No duh. That's exactly *why* I've been asking about it - so I can fix it (and 
explain the fix) for the new edition:

https://plus.google.com/115941336284685245715/posts/H85LHwSDxP1

m.
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: __block __weak - am I doing this right?

2012-02-18 Thread steven Hooley
Thanks, I'm just surprised that this common, often cited example is broken.

http://books.google.co.uk/books?id=bwQY3_5FMg8C&pg=PA775&lpg=PA775&dq=beginBackgroundTaskWithExpirationHandler&source=bl&ots=aMuw5-hiP6&sig=NFKFDhaPw41KnfOo1n7Z_OaJflM&hl=en&sa=X&ei=T-s_T76JEaOl0AW0y-iPDw&ved=0CGoQ6AEwCTgK#v=onepage&q=beginBackgroundTaskWithExpirationHandler&f=false

That's an awful lot of broken code.


On 18 February 2012 17:23, Fritz Anderson  wrote:
> On 18 Feb 2012, at 7:41 AM, steven Hooley wrote:
>
>>> The same issue came up again later the same day:
>>>
>>>   __block UIBackgroundTaskIdentifier bti = [[UIApplication 
>>> sharedApplication]
>>>                                   beginBackgroundTaskWithExpirationHandler: 
>>> ^{
>>>       [[UIApplication sharedApplication] endBackgroundTask:bti];
>>>   }];
>>>
>>> Without __block, bti is invalid, and you won't find that out easily because 
>>> it's unlikely that you'll actually expire. :) m.
>>
>> Can this be right?
>
> If I understand why you're mystified, consider this, without the __block 
> declaration.
>
> - bti starts as junk.
>
> - The block is instantiated, and captures the junk _value_ (because it's not 
> a __block variable) of bti.
>
> - The beginBackgroundTask… method creates the background task identifier.
>
> - That identifier is then assigned to bti. bti is no longer junk, but that 
> does the block no good, because it's already captured the junk value.
>
>
> If bti is declared __block, the block captures (notionally) a _reference_ to 
> bti. It doesn't evaluate bti until it executes, which will be after the 
> assignment.
>
>        — F
>

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: __block __weak - am I doing this right?

2012-02-18 Thread Fritz Anderson
On 18 Feb 2012, at 7:41 AM, steven Hooley wrote:

>> The same issue came up again later the same day:
>> 
>>   __block UIBackgroundTaskIdentifier bti = [[UIApplication sharedApplication]
>>   beginBackgroundTaskWithExpirationHandler: 
>> ^{
>>   [[UIApplication sharedApplication] endBackgroundTask:bti];
>>   }];
>> 
>> Without __block, bti is invalid, and you won't find that out easily because 
>> it's unlikely that you'll actually expire. :) m.
> 
> Can this be right?

If I understand why you're mystified, consider this, without the __block 
declaration.

- bti starts as junk.

- The block is instantiated, and captures the junk _value_ (because it's not a 
__block variable) of bti.

- The beginBackgroundTask… method creates the background task identifier.

- That identifier is then assigned to bti. bti is no longer junk, but that does 
the block no good, because it's already captured the junk value.


If bti is declared __block, the block captures (notionally) a _reference_ to 
bti. It doesn't evaluate bti until it executes, which will be after the 
assignment.

— F


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: __block __weak - am I doing this right?

2012-02-18 Thread steven Hooley
> The same issue came up again later the same day:
>
>__block UIBackgroundTaskIdentifier bti = [[UIApplication sharedApplication]
>beginBackgroundTaskWithExpirationHandler: 
> ^{
>[[UIApplication sharedApplication] endBackgroundTask:bti];
>}];
>
> Without __block, bti is invalid, and you won't find that out easily because 
> it's unlikely that you'll actually expire. :) m.


Can this be right?
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: __block __weak - am I doing this right?

2012-02-16 Thread Matt Neuburg

On Feb 16, 2012, at 4:16 PM, Greg Parker wrote:

> On Feb 16, 2012, at 12:57 PM, Matt Neuburg  wrote:
>> On Feb 16, 2012, at 12:45 PM, Greg Parker wrote:
>>> On Feb 16, 2012, at 12:42 PM, Matt Neuburg  wrote:
 On Feb 16, 2012, at 12:05 PM, Greg Parker wrote:
> 
> The question is, who retains the observer? The __block __weak variable 
> does not, because it's weak. NSNotificationCenter does not, as I 
> understand it.
 
 It does, actually; thanks for pressing me on this point.
>>> 
>>> The NSNotificationCenter documentation says:
>>> "Important: The notification center does not retain its observers…"
>> 
>> We may be talking at cross purposes.
>> 
>> If you register by saying addObserver:selector:name:object:, the 
>> notification center does not retain the observer object named in the first 
>> param.
>> 
>> But if you register by saying addObserverForName:object:queue:usingBlock:, 
>> it returns an observer object, and the notification center *does* retain 
>> that observer. 
> 
> Aha. That's the part I didn't see, and it contradicts the "Important" note at 
> the top of the NSNotificationCenter documentation. I'll file a documentation 
> bug report.
> 
> With that clarified, the example you posted should be fine.
> 
> 
> There's an alternative if you are using ARC and you know the notification 
> will fire exactly once:
> 
> // ARC required.
> __block id observer = [[NSNotificationCenter defaultCenter] 
>  addObserverForName:@"MyMandelbrotOperationFinished" 
>  object:op queue:[NSOperationQueue mainQueue] 
>  usingBlock:^(NSNotification *note) {
>MyMandelbrotOperation* op2 = note.object;
>// do stuff
>[[NSNotificationCenter defaultCenter] removeObserver:observer 
>name:@"MyMandelbrotOperationFinished" object:op2];
>observer = nil;
> }];
> 
> This version does not use __weak. Instead, the block object creates a retain 
> cycle by retaining the observer via the __block variable. When the block 
> object executes, it breaks the cycle by setting the __block variable to nil, 
> releasing the observer. 
> 
> If you have a specific time that you can break the cycle, you can use this 
> pattern. The pattern would fail if you didn't know when you could break the 
> cycle (for example, if the block might run zero times).


Right, good point (several good points). Thanks again. m.

--
matt neuburg, phd = m...@tidbits.com, http://www.apeth.net/matt/
pantes anthropoi tou eidenai oregontai phusei
Programming iOS 5! http://shop.oreilly.com/product/0636920023562.do
RubyFrontier! http://www.apeth.com/RubyFrontierDocs/default.html
TidBITS, Mac news and reviews since 1990, http://www.tidbits.com





___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: __block __weak - am I doing this right?

2012-02-16 Thread Greg Parker
On Feb 16, 2012, at 12:57 PM, Matt Neuburg  wrote:
> On Feb 16, 2012, at 12:45 PM, Greg Parker wrote:
>> On Feb 16, 2012, at 12:42 PM, Matt Neuburg  wrote:
>>> On Feb 16, 2012, at 12:05 PM, Greg Parker wrote:
 
 The question is, who retains the observer? The __block __weak variable 
 does not, because it's weak. NSNotificationCenter does not, as I 
 understand it.
>>> 
>>> It does, actually; thanks for pressing me on this point.
>> 
>> The NSNotificationCenter documentation says:
>> "Important: The notification center does not retain its observers…"
> 
> We may be talking at cross purposes.
> 
> If you register by saying addObserver:selector:name:object:, the notification 
> center does not retain the observer object named in the first param.
> 
> But if you register by saying addObserverForName:object:queue:usingBlock:, it 
> returns an observer object, and the notification center *does* retain that 
> observer. 

Aha. That's the part I didn't see, and it contradicts the "Important" note at 
the top of the NSNotificationCenter documentation. I'll file a documentation 
bug report.

With that clarified, the example you posted should be fine.


There's an alternative if you are using ARC and you know the notification will 
fire exactly once:

   // ARC required.
   __block id observer = [[NSNotificationCenter defaultCenter] 
 addObserverForName:@"MyMandelbrotOperationFinished" 
 object:op queue:[NSOperationQueue mainQueue] 
 usingBlock:^(NSNotification *note) {
   MyMandelbrotOperation* op2 = note.object;
   // do stuff
   [[NSNotificationCenter defaultCenter] removeObserver:observer 
   name:@"MyMandelbrotOperationFinished" object:op2];
   observer = nil;
   }];

This version does not use __weak. Instead, the block object creates a retain 
cycle by retaining the observer via the __block variable. When the block object 
executes, it breaks the cycle by setting the __block variable to nil, releasing 
the observer. 

If you have a specific time that you can break the cycle, you can use this 
pattern. The pattern would fail if you didn't know when you could break the 
cycle (for example, if the block might run zero times).


-- 
Greg Parker gpar...@apple.com Runtime Wrangler



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: __block __weak - am I doing this right?

2012-02-16 Thread Fritz Anderson
On 16 Feb 2012, at 2:05 PM, Greg Parker wrote:

> The question is, who retains the observer? The __block __weak variable does 
> not, because it's weak. NSNotificationCenter does not, as I understand it.

I've lost the earlier parts of this thread… Are we talking about 
-[NSNotificationCenter addObserverForName:object:queue:usingBlock:]? The 
documentation says it's necessary to keep an anchoring reference under GC, but:

> (In a reference counted environment, the system retains the returned observer 
> object until it is removed, so there is no need to retain it yourself.)

— F


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: __block __weak - am I doing this right?

2012-02-16 Thread Ken Thomases
On Feb 16, 2012, at 2:05 PM, Greg Parker wrote:

> On Feb 16, 2012, at 8:22 AM, Matt Neuburg  wrote:
>> On Wed, 15 Feb 2012 16:20:50 -0800, Greg Parker  said:
>>> 
>>> Are you using GC or ARC? I think this is safe with GC but not safe with 
>>> ARC, but I'm not an expert in the NSNotificationCenter machinery.
>> 
>> ARC, but I don't see how it might be unsafe. I sure *hope* it isn't, because 
>> that's what the __weak is for. You need that because if your observer 
>> doesn't vanish in good order, neither will +self+, because the observer 
>> retains +self+, not just while registered with the notification center but 
>> for as long as it lives (by way of the block, I presume). *That* is 
>> something I *do* understand, having spent many hours watching the retain 
>> counts at work.
> 
> The question is, who retains the observer? The __block __weak variable does 
> not, because it's weak. NSNotificationCenter does not, as I understand it.

I was worried about that, too, but the -[NSNotificationCenter 
addObserverForName:object:queue:usingBlock:] docs say:

"In a reference counted environment, the system retains the returned observer 
object until it is removed, so there is no need to retain it yourself."

ARC does still count as a reference counted environment, I assume.

Regards,
Ken


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: __block __weak - am I doing this right?

2012-02-16 Thread Matt Neuburg

On Feb 16, 2012, at 12:45 PM, Greg Parker wrote:

> On Feb 16, 2012, at 12:42 PM, Matt Neuburg  wrote:
>> On Feb 16, 2012, at 12:05 PM, Greg Parker wrote:
>>> 
>>> The question is, who retains the observer? The __block __weak variable does 
>>> not, because it's weak. NSNotificationCenter does not, as I understand it.
>> 
>> It does, actually; thanks for pressing me on this point.
> 
> The NSNotificationCenter documentation says:
> "Important: The notification center does not retain its observers…"

We may be talking at cross purposes.

If you register by saying addObserver:selector:name:object:, the notification 
center does not retain the observer object named in the first param.

But if you register by saying addObserverForName:object:queue:usingBlock:, it 
returns an observer object, and the notification center *does* retain that 
observer. And, since that block will probably mention self, and since the 
observer effectively consists of a wrapper for that block, the observer is 
retaining you. Hence the cycle. You *must* unregister or you will leak 
yourself. The example I cited shows how to do that.

m.

--
matt neuburg, phd = m...@tidbits.com, http://www.apeth.net/matt/
pantes anthropoi tou eidenai oregontai phusei
Programming iOS 5! http://shop.oreilly.com/product/0636920023562.do
RubyFrontier! http://www.apeth.com/RubyFrontierDocs/default.html
TidBITS, Mac news and reviews since 1990, http://www.tidbits.com



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: __block __weak - am I doing this right?

2012-02-16 Thread Greg Parker
On Feb 16, 2012, at 12:42 PM, Matt Neuburg  wrote:
> On Feb 16, 2012, at 12:05 PM, Greg Parker wrote:
>> 
>> The question is, who retains the observer? The __block __weak variable does 
>> not, because it's weak. NSNotificationCenter does not, as I understand it.
> 
> It does, actually; thanks for pressing me on this point.

The NSNotificationCenter documentation says:
"Important: The notification center does not retain its observers…"

So something is still not right here.


-- 
Greg Parker gpar...@apple.com Runtime Wrangler



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: __block __weak - am I doing this right?

2012-02-16 Thread Matt Neuburg

On Feb 16, 2012, at 12:05 PM, Greg Parker wrote:

> On Feb 16, 2012, at 8:22 AM, Matt Neuburg  wrote:
>> On Wed, 15 Feb 2012 16:20:50 -0800, Greg Parker  said:
>>> 
>>> Are you using GC or ARC? I think this is safe with GC but not safe with 
>>> ARC, but I'm not an expert in the NSNotificationCenter machinery.
>> 
>> ARC, but I don't see how it might be unsafe. I sure *hope* it isn't, because 
>> that's what the __weak is for. You need that because if your observer 
>> doesn't vanish in good order, neither will +self+, because the observer 
>> retains +self+, not just while registered with the notification center but 
>> for as long as it lives (by way of the block, I presume). *That* is 
>> something I *do* understand, having spent many hours watching the retain 
>> counts at work.
> 
> The question is, who retains the observer? The __block __weak variable does 
> not, because it's weak. NSNotificationCenter does not, as I understand it.

It does, actually; thanks for pressing me on this point.

That's why the easiest pattern under ARC for preventing a retain cycle in 
general (that is, where you - a view controller, say - hang on to a reference 
to the observer for a long time, like from viewWillAppear: to 
viewWillDisappear:) is to store it in a __weak ivar. When you unregister the 
observer (which you can do, because you have a reference to it in the ivar), 
the notification center releases it, it goes out of existence, the __weak ivar 
is automatically nilified, and (most important) the observer releases you, 
preventing a retain cycle.

Of course you could also solve the problem with a __strong ivar and nilify the 
ivar yourself after you unregister. But you don't have to, because the 
notification center retains the observer from the get-go. If it didn't, the 
__weak ivar would be nil when you need to unregister - and it isn't.

I've documented this (after a lot of experimentation - and did I mention "thank 
you, Instruments"???) here:

  http://www.apeth.com/iOSBook/ch12.html#_retain_cycles_and_weak_references

Naturally if you have any thoughts I would be *very* happy to hear them. m.

PS Oh, and if you'd like to play with the various possibilities, there's no 
need to write any code: I have a downloadable example project that demonstrates 
all of them:



Set the ivar to __weak and leave the #define set at 1. Run the project. Flip 
the view and flip it back (with Done) and watch the Console. You'll see that 
observer is good and that we dealloc successfully.

--
matt neuburg, phd = m...@tidbits.com, http://www.apeth.net/matt/
pantes anthropoi tou eidenai oregontai phusei
Programming iOS 5! http://shop.oreilly.com/product/0636920023562.do
RubyFrontier! http://www.apeth.com/RubyFrontierDocs/default.html
TidBITS, Mac news and reviews since 1990, http://www.tidbits.com



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: __block __weak - am I doing this right?

2012-02-16 Thread Greg Parker
On Feb 16, 2012, at 8:22 AM, Matt Neuburg  wrote:
> On Wed, 15 Feb 2012 16:20:50 -0800, Greg Parker  said:
>> 
>> Are you using GC or ARC? I think this is safe with GC but not safe with ARC, 
>> but I'm not an expert in the NSNotificationCenter machinery.
> 
> ARC, but I don't see how it might be unsafe. I sure *hope* it isn't, because 
> that's what the __weak is for. You need that because if your observer doesn't 
> vanish in good order, neither will +self+, because the observer retains 
> +self+, not just while registered with the notification center but for as 
> long as it lives (by way of the block, I presume). *That* is something I *do* 
> understand, having spent many hours watching the retain counts at work.

The question is, who retains the observer? The __block __weak variable does 
not, because it's weak. NSNotificationCenter does not, as I understand it.


-- 
Greg Parker gpar...@apple.com Runtime Wrangler



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: __block __weak - am I doing this right?

2012-02-16 Thread Matt Neuburg
Never mind the async talk in my previous answer. You mean what I know; my point 
was, I now get the idea about why it's important that the block is executed 
later. m.

--
matt neuburg, phd = m...@tidbits.com, 
A fool + a tool + an autorelease pool = cool!
Programming iOS 5! http://shop.oreilly.com/product/0636920023562.do
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: __block __weak - am I doing this right?

2012-02-16 Thread Matt Neuburg
On Wed, 15 Feb 2012 16:20:50 -0800, Greg Parker  said:
>On Feb 15, 2012, at 12:58 PM, Matt Neuburg  wrote:

>Are you using GC or ARC? I think this is safe with GC but not safe with ARC, 
>but I'm not an expert in the NSNotificationCenter machinery.

ARC, but I don't see how it might be unsafe. I sure *hope* it isn't, because 
that's what the __weak is for. You need that because if your observer doesn't 
vanish in good order, neither will +self+, because the observer retains +self+, 
not just while registered with the notification center but for as long as it 
lives (by way of the block, I presume). *That* is something I *do* understand, 
having spent many hours watching the retain counts at work.

>Without __block, the block object snapshots the value of the observer variable 
>when the block object is created. But in your code the block object is created 
>before the call to -addObserverForName:..., and at that point the observer 
>variable is not yet initialized. Boom.
>
>With __block, the block object always uses the current value of the observer 
>variable. The variable is initialized before the block object actually 
>executes, so everything works.

Thank you! (So, the fact that we are async is crucial to this working. I was 
missing *that* piece of the mental puzzle too, though of course I would not 
have used sync in any case.)

I feel this wasn't quite made clear by the WWDC videos and the docs. Perhaps 
it's in the latter and I missed it. This is not a criticism (I would never 
criticize the GCD/runtime people about how they explain GCD; au contraire, I 
think you guys are the best explainers associated with Apple), just a 
suggestion. A simple sentence would suffice: You can use the result of a call 
to a method that takes a block inside the block, but only if it is typed as 
__block (and only if the block is executed later).

The same issue came up again later the same day:

__block UIBackgroundTaskIdentifier bti = [[UIApplication sharedApplication] 
beginBackgroundTaskWithExpirationHandler: ^{
[[UIApplication sharedApplication] endBackgroundTask:bti];
}];

Without __block, bti is invalid, and you won't find that out easily because 
it's unlikely that you'll actually expire. :) m.

--
matt neuburg, phd = m...@tidbits.com, 
A fool + a tool + an autorelease pool = cool!
Programming iOS 5! http://shop.oreilly.com/product/0636920023562.do
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: __block __weak - am I doing this right?

2012-02-15 Thread Wim Lewis

On 15 Feb 2012, at 12:58 PM, Matt Neuburg wrote:
> * Why was I crashing until I said __block?


Without __block, the value of the variable is copied into the block 
(effectively as a const local variable) when the block is created. With 
__block, both the code inside and outside the block reference the same 
variable, and each can see each others' modifications (almost like a closure in 
languages that have that).

The block is created before 'observer' is initialized (it has to be, so that it 
can be passed to -addOberver...), so the value of 'observer' it captures when 
it is created is the value of the uninitialized stack variable. It's as if you 
were doing this:

  id observer = createObserverStuff(observer);

instead of this, which is kinda sorta what happens with __block variables:

  id observer = createObserverStuff(&observer);



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: __block __weak - am I doing this right?

2012-02-15 Thread Roland King
I had a similar one the other week, same idea, notification I wanted to remove 
in its handler. 

I assume that before you added __block you were getting an exception in the 
block handler, EACCESS was mine I think. 

I also changed to a block variable and it started working. My presumption was 
that observer was being captured as nil, or some unassigned value into the 
block as the method was entered and thus was rubbish when the callback came and 
as it was not a block variable the later assignment did not change the value 
captured in the block.  I also assumed that making it a block variable allowed 
the captured observer to be changed to the result of addObserver:.. at the end 
of the method call and be available to the block. 

And yes I now love blocks too, especially with all the asynchronous methods 
icloud uses. It's great in an open callback for a document to throw a block on 
the main queue to close it again on the next cycle, and do something else when 
the close callback comes. 

On 16 Feb, 2012, at 4:58, Matt Neuburg  wrote:

> This appears to be working from all points of view (thank you, Instruments!):
> 
>MyMandelbrotOperation* op = 
>[[MyMandelbrotOperation alloc] initWithSize:self.bounds.size 
> center:center zoom:1];
>__block __weak id observer = [[NSNotificationCenter defaultCenter] 
>  addObserverForName:@"MyMandelbrotOperationFinished" 
>  object:op queue:[NSOperationQueue mainQueue] 
>  usingBlock:^(NSNotification *note) {
>MyMandelbrotOperation* op2 = note.object;
>CGContextRef context = [op2 bitmapContext];
>if (self->bitmapContext)
>CGContextRelease(self->bitmapContext);
>self->bitmapContext = (CGContextRef) context;
>CGContextRetain(self->bitmapContext);
>[self setNeedsDisplay];
>[[NSNotificationCenter defaultCenter] removeObserver:observer 
>name:@"MyMandelbrotOperationFinished" object:op2];
>}];
>[self.queue addOperation:op];
> 
> This is delightful. I'm not leaking self, my operations are being dealloced 
> in good order, I'm successfully registering and deregistering, I'm 
> trampolining to the main thread without writing a trampoline method, I'm 
> avoiding the nightmare of storing my observers in an instance variable, op 
> and op2 are the same object - everything about it seems to be okay. My 
> questions are:
> 
> * Is this really an okay way to talk?
> 
> * Why was I crashing until I said __block?
> 
> m.
> 
> --
> matt neuburg, phd = m...@tidbits.com, http://www.apeth.net/matt/
> pantes anthropoi tou eidenai oregontai phusei
> Programming iOS 5! http://shop.oreilly.com/product/0636920023562.do
> RubyFrontier! http://www.apeth.com/RubyFrontierDocs/default.html
> TidBITS, Mac news and reviews since 1990, http://www.tidbits.com
> 
> 
> 
> ___
> 
> Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)
> 
> Please do not post admin requests or moderator comments to the list.
> Contact the moderators at cocoa-dev-admins(at)lists.apple.com
> 
> Help/Unsubscribe/Update your Subscription:
> https://lists.apple.com/mailman/options/cocoa-dev/rols%40rols.org
> 
> This email sent to r...@rols.org

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: __block __weak - am I doing this right?

2012-02-15 Thread Greg Parker
On Feb 15, 2012, at 12:58 PM, Matt Neuburg  wrote:
> This appears to be working from all points of view (thank you, Instruments!):
> 
>MyMandelbrotOperation* op = 
>[[MyMandelbrotOperation alloc] initWithSize:self.bounds.size 
> center:center zoom:1];
>__block __weak id observer = [[NSNotificationCenter defaultCenter] 
>  addObserverForName:@"MyMandelbrotOperationFinished" 
>  object:op queue:[NSOperationQueue mainQueue] 
>  usingBlock:^(NSNotification *note) {
>MyMandelbrotOperation* op2 = note.object;
>CGContextRef context = [op2 bitmapContext];
>if (self->bitmapContext)
>CGContextRelease(self->bitmapContext);
>self->bitmapContext = (CGContextRef) context;
>CGContextRetain(self->bitmapContext);
>[self setNeedsDisplay];
>[[NSNotificationCenter defaultCenter] removeObserver:observer 
>name:@"MyMandelbrotOperationFinished" object:op2];
>}];
>[self.queue addOperation:op];
> 
> This is delightful. I'm not leaking self, my operations are being dealloced 
> in good order, I'm successfully registering and deregistering, I'm 
> trampolining to the main thread without writing a trampoline method, I'm 
> avoiding the nightmare of storing my observers in an instance variable, op 
> and op2 are the same object - everything about it seems to be okay. My 
> questions are:
> 
> * Is this really an okay way to talk?

Are you using GC or ARC? I think this is safe with GC but not safe with ARC, 
but I'm not an expert in the NSNotificationCenter machinery.


> * Why was I crashing until I said __block?

Without __block, the block object snapshots the value of the observer variable 
when the block object is created. But in your code the block object is created 
before the call to -addObserverForName:..., and at that point the observer 
variable is not yet initialized. Boom.

With __block, the block object always uses the current value of the observer 
variable. The variable is initialized before the block object actually 
executes, so everything works.


-- 
Greg Parker gpar...@apple.com Runtime Wrangler



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com