标签: nsrunloop

如何包装异步类以使其同步?使用NSRunLoop?

我目前正在开发一个iPhone应用程序,我有一个来自第三方的库,它有异步行为,但是我想用自己的类包装并使它看起来是同步的.

这个库中的中心类,我们称之为Connection类,有几个函数在调用委托类的实例上的方法时解析它们的最终结果.我正在尝试做的是包装这个类和委托,使它看起来是同步的而不是异步的.如果我在Java中这样做,我会使用FutureTask或CountdownLatch或只是join().但我不确定目标C中最好的方法.

我首先创建了一个NSThread扩展,NFCThread,它符合上面提到的委托协议.我的想法是我将init和NFCThread,将NFCThread实例传递给Connection的setDelegate方法,启动线程然后在Connection上调用异步方法.我的期望是NFCThread实例上的三个委托方法之一将被调用,最终导致线程退出.

为了模拟连接,我做了以下操作.我在NFCThread中添加了一个NSConditionalLock:

joinLock = [[NSConditionLock alloc] initWithCondition:NO];
Run Code Online (Sandbox Code Playgroud)

调用Connection的代码看起来像这样:

NFCThread *t = [[NFCThread alloc] init];
[connection setDelegate:t];
[t start];

[connection openSession];
// Process errors, etc...

[t.joinLock lockWhenCondition:YES];
[t.joinLock unlock];
[t release];
[connection setDelegate:nil];
Run Code Online (Sandbox Code Playgroud)

委托的协议有三种方法.在NFCThread中我实现了每个方法,如下所示:

- (void)didReceiveMessage:(CommandType)cmdType 
                     data:(NSString *)responseData 
               length:(NSInteger)length {
    NSLog(@"didReceiveMessage");
    // Do something with data and cmdType...
    [joinLock lock];
    [joinLock unlockWithCondition:YES];
    callBackInvoked = YES;
}
Run Code Online (Sandbox Code Playgroud)

我重载了NFCThread的主要方法,以便它不断循环.像这样的东西:

while (!callBackInvoked) { ; }
Run Code Online (Sandbox Code Playgroud)

我发现这不是一个好主意,因为它会导致cpu使用率通过屋顶.所以我尝试使用我在这个网站上找到的一些例子的运行循环:

NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
[runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];

