Re: blocks and NSInvocation question
Re: blocks and NSInvocation question
- Subject: Re: blocks and NSInvocation question
- From: Ken Thomases <email@hidden>
- Date: Mon, 11 Apr 2011 10:30:11 -0500
On Apr 10, 2011, at 11:53 PM, John Michael Zorko wrote:
> I'm stumped as to why this generates a warning when I compile. Do I need to do something special with my AVURLAsset * to be able to access it from inside the block in order to add it to an NSInvocation?
> AVURLAsset *asset = [AVURLAsset URLAssetWithURL:streamURL options:nil];
> [asset loadValuesAsynchronouslyForKeys:[NSArray arrayWithObject:tracks] completionHandler:^
> {
> NSInvocation *inv = [NSInvocation invocationWithMethodSignature:sig];
> [inv setArgument:&asset atIndex:2]; // warning: passing argument 1 of 'setArgument:atIndex:' discards qualifiers from pointer target type
Since asset is a non-__block variable declared outside the block but referenced within it, the block holds a const copy of it. In other words, inside the block, "asset" is of type "AVURLAsset * const" -- a const pointer to an AVURLAsset. This is fine and right.
Taking the address of asset yields an expression of type "AVURLAsset * const *".
However, -[NSInvocation setArgument:atIndex:] takes a non-const void* for its buffer parameter. The compiler is telling you that you're passing a pointer-to-const in a pointer-to-non-const parameter. In theory, NSInvocation could write through that pointer, thus modifying something through a pointer that's not supposed to allow that.
In this case, the warning is not flagging a real problem. NSInvocation will not write through that pointer. I believe that -setArgument:atIndex: should have been declared to take a "const void *" buffer. You can silence the warning by explicitly casting to (void*), like so:
[inv setArgument:(void*)&asset atIndex:2];
All of that said, since you're already using blocks, you'd almost certainly be better off using another block, dispatched to the main queue, rather than using NSInvocation or -performSelectorOnMainThread:...
[asset loadValuesAsynchronouslyForKeys:[NSArray arrayWithObject:tracks] completionHandler:^{
// Use dispatch_sync if that's really necessary
dispatch_async(dispatch_get_main_queue(), ^{
[self setupPlayerForAsset:asset withIndex:index]; // Wrap index in NSNumber if really necessary
});
}];
I wasn't sure if the waitUntilDone:YES was strictly necessary. It seems that asynchrony is implicit in the use of -loadValuesAsynchronouslyForKeys:..., so I didn't bother translating waitUntilDone:YES into a use of dispatch_sync(). Also, I suspect that wrapping the index in an NSNumber was intended to facilitate the indirect invocation of -setupPlayerForAsset:withIndex: and isn't strictly necessary or desired, either.
Regards,
Ken
_______________________________________________
Cocoa-dev mailing list (email@hidden)
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:
This email sent to email@hidden