iOS如何确定阻止UI的内容

use*_*468 26 user-interface multithreading blocking ios

我是iOS开发的新手,但我开始掌握一些更复杂的概念.我目前有一个实现AVCam捕获视频的应用程序.AVCam是在单独的线程上创建的,但使用的是我的主xib文件中的视图.当摄像头完成捕获时,它会在我的ViewController类中调用一个完整的函数.在完整的函数中,我调用了许多其他函数来更新UI以及一些NSLog.一切似乎工作正常,我立即在控制台中看到日志,但UI需要另外3秒钟来更新.我已经尝试使用工具来查找有问题的代码,但我似乎无法找到它.还有另一种方法可以确定UI阻塞的内容吗?

这是录制完成时调用的代码;

-(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);
}
Run Code Online (Sandbox Code Playgroud)

一切都被立即记录,但进度HUD和模态视图控制器不会触发大约2-5秒,这很奇怪.

这是线程的前后状态(当它被冻结时与它解冻时). 在此输入图像描述 在此输入图像描述

Oss*_*sir 47

尝试暂停程序执行(底部面板中有一个按钮Xcode,第三个)

暂停

  • 然后看左面板(Navigator panel),
  • Debug Navigator

Debug Navigator

  • 使用main函数查找线程,并且您可以通过此线程中的方法找出mb,更新UI需要花费很长时间.现在正在使用的方法通常是顶部黑色(灰色列出obj-c内部方法).

主要

  • 这种方法可能需要几次尝试才能产生有用的结果,因此请确保您有耐心. (2认同)

Mic*_*eno 13

您可以通过在配置文件模式下运行应用程序来使用Instruments中的系统跟踪工具.然后,您将获得系统中所有线程的详细运行以及线程经历的每个调度事件中的堆栈跟踪.

2016 WWDC System Trace in Depth中有一个很棒的视频,它将指导您调试阻塞的线程问题.

这比Time Profiler仪器要好得多,因为该工具的工作原理是每隔一段时间对CPU上运行的内容进行采样.但是,如果您的线程被阻止,它不会在CPU上运行,因此 - 它将不会被采样.您的主线程可能会被阻止一整秒,但它不会显示在Time Profiler中.

  • 为此+1 - 不要以为我以前一直看过WWDC视频,但这真是令人大开眼界 (3认同)

Cag*_*aya 7

您可以使用Time Profiler找出阻止您的应用的内容.


Olh*_*iuk 5

Michael Cueno 的建议很棒 - 描述了系统跟踪分析和“兴趣点”。

然而,在 iOS 12+ 中还有另一个工具可以使用路标来做到这一点:https : //pspdfkit.com/blog/2018/using-signposts-for-performance-tuning-on-ios/

我们的想法是使用功能os_signpost,从os框架,并在所有怀疑阻止主线程的地方插入它。

比如说,你按下 UIButton,有时它会滞后。您应该os_signpostbuttonPressed处理程序和您怀疑的所有函数中插入。

然后,您应该在 Instruments 中进行分析,使用Blank模板并添加os_signpost子模板。一个例子在这里:https : //github.com/gatamar/UnsplashSearch

在此处输入图片说明

请注意 Swift / Objc 中的 API 差异:

迅速:

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")
}
Run Code Online (Sandbox Code Playgroud)

对象:

#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);
Run Code Online (Sandbox Code Playgroud)