Ios 我应该在什么时候将Runloop应用于我的程序,为什么?

Ios 我应该在什么时候将Runloop应用于我的程序,为什么?,ios,objective-c,multithreading,performance,runloop,Ios,Objective C,Multithreading,Performance,Runloop,我的要求是,我想每6秒调用一个API从我的服务器请求一些新信息,因此我编写了如下代码: MyBackgroundThread(){ while(self.isStop){ [self callMyAPI]; [NSThread sleepfortimeinterval : 6 ]; } } MyBackgroundThread(){ NSTimer *timer = [NSTimer timerWithTimeInterval:6

我的要求是,我想每6秒调用一个API从我的服务器请求一些新信息,因此我编写了如下代码:

MyBackgroundThread(){

    while(self.isStop){
        [self callMyAPI]; 
        [NSThread sleepfortimeinterval : 6 ];
    }
}
MyBackgroundThread(){

    NSTimer *timer = [NSTimer timerWithTimeInterval:6 target:self selector:@selector(callMyAPI) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
    [timer release];
    while (! self.isCancelled) {
        BOOL ret = [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
    }
}

但我今天发现,基金会图书馆提供了一个写运行循环的方法。因此,我可以按如下方式重写代码:

MyBackgroundThread(){

    while(self.isStop){
        [self callMyAPI]; 
        [NSThread sleepfortimeinterval : 6 ];
    }
}
MyBackgroundThread(){

    NSTimer *timer = [NSTimer timerWithTimeInterval:6 target:self selector:@selector(callMyAPI) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
    [timer release];
    while (! self.isCancelled) {
        BOOL ret = [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
    }
}
然而,我不知道这是否是一个更好的方式来做我的工作比我原来的一个?如果是,为什么?我如何测试这两种方法在效率(或其他属性?)上的差异


谢谢

我认为通常没有必要为计时器创建新的运行循环。我建议两种方法中的一种:

  • 在主运行循环上调度
    NSTimer
    ,但让被调用的方法将请求分派到后台队列

  • 创建调度计时器,计划在指定的后台调度队列上运行。为此,请创建调度计时器属性:

    @property (nonatomic, strong) dispatch_source_t timer;
    
    然后实例化并启动调度计时器源,以便在指定的GCD队列上运行:

    dispatch_queue_t queue = dispatch_queue_create("com.domain.app.polltimer", 0);
    self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
    dispatch_source_set_timer(self.timer, dispatch_walltime(NULL, 0), kPollFrequencySeconds * NSEC_PER_SEC, 1ull * NSEC_PER_SEC);
    
    dispatch_source_set_event_handler(self.timer, ^{
        <#code to be run upon timer event#>
    });
    
    dispatch_resume(self.timer);
    
    这样就完全不需要计时器(和自定义运行循环)


    最后,如果您真的需要以这种频率检测系统更改,它可能会建议一种非常不同的服务器体系结构。例如,如果您每六秒轮询一次,看看服务器上是否发生了什么变化,您可以考虑基于套接字的实现或使用推送通知。在这两种方法中,服务器都会在重大事件发生时通知客户端应用程序,而不是像坐在汽车后座的巴特·辛普森(Bart Simpson)那样不断询问“我们到了吗?”


    适当的体系结构可能是服务器数据更改频率和客户端应用程序要求的函数。

    非常感谢!我正在尝试使用套接字,但是我不知道创建一个新的运行循环的合适时间是什么,而不仅仅是使用主线程创建的运行循环,并在从源代码中获取sth后分离一个新线程来处理事件?如果有可能对主运行循环产生不利影响,我可能倾向于创建另一个运行循环。但每六秒钟触发一次事件远没有达到这个临界值。而且,正如我所建议的,使用GCD定时器或方法后的调度,它可以解决棘手的问题。