将选择器加入到运行循环中 - [NSObject PerformSelector:withObject:afterDelay:] 是正确的方法吗?

发布于 2024-08-11 07:47:51 字数 645 浏览 6 评论 0 原文

我希望在当前方法通过并且 UI 已更新后执行一个方法。为此,我现在正在使用 [object PerformSelector:@selector(someSelector) withObject:someObject afterDelay:0.0] 。根据 Apple 的文档,这会创建NSTimer 将触发选择器并将其附加到当前 NSRunLoop。但我不认为这很优雅。有没有一种简单的方法可以直接将选择器排入当前运行循环,而不需要 Cocoa 创建计时器等?

performSelectorOnMainThread:withObject:waitUntilDone: (如果我在主线程上)或 performSelector:onThread:withObject:waitUntilDone:waitUntilDone:NO > 以更少的开销做我想做的事?

提前欢呼并感谢

MrMage

I'd like to have a method be executed after the current method has passed and the UI has been updated. For that purpose, I'm using [object performSelector:@selector(someSelector) withObject:someObject afterDelay:0.0] right now. According to Apple's documentation, this creates a NSTimer which will then trigger and append the selector to the current NSRunLoop. But I don't consider this very elegant. Is there an easy way to directly enqueue the selector to the current run loop, without having Cocoa create a Timer etc.?

Would performSelectorOnMainThread:withObject:waitUntilDone: (if I'm on the main thread) or performSelector:onThread:withObject:waitUntilDone: with waitUntilDone:NO do what I want with less overhead?

Cheers and thanks in advance

MrMage

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

疏忽 2024-08-18 07:47:51

Cocoa 是事件驱动的。您不会“在当前运行循环中将选择器排入队列”。简而言之:发送到应用程序的事件(用户输入、计时器、网络活动...)会导致运行循环运行,从而导致循环运行中发生一些事情。当然还有“细节”,但这是最基本的行为。

如果您想推迟执行某些选择器到当前运行循环的末尾,请最后调用它,或者要求它在(非常接近)即将到来的循环运行中运行。 -performSelector:... 方法是执行此操作的正确方法。他们创建一个计时器,该计时器会产生一个导致事情发生的事件。

有关详细信息,请参阅 Cocoa 事件处理指南

Cocoa is event-driven. You don't "enqueue a selector within the current run loop". To put it simplistically: An event sent to the application (user input, a timer, network activity ...) causes the run loop to run, which causes things to happen in that run of the loop. There are of course "details", but this is the most basic behavior.

If you want to put off performing some selector to the end of the current run loop, call it last, or ask it to be run on a (very near) upcoming run of the loop. The -performSelector:... methods are the correct way to do this. They create a timer which results in an event which causes things to happen.

For more information, see the Cocoa Event-Handling Guide.

执手闯天涯 2024-08-18 07:47:51

我没有看到您突出显示的 -performSelector:withObject:afterDelay: 方法有任何不优雅的地方。此方法只是将要在运行循环的当前周期完成后执行的任务放入队列。来自您链接到的部分中的文档

执行指定的选择器
下次运行期间的当前线程
循环周期和可选延迟之后
时期。因为它会等到
下一个运行循环周期执行
选择器,这些方法提供了一个
自动最小延迟
当前正在执行的代码。多种的
排队选择器执行一次
一个接一个地按顺序排列
已排队。

不会创建 NSTimer 对象来管理此操作,选择器只是排队等待一定延迟后运行(小延迟意味着在运行循环周期完成后立即运行)。对于您希望在 UI 更新后执行的操作,这是最简单的技术。

对于更明确的线程队列,您可以查看 NSOperations NSOperationQueues 。 maxConcurrentOperationCount 为 1 的 NSOperationQueue 可以按顺序运行操作,一个接一个。

I don't see anything inelegant about the -performSelector:withObject:afterDelay: method that you highlight. This method simply enqueues a task to be performed after the completion of the current cycle of the run loop. From the documentation in the section you linked to:

Performs the specified selector on the
current thread during the next run
loop cycle and after an optional delay
period. Because it waits until the
next run loop cycle to perform the
selector, these methods provide an
automatic mini delay from the
currently executing code. Multiple
queued selectors are performed one
after another in the order they were
queued.

An NSTimer object is not created to manage this, the selector is simply enqueued to be run after a certain delay (a small delay means immediately after the completion of the run loop cycle). For actions that you wish to happen after updates to the UI take place, this is the simplest technique.

For more explicit, threaded queueing, you could look at NSOperations and NSOperationQueues. An NSOperationQueue with a maxConcurrentOperationCount of 1 can run operations in order, one after the other.

末が日狂欢 2024-08-18 07:47:51

我更喜欢 NSRunLoop 方法“performSelector:target:argument:order:modes:”。它保证在运行循环的下一次迭代之前不会执行选择器,并且您不必胡乱指定任意延迟等。

I prefer the NSRunLoop method "performSelector:target:argument:order:modes:". It's guaranteed to not execute the selector until the next iteration of the run loop, and you don't have to mess around with specifying arbitrary delays, etc.

新一帅帅 2024-08-18 07:47:51

我自己多次使用过这种技术,而且我不认为它有那么不雅...但是,您可以尝试的另一种选择是:

performSelectorOnMainThread:withObject:waitUntilDone:NO

仅仅因为您已经在主线程上,并不意味着它不起作用(事实上,文档引用了从主线程调用时会发生的行为)...并且我认为设置 waitUntilDone 时它​​会具有相同的行为为 NO,它将执行选择器的请求排队,并在当前运行循环结束时运行它。

I have used this technique many times myself, and I don't think it's that inelegant... however, an alternative you could try is:

performSelectorOnMainThread:withObject:waitUntilDone:NO.

Just because you are already on the main thread, does not mean it would not work (in fact the documents reference behaviour that will happen when called from the main thread)... and I think it would have the same behavior when waitUntilDone is set to NO, where it queues up the request to execute the selector and have it run when the current run-loop ends.

在巴黎塔顶看东京樱花 2024-08-18 07:47:51

只是为了完整起见,我想添加这个解决方案,如果我们想挑剔的话,这将是合适的解决方案;)

[[NSOperationQueue currentQueue] addOperationWithBlock:^{
    // will be with you in a moment...
}];

Just for completeness sake I'd like to add this solution, which would be the appropriate one if we want to be nitpicking ;)

[[NSOperationQueue currentQueue] addOperationWithBlock:^{
    // will be with you in a moment...
}];
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文