performSelector:@selector withObject:nil afterDelay: not calls method (Objective C)

1k views Asked by At

I tried to implement alarm and person relations in the morning through delegate and to simulate delays after each ring used performSelector:@selector withObject:nil afterDelay. But no function calls performed, but when I use simply performSelector: - it works fine. All in main thread. Can somebody explain that? Here is my code:

    #import <Foundation/Foundation.h>

    @protocol MyDelegateProtocol <NSObject>

    @optional
    - (void) wakeUp;
    - (void) standUp;

    @end

#import <Foundation/Foundation.h>
#import "myDelegateProtocol.h"

@interface Alarm : NSObject

@property (nonatomic, weak) id <MyDelegateProtocol> delegate;
@property (nonatomic, assign) NSUInteger ringsLeft;
@property (nonatomic, assign) SEL selector;

- (void) setAlarm: (CGFloat) delay;
- (void) fiveMinutesMore;
- (id) initWithRings: (NSUInteger) rings;
- (void) doAlarm;


@end

#import "Alarm.h"

@implementation Alarm

@synthesize delegate;
@synthesize selector;

- (id) initWithRings:(NSUInteger)rings
{
    self = [super init];
    if (self) {
        self.ringsLeft = rings;
    }
    return self;
}
- (void)setAlarm:(CGFloat)delay {
    if (delegate) {
        if (self.ringsLeft>0) {
            self.ringsLeft--;
            selector = @selector(wakeUp);
        } else {
            selector = @selector(standUp);
        }
    }
    if ([delegate respondsToSelector:selector]) {
        [self performSelector:@selector(doAlarm)];
//        [self performSelector:@selector(doAlarm) withObject:nil afterDelay:delay];
    }
}
- (void)doAlarm {
    [delegate performSelector:selector];
}
- (void)fiveMinutesMore {
    [self setAlarm:1.0];
}

@end

#import <Foundation/Foundation.h>
#import "Alarm.h"

@interface Person : NSObject <MyDelegateProtocol>

@property (nonatomic,assign) NSUInteger chanceToWakeUp;
@property (nonatomic,strong) Alarm *myAlarm;

- (void) goSleepFor: (CGFloat) seconds;
- (id) init;

@end

#import "Person.h"

@implementation Person

@synthesize chanceToWakeUp;
@synthesize myAlarm;

-(void) goSleepFor:(CGFloat)seconds
{
    NSLog(@"Going for a sleep");
    [myAlarm setAlarm:seconds];
}
-(void) wakeUp
{
    NSLog(@"Ringing...");
    NSUInteger randomNumber = arc4random_uniform(6);
    if (randomNumber>chanceToWakeUp) {
        chanceToWakeUp++;
        NSLog(@"Person takes five minutes more to sleep");
        [myAlarm fiveMinutesMore];
    } else {
        [self standUp];
    }
}
-(void) standUp
{
    NSLog(@"Person stand's up");
}
-(id) init
{
    self = [super init];
    if (self) {
        chanceToWakeUp=0;
        myAlarm = [[Alarm alloc] initWithRings:5];
        myAlarm.delegate=self;
    }
    return self;
}

@end

#import <Foundation/Foundation.h>
#import "Person.h"


int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Person *tiredPerson = [[Person alloc] init];
        [tiredPerson goSleepFor:10.0f];
    }
    return 0;
}
4

There are 4 answers

2
zaph On

To use:

[self performSelector:@selector(doAlarm:) withObject:nil afterDelay:delay];

the method must be defined to take an argument:

- (void)doAlarm:(id)object {

or

[self performSelector:@selector(doAlarm) withObject:nil afterDelay:delay];

the method must be defined to take an argument:

- (void)doAlarm {
0
Bruno Berisso On

I think your program is terminating before your delay time out. Try adding:

[[NSRunLoop currentRunLoop] run]

after your goToSleepFor: call.

1
newacct On

Performing a selector with delay queues the operation on the current run loop. You didn't start any run loops in your program. Your program simply calls some functions synchronously which return and then your program exits.

0
Jim75 On

if your code is running when the run loop is in a mode other than the default mode, try this:

        [self performSelector:@selector(doAlarm) withObject:nil
               afterDelay:delay
                  inModes:@[[[NSRunLoop currentRunLoop] currentMode]]];