iOS-如何在设定的时间后中断异步后台操作

iOS-如何在设定的时间后中断异步后台操作,ios,objective-c,multithreading,cocoa-touch,grand-central-dispatch,Ios,Objective C,Multithreading,Cocoa Touch,Grand Central Dispatch,注意:请不要评论这是否是个好主意;)我只是在试验,所以想看看结果如何 我有一个UITextView和一些inputText,我将把它们设置为UITextView的文本 我想尝试将inputText直观地输入文本视图,比如说,一次输入一个字母或一个单词 例如(不考虑滴水供给延迟或执行线程): 现在,由于所有的滴水喂食都是在后台异步进行的,一旦我添加了代码来设置视图的动画,您就会错过可视的滴水喂食。主线程一直运行到设置屏幕外视图的动画 我不知道如何实现我想要的 我是否以某种方式中断了上述循环?检查从

注意:请不要评论这是否是个好主意;)我只是在试验,所以想看看结果如何

我有一个
UITextView
和一些
inputText
,我将把它们设置为
UITextView
的文本

我想尝试将
inputText
直观地输入文本视图,比如说,一次输入一个字母或一个单词

例如(不考虑滴水供给延迟或执行线程):

现在,由于所有的滴水喂食都是在后台异步进行的,一旦我添加了代码来设置视图的动画,您就会错过可视的滴水喂食。主线程一直运行到设置屏幕外视图的动画

我不知道如何实现我想要的

我是否以某种方式中断了上述循环?检查从另一个线程更新的标志

我不能将等待放在主线程上,因为它将阻止对
UITextView
的滴灌供给更新


有什么建议吗?

您可以延迟动画以“给”滴水供给时间,如下所示:

dispatch_queue_t backgroundQueue = dispatch_queue_create("background_queue", 0);
for (NSInteger i = 0; i < inputText.length; i++) {
    dispatch_async(backgroundQueue, ^{
        [NSThread sleepForTimeInterval:0.01f];
        NSString* charAtIndex = [inputText substringWithRange:NSMakeRange(i, 1)];
        dispatch_async(dispatch_get_main_queue(), ^{
            _textView.text = [NSString stringWithFormat:@"%@%@", _textView.text, charAtIndex];
        });    
    });
}

// ...
// Animate the view (including the UITextView) off screen
// ...
// User continues with the main workflow
double delayInSeconds = 0.5f;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
    // ...
    // Animate the view (including the UITextView) off screen
    // ...              
});
这样,用户将看到0.5s的滴灌进给动画。这是GCD版本,但您也可以使用该方法:

[UIView animateWithDuration:0.3f // Set your duration here
                      delay:0.5f
                    options:UIViewAnimationOptionCurveEaseOut // Choose the right option here
                 animations:^{
                     // Do your animations here.
                 }
                 completion:^(BOOL finished){
                     if (finished) {
                         // Do your method here after your animation.
                     }
                 }];

您可以延迟动画以“给予”滴水供给时间,如下所示:

dispatch_queue_t backgroundQueue = dispatch_queue_create("background_queue", 0);
for (NSInteger i = 0; i < inputText.length; i++) {
    dispatch_async(backgroundQueue, ^{
        [NSThread sleepForTimeInterval:0.01f];
        NSString* charAtIndex = [inputText substringWithRange:NSMakeRange(i, 1)];
        dispatch_async(dispatch_get_main_queue(), ^{
            _textView.text = [NSString stringWithFormat:@"%@%@", _textView.text, charAtIndex];
        });    
    });
}

// ...
// Animate the view (including the UITextView) off screen
// ...
// User continues with the main workflow
double delayInSeconds = 0.5f;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
    // ...
    // Animate the view (including the UITextView) off screen
    // ...              
});
这样,用户将看到0.5s的滴灌进给动画。这是GCD版本,但您也可以使用该方法:

[UIView animateWithDuration:0.3f // Set your duration here
                      delay:0.5f
                    options:UIViewAnimationOptionCurveEaseOut // Choose the right option here
                 animations:^{
                     // Do your animations here.
                 }
                 completion:^(BOOL finished){
                     if (finished) {
                         // Do your method here after your animation.
                     }
                 }];

最好不要将大量任务排队,然后再设置另一个延迟的动画。是的,它会工作,但它不是那么容易维护,也不能很好地适应未来的其他情况

相反,可以考虑使用一个
NSTimer
和几个实例变量(它们可以封装在另一个类中,以保持一切整洁)。实例变量基本上是当前进度(
i
来自循环)。每次定时器启动时,检查
i
-如果文本动画未完成,请使用
i
对UI进行子串和更新。如果文字动画已完成,请使计时器无效并启动最终视图动画


通过这种方式,逻辑是有组织的、易于理解的、可重用的和可取消的。

您最好不要将大量任务排队,然后再设置另一个延迟的动画。是的,它会工作,但它不是那么容易维护,也不能很好地适应未来的其他情况

相反,可以考虑使用一个
NSTimer
和几个实例变量(它们可以封装在另一个类中,以保持一切整洁)。实例变量基本上是当前进度(
i
来自循环)。每次定时器启动时,检查
i
-如果文本动画未完成,请使用
i
对UI进行子串和更新。如果文字动画已完成,请使计时器无效并启动最终视图动画


通过这种方式,逻辑是有组织的、易于理解的、可重用的和可取消的。

根据J.Costa的建议,我一直坚持大中央调度方法。我缺少的部分(我不确定我是否很好地解释了这个需求)是对共享资源的访问

在以下代码中,我将其结构化为:

  • BOOL
    共享资源,用于指示滴灌进料是否应继续
  • 创建一个串行队列,用于读取/写入该共享资源
  • 滴灌供给发生在后台队列上,另外还使用串行队列检查是否应该继续
  • 延迟视图动画是使用
    dispatch\u after
    设置的,当它发生时,它使用串行队列发出滴水供给应停止的信号
代码:

NSString*inputText=@“一些有意义的文本…”;
调度队列\u t serialQueue=调度队列\u创建(“serialQueue”,调度队列\u SERIAL);
//共享资源
_ContinuedLipfeed=是;
调度异步(调度获取全局队列(调度队列优先级默认为0)^{
对于(NSInteger i=0;i
根据J.科斯塔的建议,我一直坚持大中央调度方法。我缺少的部分(我不确定我是否很好地解释了这个需求)是对共享资源的访问

在以下代码中,我将其结构化为:

  • BOOL
    共享资源,用于指示滴灌进料是否应继续
  • 创建一个串行队列,用于读取/写入该共享资源
  • 滴灌供给发生在后台队列上,另外还使用串行队列检查是否应该继续
  • 延迟视图动画是使用
    dispatch\u after