【问题标题】:UIActionSheet taking long time to respondUIActionSheet 需要很长时间才能响应
【发布时间】:2012-06-14 09:19:13
【问题描述】:

我正在 actionSheet:clickedButtonAtIndex 委托方法上创建 UIActionSheet

- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex     
 if(buttonIndex == 1){

        [self.myFirstView removeFromSuperview]; 

        if (!self.mySecondView) {
            [[NSBundle mainBundle] loadNibNamed:@"MySecondView" owner:self options:nil];
        }
        [self.mySecondView setFrame:CGRectMake(0, 0, 320, 480)];

        [[UIApplication sharedApplication].keyWindow addSubview: self.mySecondView];

        UIActionSheet * action = [[UIActionSheet alloc]initWithTitle:@""
                                                            delegate:self
                                                   cancelButtonTitle: nil
                                              destructiveButtonTitle: deleteContacts
                                                   otherButtonTitles: cancel, nil];
        action.tag = 102;
        [action showInView:self.view];
        [action release];

    }

我用与上面完全相同的方法处理这个UIActionSheet的点击事件。

if(actionSheet.tag == 102){

    if(buttonIndex == 0){
        if([[NSBundle mainBundle] loadNibNamed:@"MyThirdView" owner:self options:nil]) { 
            [self.myThirdView setFrame:CGRectMake(0, 0, 320, 480)];
            [[UIApplication sharedApplication].keyWindow addSubview:self.myThirdView];
        }
        [self.mySecondView removeFromSuperview]; 

        [self.doneButton.target performSelector:self.doneButton.action withObject:self.doneButton.target];

        [self performSelector:@selector(RemoveView) withObject:self afterDelay:3.0];

    }
}

我面临的问题是,UIActionSheet 需要太多时间来响应。当我单击UIActionSheet 按钮时,它会在myThirdView 加载之前处于冻结状态2 或3 秒。我无法理解,这种情况下的响应延迟是什么,因为我在UIActionSheet 按钮单击事件方法中做的第一件事是加载myThirdView。其余代码仅在加载 myThirdView 的代码之后执行。但即使是第一行代码似乎也会在延迟后执行。 有什么建议吗?

【问题讨论】:

  • [action showInView:self.view]; 改为[action showInView:self.mySecondView]; 是否有效?
  • 它有效。但action sheet的响应速度没有明显变化。
  • 我认为正确的答案应该是结合 The Saad 和 Andrew Zimmer 的答案。应该在后台线程上运行的代码是这行代码[self.doneButton.target performSelector:self.doneButton.action withObject:self.doneButton];。包括RemoveView 方法在内的其余代码应该在主线程上运行。特别提到 Gabriel 模拟按钮触摸动作。
  • 首先,我自己是一名反ARC编码员,所以我有一些提示。其次,我对你写导航的方式有点前卫,它看起来很乱,但我不能用这个最小的观点给出任何建议。 Tiptime:第一,断点,看看发生了什么线程。 2:performSelectorOnMainThread而不是performSelector。 3:在执行回调之前不要释放 UIActionSheet。 4:确保“自我”仍然存在。 5:使用断点和step-thru来衡量处理函数的速度

标签: iphone objective-c ios uiview uiactionsheet


【解决方案1】:

这可能是由于这个

[self performSelector:@selector(RemoveView) withObject:self afterDelay:3.0];

创建其他方法并在该方法中执行此操作。像这样

[self viewRemover];

在 viewRemover 中

-(void) viewRemover
{
    [self performSelector:@selector(RemoveView) withObject:self afterDelay:3.0];

}

所以你的代码现在会是这样的

if(actionSheet.tag == 102){

    if(buttonIndex == 0){
        if([[NSBundle mainBundle] loadNibNamed:@"MyThirdView" owner:self options:nil]) { 
            [self.myThirdView setFrame:CGRectMake(0, 0, 320, 480)];
            [[UIApplication sharedApplication].keyWindow addSubview:self.myThirdView];
        }
        [self.mySecondView removeFromSuperview]; 

        [self.doneButton.target performSelector:self.doneButton.action withObject:self.doneButton.target];

    [self performSelectorInBackground:@selector(viewRemover) withObject:nil];

    }
}

【讨论】:

  • 在调试时,控件没有进入RemoveView方法。也许它与self performSelectorInBackground 中的withObject:nil 有关。反正延迟问题还没解决。
  • 哦,顺便说一句,如果 viewRemover 正在编辑屏幕上的可见对象,请不要在后台线程中执行此操作。这会导致间歇性问题,调试起来并不有趣。
【解决方案2】:

用户界面操作在主线程中运行,并且仅在您的方法结束时发生。因此,MyThirdView 在其他指令完成之前不会出现。我唯一能想到的就是延迟:

