バックグラウンド スレッドでテキスト ブロックの高さを測定しています。DynamicColor
なんらかの理由で、アプリケーションの起動直後にこれが発生した場合、アプリがダーク モードかどうかをチェックするため、スレッドはメイン スレッドにある必要がある NSColor サブクラスを呼び出します。
バックグラウンド スレッドが実行されているクラスには、 への参照はありませんがDynamicColor
、NSTextStorage
が割り当てられると、 DynamicColor が呼び出されます。バックグラウンド タスクから UI 呼び出しを行うと、エラーが発生します。
が存在することを知らないクラスを呼び出す方法がNSTextStorage
わかりません。私のNSDocument
サブクラスだけがそれを参照しており、他のクラスはそれを認識していません。
のバックグラウンド スレッドへの呼び出しNSDocument
:
- (void)updatePreviewAndUI:(bool)updateUI {
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
Preview *preview = [[PreviewCreator alloc] initWithScript:script];
});
}
バックグラウンド スレッドは、文字列データを含む多数の要素を調べて、それらの高さを計算します。
+ (NSInteger)heightForString:(NSString *)string font:(NSFont *)font maxWidth:(NSInteger)maxWidth lineHeight:(CGFloat)lineHeight
{
// The error occurs here
NSTextStorage *textStorage = [[NSTextStorage alloc] initWithString:string attributes:@{NSFontAttributeName: font }];
NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
NSTextContainer *textContainer = [[NSTextContainer alloc] initWithContainerSize:NSMakeSize(maxWidth, MAXFLOAT)];
[layoutManager addTextContainer:textContainer];
[textStorage addLayoutManager:layoutManager];
...
}
が割り当てられたDynamicColor
ときに呼び出されます。NSTextStorage
でメインスレッドかどうかを確認することでクラッシュは回避できましたDynamicColor
が、エラーの原因が気になります。
DynamicColor
NSColor
サブクラスです。関連する部分は次のとおりです。
#define FORWARD( PROP, TYPE ) \
- (TYPE)PROP { return [self.effectiveColor PROP]; }
- (NSColor *)effectiveColor
{
if (NSApp) {
// Call to Application delegate causes the thread error
if ([(ApplicationDelegate*)[NSApp delegate] isForcedLightMode]) {
if (self.aquaColor != nil) return self.aquaColor;
}
else if ([(ApplicationDelegate*)[NSApp delegate] isForcedDarkMode]) {
if (self.darkAquaColor != nil) return self.darkAquaColor;
}
}
}
前景色を無地にしてみNSColor
ましたがダメでした。NSTextContainer
アプリの実行時に毎回エラーが発生するわけではなく、テスト環境では問題を再現できませんでした。また、これが発生するのは、テキスト コンテナーが割り当てられるのは初めてです。