iOS 如何确定是什么阻止了 UI
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15928035/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
iOS How to determine what is blocking the UI
提问by user379468
I'm fairly new to iOS development but I'm starting to grasp some of the more complicated concepts. I currently have an application that implements an AVCam to capture video. The AVCam is created on a separate thread, but uses a view that is in my main xib file. When the camera is done capturing, it calls a complete function in my ViewController class. Within the complete function I call a number of other functions that update the UI as well as a few NSLogs. Everything seems to work fine, I see the logs in the console immediately, but the UI takes another 3 seconds to update. I've tried using instruments to find the offending code, but I can't seem to find it. Is there another way to determine what is blocking by UI?
我对 iOS 开发还很陌生,但我开始掌握一些更复杂的概念。我目前有一个实现 AVCam 来捕获视频的应用程序。AVCam 是在单独的线程上创建的,但使用的是我的主 xib 文件中的视图。当相机完成捕获时,它会在我的 ViewController 类中调用一个完整的函数。在完整的函数中,我调用了许多其他更新 UI 的函数以及一些 NSLog。一切似乎都很好,我立即在控制台中看到了日志,但 UI 又需要 3 秒钟才能更新。我试过使用仪器来查找有问题的代码,但我似乎找不到它。有没有另一种方法来确定 UI 阻止了什么?
Here is the code called when the recording is complete;
下面是录制完成时调用的代码;
-(void)movieRecordingCompleted{
[HUD hide:YES];
NSLog(@"movieRecordingCompleted");
[self showModalViewController];
NSString *pathToMovie = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/Movie.mov"];
NSLog(@"pathToMovie: %@", pathToMovie);
pathToTreatedVid = pathToMovie;
NSLog(@"File Save Called");
UISaveVideoAtPathToSavedPhotosAlbum(pathToMovie, nil, NULL, NULL);
}
Everything is logged immediately, but the progress HUD and the modal view controller don't trigger for about 2 - 5 seconds, it's very strange.
一切都会立即记录下来,但是进度 HUD 和模态视图控制器在大约 2 - 5 秒内没有触发,这很奇怪。
Here is the before and after state of the threads (when it is frozen vs when it becomes unfrozen).
这是线程的前后状态(冻结时与解冻时)。
回答by Ossir
Try to Pause program execution (there is a button for that in bottom panel of Xcode
, the third one)
尝试暂停程序执行(Xcode
在第三个的底部面板中有一个按钮)
- Then look at left panel (
Navigator panel
), - Find
Debug Navigator
- 然后看左侧面板 (
Navigator panel
), - 找
Debug Navigator
- Find thread with
main
function, and mb you can figure out by methods in this thread, what takes so long to update your UI. The method that are working right now is the top black one usually(with grey colour listedobj-c
internal methods).
- 找到有
main
函数的线程,然后你可以通过这个线程中的方法找出什么需要这么长时间来更新你的用户界面。现在正在使用的方法通常是顶部黑色的obj-c
方法(灰色列出内部方法)。
回答by Michael Cueno
You can use the System Trace tool in Instruments by running your App in profile mode. Then you will get a detailed run down of all the threads in the system along with stack traces at each scheduling event the thread goes through.
您可以通过在配置文件模式下运行您的应用程序来使用 Instruments 中的系统跟踪工具。然后,您将获得系统中所有线程的详细运行情况以及线程经过的每个调度事件的堆栈跟踪。
There is a great video from the 2016 WWDC System Trace in Depthwhich will walk you through debugging a blocked thread issue.
2016 WWDC System Trace in Depth 中有一个很棒的视频,它将引导您调试阻塞的线程问题。
This is much better than the Time Profilerinstrument since, that tool works based off of taking samples of what is running on the CPU at intervals. However, if your thread is blocked, it isn't running on the CPU, so - it will not be sampled. You might have your main thread blocked for a whole second but it won't show up in Time Profiler.
这比Time Profiler工具要好得多,因为该工具基于每隔一段时间对 CPU 上运行的内容进行采样而工作。但是,如果您的线程被阻塞,则它不会在 CPU 上运行,因此 - 它不会被采样。您的主线程可能被阻塞了一整秒,但它不会显示在 Time Profiler 中。
回答by Cagdas Altinkaya
You can use Time Profilerto find out what's blocking your app.
您可以使用Time Profiler找出阻止您的应用程序的原因。
回答by Olha Pavliuk
Michael Cueno's advice is wonderful - System Trace profiling and "points of interest" are described.
Michael Cueno 的建议很棒 - 描述了系统跟踪分析和“兴趣点”。
Yet there's another Instrument to do this in iOS 12+, using signposts: https://pspdfkit.com/blog/2018/using-signposts-for-performance-tuning-on-ios/
然而,在 iOS 12+ 中还有另一个工具可以使用路标来做到这一点:https: //pspdfkit.com/blog/2018/using-signposts-for-performance-tuning-on-ios/
The idea is you use the function os_signpost
from os
framework, and insert it in all the places which you suspect for blocking Main thread.
我们的想法是使用功能os_signpost
,从os
框架,并在所有怀疑阻止主线程的地方插入它。
Say, you press UIButton and sometimes it lags.
You should insert os_signpost
in buttonPressed
handler and in all functions you suspect.
比如说,你按下 UIButton,有时它会滞后。您应该os_signpost
在buttonPressed
处理程序和您怀疑的所有函数中插入。
Then, you should profile in Instruments, using Blank
template and adding os_signpost
sub-template. An example is here: https://github.com/gatamar/UnsplashSearch.
然后,您应该在 Instruments 中进行分析,使用Blank
模板并添加os_signpost
子模板。一个例子在这里:https: //github.com/gatamar/UnsplashSearch。
Note the API differences in Swift / Objc:
请注意 Swift / Objc 中的 API 差异:
Swift:
迅速:
import os
...
static let pointsOfInterest = OSLog(subsystem: "com.apple.SolarSystem", category: .pointsOfInterest)
os_signpost(.begin, log: ViewController.pointsOfInterest, name: "createSubviews")
defer {
os_signpost(.end, log: ViewController.pointsOfInterest, name: "createSubviews")
}
Objc:
对象:
#include <os/log.h>
#include <os/signpost.h>
os_log_t log = os_log_create("com.apple.SolarSystem", "YourCategory");
os_signpost_id_t spid = os_signpost_id_generate(log);
...
os_signpost_interval_begin(log, spid, "func1");
...
os_signpost_interval_end(log, spid, "func1);
回答by Shahriar
If you have UI Blocking issue on the Simulator:
如果您在模拟器上遇到UI 阻塞问题:
Before diving into any of the other approaches, try to quite the simulatorand delete the app and rebuild/run the app again, in my case I couldn't find any thread issue or crash, after almost an hour digging in Instruments I just thought it might be the Simulator issue and that was it :)
在深入研究任何其他方法之前,尝试关闭模拟器并删除应用程序并再次重新构建/运行应用程序,在我的情况下,我找不到任何线程问题或崩溃,在我刚刚想到的仪器中挖掘了将近一个小时这可能是模拟器的问题,就是这样:)
回答by Reid
I like using this function:
我喜欢使用这个功能:
sleep(x);
where "x" is the number of seconds...it will simply block whatever thread it's run on for that number of seconds. If your UI freezes, you know you blocked the main thread and thus that code is being run on the main thread (whether you intended that or not). Try placing this call in different places in your code and it should help you diagnose what's going on. Hope that helps.
其中“x”是秒数......它会简单地阻止它在该秒数内运行的任何线程。如果您的 UI 冻结,您就知道您阻塞了主线程,因此该代码正在主线程上运行(无论您是否有意)。尝试将此调用放置在代码中的不同位置,它应该可以帮助您诊断发生了什么。希望有帮助。