Neil Shweky
Neil Shweky

Reputation: 893

Can you store functions in an array in Objective-C?

I want to make an array of functions so that I could randomize the order in which the functions are called. Could I do something like:

NSMutableArray *MyArray =
    [NSMutableArray arrayWithObjects: function1, function2, function3, nil];

So that I could then do something like this:

RandomNum = arc4random() %([MyArray count]);
MyArray[RandomNum];

Thus randomizing the order in which these functions are called?

How do I store functions in an array?

Upvotes: 6

Views: 3629

Answers (4)

Daij-Djan
Daij-Djan

Reputation: 50109

There ways come to mind

  1. you can store blocks in an array
  2. but you can also method invocations there if you want to call methods and not blocks (you would do the latter via NSInvocation)
  3. For C functions, wrap them in an NSValue to store them and call em later

sample 1 -- blocks

    NSMutableArray *array = [NSMutableArray array];
    [array addObject:^{ /* block */ }];

sample 2 -- invocation

    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[object methodSignatureForSelector:selector]];
    invocation.target = object;
    invocation.selector = selector;
    [array addObject:invocation];

sample 3 -- C-Function

    [NSValue valueWithPointer:function1]

Upvotes: 4

shannoga
shannoga

Reputation: 19869

Blocks will be the best approach, but I you are not familiar with blocks or from ant other reason you can use: NSSelectorFromString & NSStringFromSelector.

EDITED

  1. Store the methods in array with NSStringFromSelector
  2. You can then shuffle the array as described here : Shuffling array
  3. call the functions using NSSelectorFromString.

For Example

NSArray * functions = @[NSStringFromSelector(selector1),NSStringFromSelector(selector2),
NSStringFromSelector(selector3),NSStringFromSelector(selector4)];

//shuffle the array (see link)
 [functions shuffle];

 [arr enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
       [self performSelector:NSSelectorFromString(functions[idx]) withObject:nil];
 }];

(The code was written on the fly, please check it out).

Upvotes: 1

Jano
Jano

Reputation: 63697

Store a pointer to a function in an array and call the function:

#import <Foundation/Foundation.h>

static void hello() {
    NSLog(@"hey\n");
}

int main(int argc, char *argv[]) {
    @autoreleasepool {
        NSPointerArray *array = [NSPointerArray pointerArrayWithOptions:NSPointerFunctionsOpaqueMemory];
        [array addPointer: &hello];
        void* ptr = [array pointerAtIndex:0];
        ((void (*)(void)) ptr)(); // prints hey
    }
}

Upvotes: 1

Bartosz Ciechanowski
Bartosz Ciechanowski

Reputation: 10333

As for ObjC blocks you can just store them in an NSArray directly. Plain C functions have to be wrapped into an NSValue:

NSArray *functions = @[[NSValue valueWithPointer:function1], [NSValue valueWithPointer:function2]];

Then you can call them as follow, just make sure you cast it to correct signature:

((void (*)(int))[functions[RandomNum] pointerValue])(10);

Upvotes: 4

Related Questions