如何在prepareForSegue调用前启动等待动画并在其完成后关闭?
兄弟,你猜的完全没错!prepareForSegue是在主线程执行的,如果里面有耗时操作(比如数据处理、网络请求或者复杂的模型初始化),会直接把主线程堵死——你的等待动画刚要开始渲染,就被后面的耗时操作卡住了,等所有准备工作做完,动画刚显示出来就被立刻关闭,所以你根本看不到它。
给你一套可行的解决方案,核心思路是把耗时的准备工作移到后台线程,让主线程专注于显示动画和处理UI跳转:
步骤1:修改按钮的触发逻辑
如果你的DoneButton是直接在Storyboard里绑定了Segue(就是从按钮直接拖到下一个控制器),先取消这个绑定,改成给按钮添加点击事件:
- (IBAction)doneButtonTapped:(UIButton *)sender { // 第一步:立刻启动等待动画(这时候主线程没被阻塞,动画能正常显示) [self startWaitingAnimation]; // 第二步:把耗时的准备工作丢到后台队列执行 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // 这里放你原本在prepareForSegue里的耗时操作: // 比如处理数据、请求接口、初始化复杂模型等等 // 举个例子,模拟2秒的耗时操作 [NSThread sleepForTimeInterval:2]; // 第三步:准备工作完成后切回主线程 dispatch_async(dispatch_get_main_queue(), ^{ // 先关闭等待动画 [self stopWaitingAnimation]; // 手动触发Segue跳转 [self performSegueWithIdentifier:@"YourSegueID" sender:self]; }); }); }
步骤2:简化prepareForSegue的逻辑
现在prepareForSegue里只做轻量的UI数据传递,不要再放任何耗时操作:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { if ([segue.identifier isEqualToString:@"YourSegueID"]) { NextViewController *nextVC = segue.destinationViewController; // 这里只做简单的数据传递,比如把后台处理好的数据传给下一个控制器 nextVC.processedData = self.myProcessedData; } }
额外注意点
- 确保你的
startWaitingAnimation和stopWaitingAnimation方法里的UI操作都是在主线程执行的(一般UI操作默认都是主线程,只要你没手动把它们丢去后台就没问题)。 - 如果你的准备工作涉及到网络请求,建议用NSURLSession或者AFNetworking这类自带后台线程处理的框架,避免自己手动管理线程出问题。
这样调整后,等待动画会在点击按钮后立刻显示,后台默默完成准备工作,等一切就绪后关闭动画再跳转,完美解决你的问题!
内容的提问来源于stack exchange,提问作者Reza.Ab
相关产品推荐
相关产品推荐

