亲爱的stackoverflow人,
就像上次一样,我特此提出一个我最近偶然发现的问题.我希望那里的某个人可以对我有所了解.
每当我尝试下载一个大文件的背后UIScrollView,MPMapView或者什么的,下载过程被当我触摸iPhone屏幕停止.值得庆幸的是,Jörn的一篇很棒的博客文章提出了一个替代选项,NSRunLoopCommonModes用于连接.
这让我看看两个模式的细节,NSDefaultRunLoopMode和NSRunLoopCommonModes,但苹果文档并没有好好解释,除了说
NSDefaultRunLoopMode
处理NSConnection对象以外的输入源的模式.这是最常用的运行循环模式.
NSRunLoopCommonModes
使用此值作为模式添加到运行循环的对象由已声明为"常用"模式集的成员的所有运行循环模式监视;有关详细信息,请参阅CFRunLoopAddCommonMode的说明.
CFRunLoopAddCommonMode
源,定时器和观察器被注册到一个或多个运行循环模式,并且仅在运行循环以其中一种模式运行时运行.常用模式是一组运行循环模式,您可以为其定义这些模式共享的一组源,定时器和观察器.例如,不是将源注册到每个特定的运行循环模式,而是可以将其注册到运行循环的公共伪模式,并且它将在共模模式集中的每个运行循环模式中自动注册.同样,当将模式添加到该组共用模式时,已经注册到公共伪模式的任何源,定时器或观察者被添加到新添加的共模.
有谁能用人类语言解释这两个?
谁能解释一下是NSRunLoop什么?所以我知道这NSRunLoop是一件与之相关的事情NSThread吗?所以假设我创建一个类似的线程
NSThread* th=[[NSThread alloc] initWithTarget:self selector:@selector(someMethod) object:nil];
[th start];
-(void) someMethod
{
    NSLog(@"operation");
}
在这个线程完成他的工作之后?为什么使用RunLoops或在哪里使用?从Apple docs我已经阅读了一些东西,但对我来说并不清楚,所以请尽可能简单地解释
我有一项需要每1秒执行一次的任务.目前我每隔1秒就有一次NSTimer重复射击.如何在后台线程(非UI线程)中触发计时器?
我可以在主线程上使用NSTimer激发然后使用NSBlockOperation来调度后台线程,但我想知道是否有更有效的方法来执行此操作.
我希望能够block在下一个运行循环迭代中执行a .它是否在下一个运行循环的开始或结束时执行并不是那么重要,只是执行被推迟到当前运行循环中的所有代码都已完成执行.
我知道以下内容不起作用,因为它与主运行循环交错,所以我的代码可能会在下一个运行循环中执行,但它可能不会.
dispatch_async(dispatch_get_main_queue(),^{
    //my code
});
以下我认为遇到与上述相同的问题:
dispatch_after(DISPATCH_TIME_NOW, dispatch_get_main_queue(), ^(void){
    //my code
});
现在我相信以下内容可以正常工作,因为它放在当前运行循环的末尾(如果我错了,请纠正我),这实际上有用吗?
[self performSelector:@selector(myMethod) withObject:nil afterDelay:0];
那个有0间隔的计时器怎么样?文档说明:If seconds is less than or equal to 0.0, this method chooses the nonnegative value of 0.1 milliseconds instead.这是否可以保证在下一次运行循环迭代中执行?
[NSTimer scheduledTimerWithTimeInterval:0 target:self selector:@selector(myMethod) userInfo:nil repeats:NO];
这是我能想到的所有选项,但我仍然没有接近于在下一次运行循环迭代中执行一个块(而不是调用方法),并保证它不会更快.
cocoa cocoa-touch objective-c grand-central-dispatch nsrunloop
所以我正在开始一个新的NSThread,我希望以后可以通过调用来使用它performSelector:onThread:....根据我的理解,调用方法将该调用添加到该线程上的runloop,因此在下一次迭代时,它将弹出所有这些调用,然后调用它们,直到没有任何东西可以调用.所以我需要这种功能,一个空闲的线程准备工作,我可以调用它.我当前的代码如下所示:
   - (void)doInitialize
   {
       mThread =  [[NSThread alloc] initWithTarget:self selector:@selector(runThread) object:nil];
       [mthread start];
   }
   - (void)runThread
   {
       NSAutoReleasePool *pool = [[NSAutoReleasePool alloc] init];
       // From what I understand from the Google machine is that this call should start the
       // runloop on this thread, but it DOESN'T. The thread dies and is un-callable
       [[NSRunLoop currentRunLoop] run];
       [pool drain];
   }
   - (void)scheduleSomethingOnThread
   {
       [self performSelector:@selector(hardWork) onThread:mThread withObject:nil waitUntilDone:NO];
   }
