私は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秒間トリガーしないため、非常に奇妙です。
スレッドの前と後の状態を示します(フリーズしたときとフリーズ解除したとき)。
プログラムの実行を一時停止してみてください(Xcode
の下部パネルに3つ目のボタンがあります)。
Navigator panel
)、Debug Navigator
main
関数を使用してスレッドを検索します。このスレッドのメソッドによって、UIの更新に非常に長い時間がかかることを理解できます。現在機能しているメソッドは、通常、一番上の黒のメソッドです(灰色がリストされていますobj-c
内部メソッド)。アプリをプロファイルモードで実行すると、Instrumentsのシステムトレースツールを使用できます。次に、システム内のすべてのスレッドの詳細な概要と、スレッドが通過する各スケジューリングイベントでのスタックトレースを取得します。
2016 WWDCのすばらしいビデオ システムトレースの詳細 がブロックされたスレッドの問題のデバッグについて説明します。
これはTime Profiler計測器よりもはるかに優れています。なぜなら、そのツールは、CPUで実行されているもののサンプルを一定間隔で取得することに基づいて機能するためです。ただし、スレッドがブロックされている場合は、CPUで実行されていないため、サンプリングされません。メインスレッドが1秒間ブロックされている可能性がありますが、Time Profilerには表示されません。
Time Profiler を使用して、アプリをブロックしているものを見つけることができます。
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 。
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);
シミュレータでUIブロッキングの問題がある場合:
他のアプローチのいずれかに飛び込む前に、シミュレータを終了して、アプリを削除して、アプリを再ビルド/実行してみてください。 tスレッドの問題やクラッシュを見つけます。Instrumentsで1時間ほど掘り下げた後、シミュレータの問題である可能性があると思いましたが、それだけでした:)