Re: BOOL returned via -performSelctor: not BOOL on 64-bit system
Re: BOOL returned via -performSelctor: not BOOL on 64-bit system
- Subject: Re: BOOL returned via -performSelctor: not BOOL on 64-bit system
- From: Alexander Heinz <email@hidden>
- Date: Tue, 8 Jun 2010 13:53:30 -0400
On Jun 8, 2010, at 1:37 PM, Jean-Daniel Dupas wrote:
>
> Le 8 juin 2010 à 19:23, James Bucanek a écrit :
>
>> Nick Zitzmann <mailto:email@hidden> wrote (Tuesday, June 8, 2010 9:27 AM -0600):
>>
>>> On Jun 8, 2010, at 10:16 AM, James Bucanek wrote:
>>>
>>>> I've been trying to track down a peculiar bug reported by a customer, and I've narrowed it down to a problem returning a BOOL value via
>>> -[NSObject performSelector:] on a dual Quad-Core Intel Xeon processor running 64-bit code. It seems that the returned value contains random data, which obscures the BOOL.
>>>>
>>>> I've included the relevant code from the project below for completeness, but the problem boils down to this statement:
>>>>
>>>> if ([condition performSelector:conditionSelector]!=NO)
>>>
>>> According to the documentation, that method returns an object, not a primitive. You can't use it if the selector returns a primitive; it doesn't work that way. If you want to call some selector and get a BOOL return value, then you must do this instead:
>>>
>>> BOOL returnValue = ((BOOL (*)(id, SEL))objc_msgSend)(condition, conditionSelector);
>>
>> For the record, the following is equivalent (i.e. produces the same machine code) and is probably a little easier to read:
>>
>> BOOL returnValue = (BOOL)((uintptr_t)[condition performSelector:conditionSelector]);
>
> It's not more valid though. -performSelector must be used only with selector that return an object.
>
> From the -performSelector reference:
>
> "For methods that return anything other than an object, use NSInvocation."
Alternatively, if you can alter the method being called, (which I assume you can, since you posted the source) you could change the methods to return an NSNumber-wrapped boolean value, rather than a scalar value.
(Standard "written-in-Mail" warning applies)
> - (NSNumber*)shouldCancelAction
> {
> // if this condition causes actions to be skipped, apply the condition
> return [NSNumber numberWithBool:( [self canCancelAction] ? [self test] : NO )];
> }
>
> - (NSNumber*)shouldHoldAction
> {
> // if this condition causes actions to be held, apply the condition
> return [NSNumber numberWithBool:( [self canHoldAction] ? [self test] : NO )];
> }
>
> - (NSNumber*)shouldStopAction
> {
> // If this condition causes actions to abort, apply the condition
> return [NSNumber numberWithBool:( [self canStopAction] ? [self test] : NO )];
> }
And the conditional statements change to the form:
> if (![[condition performSelector:conditionSelector] boolValue])
This is certainly the least performant of the recommended solutions, but if that's not a major concern, this would be my preferred way, since I think it's the easiest to read.
- Alex_______________________________________________
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