我可以在不使用NSTimer的情况下使用连续后台线程更新iPhone UI吗?
比如说,如果我从www.example.com/number上阅读,我会得到一个随机数。在我的iPhone应用程序中,我希望能够连续读取该地址,并在每次请求完成后在屏幕上显示新号码。我们还假设我希望这个过程在视图加载后立即开始。最后,作为旁注,我将使用简化web请求 方法1:在viewDidLoad方法中,我可以在一个循环中同步读取URL(在收到HTTP请求的响应之前,执行不会继续)。优点:请求是串行的,我可以完全控制对每个请求的响应。缺点:UI从未更新,因为我从未退出函数并将控制权交还给运行时循环。显然,这不是一个好的解决方案 方法2:在viewDidLoad方法中,我创建了一个计时器,它每秒调用一次fetchURL函数。优点:每个请求都在一个单独的线程中,每个请求完成后UI都会更新。缺点:请求在单独的线程中,无法很好地控制。例如,如果在第一次请求时存在连接超时,我希望能够显示错误弹出窗口,并且在更改设置之前不会发生任何进一步的请求。但是,使用这种方法,如果超时需要3秒钟,那么在这段时间内,将已经启动了另外两个请求。如果我只是放慢了定时器的速度,那么当连接正常工作时,数据进入的速度就太慢了 似乎应该有某种方法将我提到的前两种方法的优点结合起来。我想要一种方式,我可以决定是否不发送下一个请求的基础上的结果,前一个请求 方法3:我考虑使用一个触发更快的计时器(比如说每.25秒),但是让计时器的功能检查一个标志,看看下一步该怎么做。因此,如果前一个请求已完成,它将发送一个新请求(除非有错误)。否则,如果前一个请求尚未完成,计时器的函数将返回,而不发送新的请求。通过更快地启动此计时器,您将获得更好的响应时间,但该标志将让我获得所需的同步我可以在不使用NSTimer的情况下使用连续后台线程更新iPhone UI吗?,iphone,objective-c,architecture,multithreading,Iphone,Objective C,Architecture,Multithreading,比如说,如果我从www.example.com/number上阅读,我会得到一个随机数。在我的iPhone应用程序中,我希望能够连续读取该地址,并在每次请求完成后在屏幕上显示新号码。我们还假设我希望这个过程在视图加载后立即开始。最后,作为旁注,我将使用简化web请求 方法1:在viewDidLoad方法中,我可以在一个循环中同步读取URL(在收到HTTP请求的响应之前,执行不会继续)。优点:请求是串行的,我可以完全控制对每个请求的响应。缺点:UI从未更新,因为我从未退出函数并将控制权交还给运行时
看起来方法3可以满足我的要求,但也有点强迫。有没有人对此有更好的方法的建议,或者类似于方法3的方法是最好的方法?我相信NSOperation是您所需要的。使用上面的1号解决方案,但将代码放在NSO操作的主方法中。大概是这样的: .h文件
@interface MyRandomNumberFetcher : NSOperation {
}
@end
.m文件
@implementation MyRandomNumberFetcher
- (void) main {
// This is where you start the web service calls.
}
@end
我还建议添加对UI控制器的引用,以便您的操作队列类可以在适当的时候调用它。我相信NSOperation就是您所需要的。使用上面的1号解决方案,但将代码放在NSO操作的主方法中。大概是这样的: .h文件
@interface MyRandomNumberFetcher : NSOperation {
}
@end
.m文件
@implementation MyRandomNumberFetcher
- (void) main {
// This is where you start the web service calls.
}
@end
我还建议添加对UI控制器的引用,以便您的操作队列类可以在适当的时候调用它。这里还有另一个建议。创建一个NSOperationQueue,它将在不同的线程上运行您的请求。如果发现需要刷新UI,请调用performSelectorOnMainThread。请求完成后,创建另一个请求并将其添加到队列中。将队列设置为一次只运行一个操作
这样,您就不会同时运行两个请求。这里还有另一个建议。创建一个NSOperationQueue,它将在不同的线程上运行您的请求。如果发现需要刷新UI,请调用performSelectorOnMainThread。请求完成后,创建另一个请求并将其添加到队列中。将队列设置为一次只运行一个操作
这样你就不会有两个请求同时运行。你可以用更少的代码和资源使用GCD来实现这一点。这就是你可以做到的: 在
viewDidLoad
中,异步调用执行以下操作的块(使用dispatch\u async
):
dispatch\u after
)setNeedsDisplay
dispatch\u get\u main\u queue
来获取此队列。然后将其视为任何其他队列(例如,您可以通过调用dispatch\u async
)来添加块)NSObject
的performselectornmainthread:withObject:waituntldone:
方法这就是说,您永远不应该如此频繁地执行小请求(除非用于获取游戏数据之类的特定任务)。它将通过阻止天线休眠来严重缩短电池寿命。您可以使用GCD以更少的代码和更少的资源来实现这一点。这就是你可以做到的: 在
viewDidLoad
中,异步调用执行以下操作的块(使用dispatch\u async
):
dispatch\u after
)setNeedsDisplay