DadEap Purple
DadEap Purple

Reputation: 91

Make an Array of Methods

I would like to create an NSArray of Methods.

I have the following code :

- (void) showText { NSLog(@"text1"); }
- (void) showText2 { NSLog(@"text2"); }
- (void) showText3 { NSLog(@"text3"); }

I would like to do something like this :

arrayOfMethods = [NSArray arrayWithObjects:[self showText], [self showText2], 
    [self showText3],  nil];

but it seems to not work because the return value is void and not an (id). But that's what i want !

The final goal is this :

[cell.button addTarget:self action:@selector([arrayOfMethods 
    objectAtIndex:indexPath.item]) forControlEvents:UIControlEventTouchUpInside];

Upvotes: 1

Views: 159

Answers (8)

matt
matt

Reputation: 535202

This would be a lot easier in Swift, because in Swift when you call addTarget:action:forControlEvents: what you pass for action: is a string. Thus you could just keep an array of strings.

So, your array would look like:

let arr = ["showText", "showText2", "showText3"]

...and you'd be all set. You'd pass e.g. arr[1] directly to action: when you call addTarget:action:forControlEvents:.


As it turns out, you didn't really need to "Make an Array of Methods", nor would it have done you any good to do so, because the action: parameter is a selector, not a method. However, the more general question you seemed to be asking - how to store an actual array of methods - is also trivial in Swift, because in Swift, methods are objects and can be stored in an array:

typealias V = () -> ()
var arr = V[]()
func showtext1 () { println ("text1") }
func showtext2 () { println ("text2") }
func showtext3 () { println ("text3") }
func makeArray () { // here's how to make the array
    arr = [self.showtext1, self.showtext2, self.showtext3]
}
func callArray () { // here's how to call all the methods in the array
    for m in arr {m()}
}

Upvotes: 0

BlaShadow
BlaShadow

Reputation: 11693

You may want to use block and pass them to a method and execute it.

NSArray *callbacks = @[
                       ^(){
                          // do some magics stuff                           
                       },
                        ^(){
                          // do some magics stuff   
                        },
                       ];

execute([callbacks objectAtIndex:0])

-(void) execute:(void (^)())block{
    block();
}

Upvotes: 3

Caleb
Caleb

Reputation: 124997

Methods are not objects, so aren't eligible to be stored in an NSArray. You could store strings to be used as selectors in an array, or you could store blocks that call the methods in question in an array, but not the methods themselves.

Array of strings for selectors:

NSArray *selectors = @[@"showText", @"showText2", @"showText3"];

You can then call one of these, say the middle one, like this:

SEL selector = NSSelectorFromString(selectors[1]);
[someObject performSelector:selector];

For the case you're considering, it's not clear that you even need methods at all; an array of blocks would do nicely.

Upvotes: 4

Ashley Mills
Ashley Mills

Reputation: 53111

You could try an array of NSInvocations:

NSArray * invocations = @[ [NSInvocation invocationWithMethodSignature: [NSMethodSignature methodSignatureForSelector: @selector(showText)]],
                           [NSInvocation invocationWithMethodSignature: [NSMethodSignature methodSignatureForSelector: @selector(showText2)]],
                           [NSInvocation invocationWithMethodSignature: [NSMethodSignature methodSignatureForSelector: @selector(showText3)]]];

UIButton * button;

for (NSInvocation * invocation in invocations) {
    [button addTarget: self action: invocation.selector forControlEvents: UIControlEventTouchUpInside];
}

Upvotes: 0

mvanallen
mvanallen

Reputation: 754

There are several ways to solve this, here's one that most closely matches your current implementation:

arrayOfMethods = @[ NSStringFromSelector(showText), NSStringFromSelector(showText2), NSStringFromSelector(showText3) ];

And then..

[cell.button addTarget:self action:NSSelectorFromString([arrayOfMethods 
objectAtIndex:indexPath.item]) forControlEvents:UIControlEventTouchUpInside];

(..error handling omitted for clarity..)

Other options include use of Blocks or using NSInvocation objects.

Upvotes: 1

Greg
Greg

Reputation: 25459

You can create C array with selectors:

SEL selectors[] = {@selector(showText), @selector(showText2), @selector(showText3)};

And after that just call it like that:

[cell.button addTarget:self action:selectors[indexPath.item] forControlEvents:UIControlEventTouchUpInside];

Please note that it will show warnings because selector is be unknown in compile time.

Upvotes: 0

Szu
Szu

Reputation: 2252

You may also use NSOperationQueue and NSInvocationOperation to store selectors and manage them. Here is a good tutorial: http://code.tutsplus.com/tutorials/working-with-the-nsoperationqueue-class--mobile-14993

Upvotes: 0

B.S.
B.S.

Reputation: 21726

Something like that:

   arrayOfMethods = [NSArray arrayWithObjects:NSStringFromSelector(@selector(showText)), ..,  nil];
   ...
   SEL action = NSSelectorFromString([arrayOfMethods 
    objectAtIndex:indexPath.item])

   [cell.button addTarget:self action:action forControlEvents:UIControlEventTouchUpInside];

Upvotes: 1

Related Questions