简体   繁体   中英

How can I make super the target of an NSTimer?

I'm trying to use a NSTimer to call a function in an class's superclass.

The function works if I call it like this:

[super playNarrationForPage:[NSNumber numberWithInt:1]];

But if I do this:

NSTimer *narrationTimer = [NSTimer scheduledTimerWithTimeInterval:7.5
                                                           target:self.superclass
                                                           selector:@selector(playNarrationForPage:) 
                                                           userInfo:[NSNumber numberWithInt:1] 
                                                           repeats:NO
                          ];

I get this error: unrecognized selector sent to class 0x106890 2012-07-06 21:14:59.522 MyApp[19955:707] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+[MyBaseClass playNarrationForPage:]: unrecognized selector sent to class 0x106890'

I've tried setting super as the target: but I'm told "Use of undeclared identifier super". Any thoughts?

Since self.superclass returns a Class object, it's definitely not what you want.

Also, you don't seem to understand how an NSTimer calls its target. You're using an NSNumber as the timer's userInfo , and your playNarrationForPage: method seems to expect an NSNumber argument. But an NSTimer does not pass its userInfo as the argument when it calls its target! The NSTimer passes itself as the argument, like this:

// self is the NSTimer object here!
[self.target performSelector:self.selector withObject:self];

You must create a new method for your timer to call. This new method needs to take the timer as its argument, like this:

- (void)narrationTimerDidFire:(NSTimer *)timer {
    [self playNarrationForPage:timer.userInfo];
}

Then you need to use that selector when you create your timer:

NSTimer *narrationTimer = [NSTimer scheduledTimerWithTimeInterval:7.5
    target:self
    selector:@selector(narrationTimerDidFire:)
    userInfo:[NSNumber numberWithInt:1]
    repeats:NO];

If you really want to make narrationTimerDidFire: call [super playNarrationForPage:] , the compiler will let you. But doing that is very fishy . If you haven't overridden playNarrationForPage: in your subclass, then there's no reason to refer to super directly; your subclass inherits its superclass's playNarrationForPage: method. If you have overridden playNarrationForPage: in your subclass, then bypassing it from your timer's callback indicates that something is wrong with your design.

The only time you should use super is when you are in a method and want to call the superclass's implementation of the same method (including indirectly -- see below).

self.superclass doesn't make sense as the target of the timer unless your goal is to call a class method on the superclass.

Just use self as the target. If that won't work because you are overriding playNarrationForPage: and want to delay the invocation to super, then create a separate method that does something like:

- (void) _delayedDoIt
{
     [super playNarrationForPage:1];
}

And call that from self's implementation of playNarrationForPage: via the timer.

You cannot directly tell it to call the super method. target is only a pointer to an object, super does not have a separate pointer address from your self instance.

Also by assigning the target to self.superclass you are telling the target to be the class. Therefore your trying call a class method rather than an instance method which is not what you want to do.

The only way to do this would be to assign target to self and have a separate method such as:

- (void)callSuperMethod
{
    [super playNarrationForPage:[NSNumber numberWithInt:1]];
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM