• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: blocks and NSInvocation question
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

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

References: 
 >blocks and NSInvocation question (From: John Michael Zorko <email@hidden>)

  • Prev by Date: Re: Storing a block in a CF/NSMutableDictionary?
  • Next by Date: Re: AVFoundation and OpenGL?
  • Previous by thread: blocks and NSInvocation question
  • Next by thread: Determine Error from Webview loadRequest
  • Index(es):
    • Date
    • Thread