【问题标题】:iOS Objective-C equivalent of Win32 PeekMessage/Translate/DispatchiOS Objective-C 等效于 Win32 PeekMessage/Translate/Dispatch
【发布时间】:2017-02-18 14:17:57
【问题描述】:

在 Windows 中,可以在代码中运行事件..

//PeekMessage loop example
while (WM_QUIT != uMsg.message)
{
     while (PeekMessage (&uMsg, NULL, 0, 0, PM_REMOVE) > 0) //Or use an if statement
     {
          TranslateMessage (&uMsg);
          DispatchMessage (&uMsg);
     }
}

在 iOS 的 Objective-C 中,有没有办法让事件在例如 for 循环中间歇性运行?

我有一些深度嵌套的代码需要一些时间才能运行,我希望它能够间歇性地更新进度。重新设计深度嵌套的代码并不是一个真正的选择,它可以在其他操作系统上运行。

【问题讨论】:

    标签: ios objective-c dispatch


    【解决方案1】:

    因此,您基本上想要运行一个长任务并相应地更新进度。这可以使用Objective-C 中的GCDNSOperationQueue 来完成。下面的代码为您提供了一个示例。

    在这里,我将使用一个将块作为输入的函数。该函数包含异步代码。

    typedef void(^ProgressBlock)(CGFloat progress); // defined block
    
    - (void)executeTaskWithProgress:(ProgressBlock)progress; // defined function
    

    您可以通过以下两种方式异步运行您的任务:

    1. 使用GCD

      - (void)executeTaskWithProgress:(ProgressBlock)progress {
      
              dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
                    // your long running task
      
                    // the below line is for updating progress
                    dispatch_async(dispatch_get_main_queue(), ^{
                        progress(20.0);
                    });
              });
       }
      
    2. 使用NSOperation

      - (void)executeTaskWithProgress:(ProgressBlock)progress {
      
              NSOperationQueue *executionQueue = [[NSOperationQueue alloc] init];
              NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
                 // your long running task
      
                 // the below line is for updating progress
                 [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                     progress(20.0);
                 }];
              }];
      
              [executionQueue addOperation:operation];
       }
      

    您可以通过以下方式调用该函数:

    [self executeTaskWithProgress:^(CGFloat progress) {
        [self.myLabel setText:[NSString stringWithFormat:@"%f completed", progress]];
        // myLabel is an UILabel object
    }];
    

    有关在Objective-C 中使用GCD 进行异步编程的更多详细信息,我建议您查看以下tutorial。有任何疑问欢迎提问

    【讨论】:

    • 这基本上是使用调度启动后台线程的一种方式吗?我可以将选择器或 C 函数传递给它运行吗?
    • 您可以在dispatchQueue 中运行C 函数。如果它是 C++ 函数,则将 .m 文件重命名为 .mm 文件,您也将运行 C++ 函数
    • 另外,dispatchQueue 维护线程。您是否尝试过将此代码 sn-p 用于您的任务?
    • 我还没有,但我相信你提供了足够的信息,我可以让它工作。谢谢!
    【解决方案2】:

    您可以通过在控制器中使用NSTimer 来执行此操作,如下所示:

    - (void)viewDidLoad {
        [NSTimer scheduledTimerWithTimeInterval:10 target:self selector:@selector(timerCalled) userInfo:nil repeats:YES];
    }
    
    -(void)timerCalled
    {
        NSLog(@"timer called");
    }
    

    【讨论】:

      【解决方案3】:

      我不熟悉现代 Windows 异步编程技术或 PeekMessage 函数。你应该用一般的 CS 术语解释它的作用。

      听起来这是在您执行耗时任务时响应系统事件的一种方式。

      iOS 使用稍微不同的方法。它是一个在主线程上运行“事件循环”的多线程操作系统。每次通过事件循环,系统都会检查需要响应的事件(触摸事件、通知、WiFi 或蜂窝网络上的数据、屏幕更新等)并处理它们。

      您需要编写在主线程上运行的代码来执行短任务以响应用户操作或系统事件,然后返回。您不应该在主线程上执行耗时的任务。

      有一个名为 Grand Central Dispatch 的框架,它为在后台线程(或在主线程上,就此而言)运行任务提供高级支持。您还有 NSOperationQueues,它为您提供对管理任务队列的支持在主线程或后台同时或并行运行。

      这两个操作系统使用不同的范例来处理事件和并发,并且可能没有简单的“使用此函数”替代您当前的处理方式。

      您可能应该重构您的长时间运行的任务以在后台线程上运行,然后在您想要更新用户界面时向主线程发送消息。

      【讨论】:

        猜你喜欢
        • 2012-07-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多