while (!callBackInvoked) {
    [runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; …
Run Code Online (Sandbox Code Playgroud)

multithreading objective-c nsrunloop

6
推荐指数
1
解决办法
3639
查看次数

AVPlayerStatus与AVPlayerItemStatus

问题是player.status AVPlayerStatusReadyToPlay在player.currentItem.status返回之前返回完整的2秒AVPlayerItemStatusReadyToPlay.有没有人对为什么会这样做有任何有用的解释?
这只是示例代码,以显示正在发生的事情的基本概念,所以如果有任何拼写错误或其他什么请忽略它们.

- (void) someMethod
{    
    player = [[AVPlayer alloc] initWithURL:someValidURL];
    [player play];

    NSTimer *timer = [NSTimer timerWithTimeInterval:0.1 target:self selector:@selector(checkStatus:) userInfo:nil repeats:YES];
    [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
}

- (void) checkStatus: (NSTimer *)timer
{
    NSLog(@"player status: %i", player.status]);
    NSLog(@"player item status: %i", player.currentItem.status]);
}
Run Code Online (Sandbox Code Playgroud)

iphone nstimer nsrunloop avplayer

6
推荐指数
1
解决办法
1118
查看次数

不允许在Web线程上进行多次锁定!请提交一个错误.现在崩溃了

我做了一个url-Request并等待答案

我启动请求,然后等待,直到synchronousOperationComplete = TRUE

NSRunLoop *theRL = [NSRunLoop currentRunLoop];

while (!synchronousOperationComplete && [theRL runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]);
Run Code Online (Sandbox Code Playgroud)

然后我回复了

一切似乎都没问题,我得到了回应,一切正常,但当我关闭应用程序时,我得到:

bool _WebTryThreadLock(bool), 0x227f40: Multiple locks on web thread not allowed! Please file a bug. Crashing now...

1   _ZL17_WebTryThreadLockb
2   _ZL14WebRunLoopLockP19__CFRunLoopObservermPv
3   __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__
4   __CFRunLoopDoObservers
5   __CFRunLoopRun
6   CFRunLoopRunSpecific
7   CFRunLoopRunInMode
8   _ZL12RunWebThreadPv
9   _pthread_start
10  thread_start
Run Code Online (Sandbox Code Playgroud)

它似乎是NSRunLoop导致错误的原因,当我推荐它时,错误没有出现.

我使用IOS 5.0确实有人知道我可以做些什么来避免这个错误?

我在IOS 4.3和IOS5 Beta中使用它,它工作正常.

但我把我的tomcat6移动到另一台服务器,也许这是服务器的错误

THX mBax

objective-c nsurlconnection nsrunloop

6
推荐指数
1
解决办法
9208
查看次数

在NSOperation中使用NSThread睡眠

使用一些代码,我遇到了运行循环,我是新手,在NSOperations 里面.

他们NSOperation正在忙于下载数据 - 当他们忙碌时,会有代码等待下载完成,以NSRunLoops和线程休眠的形式.

我特别感兴趣的是这段代码:

while (aCertainConditionIsTrue && [self isCancelled]==NO) {
     if(![[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:1.0]]){
        [NSThread sleepForTimeInterval:1.0];
     }
}
Run Code Online (Sandbox Code Playgroud)

我已经阅读了关于运行循环的信息,runMode:beforeDate:并将等待输入源或超时.虽然我不是百分之百的东西.

在第一次执行时,它总是返回NO并命中sleepForTimeInterval:.这不好吗?

在一个特定的实用程序类中,它经常会sleepForTimeInterval:遇到很多 - 每个线程一次 - 这会严重损害性能.

对此有什么更好的解决方案或建议吗?

objective-c nsoperation grand-central-dispatch nsrunloop ios

6
推荐指数
1
解决办法
3633
查看次数

NSTimer和NSRunLoop

我的应用跟踪用户CLLocationManager.在委托电话中,didUpdateToLocation我做了所有有趣的事情来保存他们的位置.但是,我需要一种方法来测试它们是否已停止.我可以停止记录位置并考虑他们的旅行.所以我有一个NSTimerCCLocationManager那个被添加,每次取出didUpdateToLocation被调用.当用户停止并CLLocationManager停止被叫时,它将被启动.

我能够完成NSTimer工作的唯一方法是:

[[NSRunLoop mainRunLoop] addTimer:userStoppedMovingTimer forMode:NSRunLoopCommonModes];
Run Code Online (Sandbox Code Playgroud)

然后删除它:

[userStoppedMovingTimer invalidate];
Run Code Online (Sandbox Code Playgroud)

我以前从来没有像这样添加计时器.有人可以解释为什么会这样吗?

objective-c nstimer nsrunloop cllocationmanager

6
推荐指数
1
解决办法
7158
查看次数

scheduleInRunLoop - 线程网络连接

我没有找到任何可以解释NSStream线程化过程的文档.具体来说,让我们去NSInputStream.在Objective-C中对我的线程目前是一个谜,因为它看起来如此简单.

我的问题主要是指这一行:

[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
Run Code Online (Sandbox Code Playgroud)

您可以指定输入流将运行的运行循环,我认为这很酷.问题是,如果我希望输入和输出流在他们自己的线程中运行,并且两者都在单个类中实例化,比如Connection,那么如何让它们在自己的线程中运行?

我问的原因是因为代表们.以前我们已经完成了[inputStream setDelegate:self]这意味着我们必须声明stream:handleEvent处理传入/传出数据.

所以最后我的问题是,如果你有一个设置输入和输出流的类,你如何将每个流线程化并将处理流事件的责任委托给当前的类?

这里有一些代码可供选择:

[inputStream setDelegate:self];
[outputStream setDelegate:self];
[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[inputStream open];
[outputStream open];
Run Code Online (Sandbox Code Playgroud)

我在想以下几点:

  • 您不能委派当前类中的两个线程的责任,您必须委托给单独的对象.
  • 一个线程可以为两个流做什么?(我个人并不这么认为,因为输入/输出会同时运行)
  • 我认为这是错误的,你可以创建一个单独的运行循环并调用scheduleRunLoop对一些单独的线程?

有任何想法吗?

cocoa multithreading objective-c nsstream nsrunloop

6
推荐指数
1
解决办法
3449
查看次数

NSRunLoop runMode并不总是处理dispatch_async

我试图更好地了解队列及其工作原理。这个片段是为了测试他们的行为:

- (void)dispatchQueueTest
{
    NSLog( @"Begin test on %@ thread", [NSThread isMainThread] ? @"main" : @"other" );
    dispatch_semaphore_t s = dispatch_semaphore_create(0);

    dispatch_async( dispatch_get_main_queue(), ^{
        NSLog( @"Signalling semaphore" );
        dispatch_semaphore_signal(s);
    });

    NSLog( @"Waiting for worker" );
    while( dispatch_semaphore_wait( s, DISPATCH_TIME_NOW ) ) {
        NSDate* timeout = [NSDate dateWithTimeIntervalSinceNow:10.f];
        // Process events on the run loop
        [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:timeout];
    }
    dispatch_release(s);
    NSLog( @"All sync'd up" );
}
Run Code Online (Sandbox Code Playgroud)

正如预期的那样,它会在日志中生成以下内容:

Begin test on main thread
Waiting for worker
Signalling semaphore
All sync'd up …
Run Code Online (Sandbox Code Playgroud)

objective-c grand-central-dispatch nsrunloop dispatch-async

5
推荐指数
1
解决办法
1413
查看次数

使用GCD如何处理NSStream run loop调度带来的并发问题?

我有以下情况,我创建了一个 GCD 调度队列,并在其中将 an 调度NSStream到当前NSRunLoop,正如其规范中要求它发出委托事件,然后我使用[[NSRunLoop currentRunLoop run].

这会产生三种可能的情况:

  1. 创建一个串行队列,其中通过流发送初始写入消息,并且仅当存在来自NSStream对象的委托回调时才发送其他写入消息,因为尝试在不遵守此模式的情况下写入新消息(这将是可取的)将失败,因为队列被运行循环锁定。

  2. 创建一个并发队列,在该队列中消息可以自由写入流,因为发送到队列的块将与运行运行循环的块同时执行。然而,虽然希望使写入消息和运行循环并发运行,但肯定不希望必须在并发运行的队列中阻塞同时尝试写入流。

  3. 创建两个队列——一个负责保持 run loop 处于活动状态并接收 read-from-stream 回调,另一个负责向流发送异步写入消息。这看起来很理想,但是NSStream文档似乎明确指出不应尝试在调度的线程之外读取/写入流。

鉴于这些场景都不理想,如何解决这些问题?

concurrency cocoa-touch nsstream grand-central-dispatch nsrunloop

5
推荐指数
2
解决办法
1205
查看次数

Swift 中严格调度的循环计时

以非常严格的时间安排重复任务的最佳方法是什么(对于音乐排序足够准确和可靠)?从 Apple 文档中,很明显 NSTimer 在这个意义上是不可靠的(即“计时器不是实时机制”)。我从 AudioKit 的AKPlaygroundLoop借用的一种方法在大约 4 毫秒内似乎是一致的(如果不是很准确),并且可能是可行的:

class JHLoop: NSObject{
    var trigger: Int {
        return Int(60 * duration)  // 60fps * t in seconds
    }
    var counter: Int = 0
    var duration: Double  = 1.0 // in seconds, but actual loop is ~1.017s
    var displayLink: CADisplayLink?
    weak var delegate: JHLoopDelegate?

    init(dur: Double) {
        duration = dur
    }

    func stopLoop() {
        displayLink?.invalidate()
    }

    func startLoop() {
        counter = 0
        displayLink = CADisplayLink(target: self, selector: "update")
        displayLink?.frameInterval = …
Run Code Online (Sandbox Code Playgroud)

nstimer nsrunloop ios swift

5
推荐指数
1
解决办法
727
查看次数

将自定义输入源附加到 Swift 中的运行循环

有谁知道如何使用 Swift 语言将自定义输入源附加到运行循环?我正在关注这个文档:特别是运行循环:“配置运行循环源”,但我还没有弄清楚如何快速使用它。

multithreading input nsrunloop swift

5
推荐指数
0
解决办法
411
查看次数