[self.doneButton.target performSelector:self.doneButton.action withObject:self.doneButton.target];

如果您正在执行任何繁重的计算或网络连接,那肯定是原因。

OTOH,我认为您最好修改该行:

[self.doneButton.target performSelector:self.doneButton.action withObject:self.doneButton];

如果你想模拟按钮触摸动作。

【讨论】:

  • 没有显着差异。
【解决方案3】:

问题。 UIActionSheet 是否冻结,或者它是否消失并且第三个视图在 2-3 秒内不可见?

这可能是由于 2 个问题之一。

  1. 如果整个操作表冻结,那么当您启动第三个视图时,您正在做一些繁重的工作,您正在加载一些核心数据,或者大量资产,或者需要很长时间的东西。如果是这种情况,您需要重新格式化加载第三个视图的方式。我建议将任何繁重的负载推到后台(这意味着如果您的 xib 中有很多图像,您可能需要在代码中加载它们)。

  2. 另一种可能性是,您将第三个视图添加到第二个视图下方,然后在 3 秒内不隐藏第二个视图(通过延迟执行选择器来完成)。如果是这种情况,只需消除延迟即可。

我做了几个类来帮助我计时执行并找到我的代码中的瓶颈,现在它们似乎可以帮助你。 http://forrst.com/posts/Code_Execution_Timer_for_iOS_Development-dSJ

【讨论】:

    【解决方案4】:

    您的第三个视图有多大。如果 nib 文件需要加载太多,您可能会等待很多事情发生,此外,如果您必须更改一些 UI 元素并阻塞 UI 线程,您将拖拉您的应用程序,直到发生超时并且应用程序将转移有些东西可以补偿..

    我采取的路线是 dispatch_async 和 dispatch_sync

    // This will release the UI thread which may be blocking your calls.
    // You can use any of the DISPATCH_QUEUE_PRIORITY_.... values to set how important this block is.
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
        // this command will get added to the stack and return without a hitch.
        // the block will be run the next time the main runloop ends.
        dispatch_async(dispatch_get_main_queue(), ^{
            // do some UI work that can happen without a hitch, and does not impact the calling block
        });
    
        // this command will act much the same. but will pause the background execution 
        // of this block until the runloop has executed this and returned.
        dispatch_sync(dispatch_get_main_queue(), ^{
            // do some UI work that must be completed to continue.
        });
    
    });
    

    在 UI 线程中执行过多操作会暂停执行堆积在队列中的内容。将所有代码发送到后台线程,并且仅在您需要更改 UI 时才跳到 UI 线程,这是编写 iPhone 应用程序代码的更好且响应速度更快的方式。

    我希望这会有所帮助:)

    【讨论】:

    • 这段代码是我的救命稻草。确保不要将自动释放对象传递给它。因为它是一个障碍,有时你觉得你可以。
    • 我目前正在使用 arc。但我相信该块保留并释放它自己持有的所有对象。不是吗??
    • 我不确定当你使用 ARC 时是否会这样,所以你可能会没事。如果您不在 ARC 上,那么在线程之间传递自动释放的对象是相当灾难性的。过去我被这件事烧死了。
    • 但是一个块并不完全是一个线程。该块冻结在它们之间使用的当前对象。处理保留和释放本身。使用调度你应该没问题。只要在对象还活着的时候创建块。
    • 嗯,在别处看来你是对的。我想知道是什么原因导致所有这些对象释放崩溃。也许是因为对象超出了方法的范围?相关:stackoverflow.com/questions/4983729/…
    【解决方案5】:

    在 Swift 4 中: 我用这个块包装了代码

    DispatchQueue.main.async {
    
    // your code to show action sheet.
    
    }
    

    例如

    DispatchQueue.main.async {
    
                let alert = UIAlertController(title: "Options", message: String("What do want to do?"), preferredStyle: UIAlertController.Style.actionSheet)
    
                alert.addAction(UIAlertAction(title: "Open", style: UIAlertAction.Style.default, handler: {(action:UIAlertAction!) in
                    self.myOpen(code: self.codes[indexPath.row])
                }))
                alert.addAction(UIAlertAction(title: "Delete", style: UIAlertAction.Style.default, handler: {(action:UIAlertAction!) in
                    self.myDelete(indexPath: indexPath)
                }))
                alert.addAction(UIAlertAction(title: "Cancel", style: UIAlertAction.Style.default, handler: {(action:UIAlertAction!) in
                    print("Cancel")
                }))
    
                self.present(alert, animated: true, completion: nil)
    
            }
    

    【讨论】:

      猜你喜欢
      • 2017-03-16
      • 1970-01-01
      • 1970-01-01
      • 2020-09-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-25
      • 1970-01-01
      相关资源
      最近更新 更多