但是线程没有保持活动状态,performSelector:onThread没有做任何事情.我该怎么做正确的方法?
所以基本上,我有这个计时器,它应该在收到一个键事件时重复,并在用户释放键时失效.但是,即使通过调用addTimer:forMode:NSRunLoop ,我也无法"验证"计时器.有谁知道为什么会发生这种情况以及如何解决这个问题?谢谢.
以下是我所了解和理解的事情:
全局队列是一个并发队列,可以将任务分派给多个线程.执行任务的顺序无法保证.例如:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), {
 for (int i; i<10; i++) {
  doTask()
 }
})
如果我想调度到串口队列,我可以使用
dispatch_async(dispatch_queue_create("my.serial.queue", nil) {
  ...
}
每次只有一个任务被分派到一个线程并被执行.订单是FIFO.
=====我感到困惑和不完全理解=======
主线程有一个NSRunLoop,在主线程中循环任务.我想知道调度队列和运行循环之间的关系是什么?我可以理解它,如果将任务调度到主线程,主线程的NSRunLoop获取调度任务并执行它吗?
将任务分派给多个线程的全局队列怎么样?iOS/OSX系统是否自动创建线程,还为每个线程创建NSRunLoop?然后每个线程中的运行循环从全局队列中获取调度任务并执行它?
谁知道线程?do dispatch_async()和dispatch_sync()function知道哪个线程要调度任务,或者队列知道哪个线程要调度任务?
有没有办法以编程方式从调度队列中获取线程的NSRunLoop对象(调度任务的对象)?(这个问题与问题3有关)
multithreading nsthread grand-central-dispatch nsrunloop ios
我想知道是否有人可以解释为什么调度回主队列并创建重复NSTimer我不得不将它添加到RUN LOOP因为太火了?即使在使用时performselectorOnMainThread我仍然需要将它添加到RUN LOOP以使其触发.
以下是我的问题示例:
#define queue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
#define mainqueue dispatch_get_main_queue()
- (void)someMethodBeginCalled
{
    dispatch_async(queue, ^{
        int x = 0;
        dispatch_async(mainqueue, ^(void){
            if([_delegate respondsToSelector:@selector(complete:)])
                [_delegate complete:nil];
        });
    });
}
- (void)compelete:(id)object
{
    [self startTimer];
    //[self performSelectorOnMainThread:@selector(startTimer) withObject:nil waitUntilDone:NO];
}
- (void)startTimer
{
    NSTimer timer = [NSTimer timerWithTimeInterval:3 target:self selector:@selector(callsomethingelse) userInfo:nil repeats:YES];
    //NSDefaultRunLoopMode
    [[NSRunLoop currentRunLoop] addTimer:_busTimer forMode:NSRunLoopCommonModes];
}
编辑: 
我相信我措辞很差.如果我打电话,我想知道为什么 [[NSRunLoop currentRunLoop] addTimer:_busTimer forMode:NSRunLoopCommonModes];有必要.如果我不包括该行,则计时器不会触发.startTimersomeMethodBeginCalled
如果我呼吁startTimer来自viewDidLoad例如,我可以删除NSRunLoop线和计时器将每隔60秒射击.
我想知道为什么当你在GCD块中创建一个重复计时器时它不起作用?
这很好用:
-(void)viewDidLoad{
    [super viewDidLoad];
    [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(runTimer) userInfo:nil repeats:YES];
}
-(void)runTimer{
    NSLog(@"hi");
}
但这项工作:
dispatch_queue_t myQueue;
-(void)viewDidLoad{
    [super viewDidLoad];
    myQueue = dispatch_queue_create("someDescription", NULL);
    dispatch_async(myQueue, ^{
        [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(runTimer) userInfo:nil repeats:YES];
    });
}
-(void)runTimer{
    NSLog(@"hi");
}
nsrunloop ×10
objective-c ×7
ios ×5
cocoa ×4
nstimer ×4
cocoa-touch ×2
nsthread ×2
foundation ×1
iphone ×1
macos ×1
nsurlsession ×1
swift ×1