【问题标题】:performSelector:@selector withObject:nil afterDelay: not calls method (Objective C)performSelector:@selector withObject:nil afterDelay: 不调用方法(目标 C)
【发布时间】:2015-06-16 13:25:05
【问题描述】:

我尝试在早上通过委托实现警报和人员关系,并在每个环使用 performSelector:@selector withObject:nil afterDelay 后模拟延迟。但是没有执行函数调用,但是当我简单地使用 performSelector: - 它工作正常。全部在主线程中。有人可以解释一下吗?这是我的代码:

    #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;
}

【问题讨论】:

  • 创建一个名为selector 的ivar 如果这个想法很糟糕,它只会引起混乱。方法名称应该说明它们的作用。 `@synthesize1 也不是必需的,它会自动发生并创建一个名称前加“_”的 ivar,使用 self.ivar 进行访问。
  • 只有 sleep(delay) 与 #import "unistd.h" 一起使用。 [self performSelector:@selector(doAlarm) withObject:nil afterDelay:delay];和 [NSTimer timerWithTimeInterval:delay target:self selector:@selector(doAlarm) userInfo:nil repeats:NO];完全有效

标签: objective-c performselector


【解决方案1】:

我认为您的程序在延迟超时之前终止。尝试添加:

[[NSRunLoop currentRunLoop] run]

在您拨打goToSleepFor: 之后。

【讨论】:

    【解决方案2】:

    使用方法:

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

    该方法必须被定义为接受一个参数:

    - (void)doAlarm:(id)object {
    

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

    该方法必须被定义为接受一个参数:

    - (void)doAlarm {
    

    【讨论】:

    • performSelector:withObject:afterDelay: 的文档说:“标识要调用的方法的选择器。该方法不应具有重要的返回值,并且应采用 id 类型的单个参数,或者没有参数。"我认为这不是问题。
    • @Bruno Berisso 我同意。
    【解决方案3】:

    使用延迟执行选择器会将当前运行循环上的操作排队。您没有在程序中启动任何运行循环。您的程序只是简单地同步调用一些函数,这些函数返回然后您的程序退出。

    【讨论】:

    • 谢谢,它有效。添加后 CFLoopRun(); [tiredPerson goSleepFor:10.0f] 之后;延迟工作正常,但应用程序在所有操作后都没有退出。所以 CFRunLoopStop(CFRunLoopGetCurrent());已添加到 standUp 方法中,应用程序正常退出。
    【解决方案4】:

    如果您的代码在运行循环处于默认模式以外的模式时正在运行,请尝试以下操作:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-10-06
      • 1970-01-01
      • 2012-08-13
      • 1970-01-01
      • 2010-12-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多