web-dev-qa-db-ja.com

iOS UIをブロックしているものを特定する方法

私は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);
}

すべてがすぐにログに記録されますが、進行状況HUDとモーダルビューコントローラーが約2〜5秒間トリガーしないため、非常に奇妙です。

スレッドの前と後の状態を示します(フリーズしたときとフリーズ解除したとき)。 enter image description hereenter image description here

26
user379468

プログラムの実行を一時停止してみてください(Xcodeの下部パネルに3つ目のボタンがあります)。

Pause

  • 次に左パネル(Navigator panel)、
  • 検索Debug Navigator

Debug Navigator

  • main関数を使用してスレッドを検索します。このスレッドのメソッドによって、UIの更新に非常に長い時間がかかることを理解できます。現在機能しているメソッドは、通常、一番上の黒のメソッドです(灰色がリストされていますobj-c内部メソッド)。

main

47
Ossir

アプリをプロファイルモードで実行すると、Instrumentsのシステムトレースツールを使用できます。次に、システム内のすべてのスレッドの詳細な概要と、スレッドが通過する各スケジューリングイベントでのスタックトレースを取得します。

2016 WWDCのすばらしいビデオ システムトレースの詳細 がブロックされたスレッドの問題のデバッグについて説明します。

これはTime Profiler計測器よりもはるかに優れています。なぜなら、そのツールは、CPUで実行されているもののサンプルを一定間隔で取得することに基づいて機能するためです。ただし、スレッドがブロックされている場合は、CPUで実行されていないため、サンプリングされません。メインスレッドが1秒間ブロックされている可能性がありますが、Time Profilerには表示されません。

13
Michael Cueno

Time Profiler を使用して、アプリをブロックしているものを見つけることができます。

7

Michael Cuenoのアドバイスは素晴らしい-システムトレースプロファイリングと「関心のあるポイント」が説明されています。

しかし、標識を使用してiOS 12以降でこれを行う別のインストゥルメントがあります: https://pspdfkit.com/blog/2018/using-signposts-for-performance-tuning-on-ios/

アイデアは、osフレームワークの関数os_signpostを使用し、メインスレッドをブロックしていると思われるすべての場所に挿入することです。

たとえば、UIButtonを押すと、遅れることがあります。 buttonPressedハンドラーと疑わしいすべての関数にos_signpostを挿入する必要があります。

次に、Blankテンプレートを使用し、os_signpostサブテンプレートを追加して、Instrumentsでプロファイリングする必要があります。例は次のとおりです: https://github.com/gatamar/UnsplashSearch

enter image description here

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")
}

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);
1
Olha Pavliuk

シミュレータでUIブロッキングの問題がある場合

他のアプローチのいずれかに飛び込む前に、シミュレータを終了して、アプリを削除して、アプリを再ビルド/実行してみてください。 tスレッドの問題やクラッシュを見つけます。Instrumentsで1時間ほど掘り下げた後、シミュレータの問題である可能性があると思いましたが、それだけでした:)

0
Shahriar