2
votes

I'm trying to pass a float through a selector using 'withObject:' however, it only accepts objects.

There are solutions that tell me to use [NSNumber numberWithFloat: ] however it's messing with the value of my float. I am doing a before and after testing of the values of the float, and beforehand I get numbers such as 0.0034324, whereas afterwards they are all 0.0000000

[[self gameObjects] makeObjectsPerformSelector:@selector(update:) withObject: <what to put here>]];

Thanks in advance!

EDIT*

here is the context

-(void) tick:(float)dt{
    NSLog(@"%f",dt)
    [[self gameObjects] makeObjectsPerformSelector:@selector(update:) withObject:[NSNumber numberWithFloat:dt]];

}

The number outputted from above is NOT 0

But from the selector method....

- (void)update:(float)dt{

    NSLog(@"%f",dt);

}

The output is 0

5
Can you show the example where you were seeing 0.0000000? You should fix that, because wrapping the float in an NSNumber is the right answer. You just made some mistake in the implementation of it. - Firoze Lafeer
Indeed; it's a safe bet that if you think you were getting 0.00000 then you were taking the floatValue of nil rather than of an actual number. - Tommy
Show the declaration for update:. What is the parameter type? It can't be of type float since you need to pass it an NSNumber. - rmaddy
That's not possible this way because Objective-C doesn't perform autoboxing. You either have to do this yourself in an other method, use NSInvocation or use the method described here - JDS
NSNumber will not "mess" with the value of your float, if you do it right. The problem is that you're not receiving an NSNumber in your target method, but rather trying to interpret a pointer to an NSNumber as a float. - Hot Licks

5 Answers

4
votes

You should wrap the float in an NSNumber.

NSNumber * num = [NSNumber numberWithFloat:5.5];

EDIT: As rmaddy has pointed out, here are some other ways to use NSNumber *

NSNumber * num = @5.5f;
float someFloat = 5.5f;
NSNumber * num1 = @(someFloat);

To OP, We need to see more of your code to help dissect the actual problem

Update to respond to new context

In your target method you are specifying that you expect a (float) as the expected argument. It is important to be cognizant of the type of variable you are passing to functions. Notice the last argument to your makeObjectsPerformSelector method is prefaced as withObject. This indicates you are passing an object, not a primitive float. So wrap the float you want to pass in an NSNumber as such:

NSNumber * numToPass = @(floatToWrap);
[[self gameObjects] makeObjectsPerformSelector:@selector(update:) withObject:numToPass]];

- (void)update:(NSNumber *)dt {

    NSLog(@"%f",dt.floatValue); // or [dt floatValue];

}

Hope this helps

0
votes

As stated by others, you've made some mistake in your attempt to use NSNumbers and would probably be better off asking us to look at that code.

I ran the following:

float value = 0.0034324f;
NSNumber *valueObject = @(value);

NSLog(@"%0.7f, %@", value, valueObject);

Output was:

2013-07-12 17:45:07.948 Untitled[4950:707] 0.0034324, 0.0034324
0
votes

The issue was that I didn't change my selected method to accomodate an NSNumber, as it still had a float as its parameter type.

Thanks for the help everybody.

0
votes
[[self gameObjects] makeObjectsPerformSelector:@selector(update:) withObject:[NSNumber numberWithFloat:dt]];

Calls a selector that has a float argument. Chang the update: argument to NSNumber and inside it call floatValue on the NSNumber

Probably better to just do a for-in loop on your array of gameObjects than all this performSelector and NSNumber business. In the loop call the update netheid directly.

0
votes

You are looking for NSInvocation. It's not the most pleasant thing to write, but it does exactly what you asked for:

- (void)update:(CGFloat)value
{
    XCTAssertEqualsWithAccuracy(value, 2.1, 0.001, @"");
}

- (void)testNSInvocationOverArrayWithFloatArgument
{
    CGFloat value = 2.1;
    NSArray *gameObjects = @[ self ];

    for (id object in gameObjects) {
        NSMethodSignature *signature = [object methodSignatureForSelector:@selector(update:)];
        NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];

        [invocation setTarget:object];
        [invocation setSelector:@selector(update:)];
        [invocation setArgument:&value atIndex:2];

        [invocation invoke];
    }
}