0

最新の MacBook Pro が発売されたときに、アプリに Touch Bar のサポートを追加しました。その後、意味のあるカスタム エスケープ キーなど、さまざまなマイナーな改善を行いました。そのアップデートをリリースした後、アプリがエスケープ キーを更新しようとすると、クラッシュ レポートが表示されるようになりました。

一例を次に示します。

Exception Type:  SIGBUS
Exception Codes: BUS_ADRERR at 0x7fff54a05ff8
Crashed Thread:  0

Application Specific Information:
Selector name found in current argument registers: objectForKey:

Thread 0 Crashed:
0   Foundation                           0x00007fffacbaea98 -[NSConcreteMapTable objectForKey:] + 21
1   Foundation                           0x00007fffacbfc019 -[NSISEngine outgoingRowHeadForRemovingConstraintWithMarker:] + 214
2   Foundation                           0x00007fffacbfbb4c -[NSISEngine removeConstraintWithMarker:] + 479
3   Foundation                           0x00007fffacbf76a6 -[NSISEngine _flushPendingRemovals] + 615
4   Foundation                           0x00007fffacbf4b06 -[NSISEngine withBehaviors:performModifications:] + 197
5   AppKit                               0x00007fffa8c83760 -[NSView(NSConstraintBasedLayout) _withAutomaticEngineOptimizationDisabled:] + 69
6   AppKit                               0x00007fffa8d129dd -[NSView(NSConstraintBasedLayout) removeConstraints:] + 276
7   AppKit                               0x00007fffa8c88f9e -[NSView(NSConstraintBasedLayout) _constraints_snipDangliesWithForce:] + 595
8   AppKit                               0x00007fffa8c82d9e -[NSView _setSuperview:] + 1076
9   AppKit                               0x00007fffa8c88945 -[NSView removeFromSuperview] + 446
10  AppKit                               0x00007fffa9593eef -[NSTouchBarEscapeKeyViewController setTouchBarItem:] + 145
11  AppKit                               0x00007fffa9176bf5 -[NSApplicationFunctionRowController _updateEscapeKeyItem] + 438
12  AppKit                               0x00007fffa9176bf5 -[NSApplicationFunctionRowController _updateEscapeKeyItem] + 438
13  AppKit                               0x00007fffa9176bf5 -[NSApplicationFunctionRowController _updateEscapeKeyItem] + 438
…
509 AppKit                               0x00007fffa9176bf5 -[NSApplicationFunctionRowController _updateEscapeKeyItem] + 438
510 AppKit                               0x00007fffa9176bf5 -[NSApplicationFunctionRowController _updateEscapeKeyItem] + 438
511 AppKit                               0x00007fffa9176bf5 -[NSApplicationFunctionRowController _updateEscapeKeyItem] + 438

簡潔にするために約 500 行を削除しました。[NSApplicationFunctionRowController _updateEscapeKeyItem] + 438

ここで、もう 1 つの短縮レポートを示します。これは私の最も一般的なクラッシュです。実際には自分のコードを呼び出しますが、呼び出しているコードは実際の問題ではないと思われます。

Exception Type:  SIGBUS
Exception Codes: BUS_ADRERR at 0x7fff5b8c2f74
Crashed Thread:  0

Thread 0 Crashed:
0   CoreText                             0x00007fffc87d2e8d _ZNK3OTL7GCommon9NthLookupEj + 41
1   CoreText                             0x00007fffc87d658b _ZNK3OTL4GPOS12ApplyLookupsER8TRunGlueiRNS_12GlyphLookupsE + 155
2   CoreText                             0x00007fffc87d5f53 _ZN26TOpenTypePositioningEngine12PositionRunsER9SyncStateR13KerningStatus + 839
3   CoreText                             0x00007fffc8823920 _ZN14TKerningEngine14PositionGlyphsER8TRunGlue11ShapingTypePK10__CFString + 168
4   CoreText                             0x00007fffc87ddcf7 CTFontTransformGlyphs + 463
5   UIFoundation                         0x00007fffd9d2a795 __NSStringDrawingEngine + 7348
6   UIFoundation                         0x00007fffd9d315ea -[NSAttributedString(NSExtendedStringDrawing) boundingRectWithSize:options:context:] + 605
7   UIFoundation                         0x00007fffd9d31efd -[NSAttributedString(NSExtendedStringDrawing) boundingRectWithSize:options:] + 32
8   AppKit                               0x00007fffc4e711cb -[NSAttributedString(NSStringDrawingExtension) _sizeWithSize:] + 55
9   AppKit                               0x00007fffc4e710ff -[NSButtonCell(NSButtonCellPrivate) _titleSizeWithSize:] + 97
10  AppKit                               0x00007fffc4e70eab -[NSButtonCell(NSButtonCellPrivate) _alignedTitleRectWithRect:] + 235
11  AppKit                               0x00007fffc4e25162 -[NSButtonCell cellSizeForBounds:] + 918
12  AppKit                               0x00007fffc4da2a21 -[NSCell cellSize] + 68
13  AppKit                               0x00007fffc4da295a -[NSControl sizeToFit] + 53
14  AppKit                               0x00007fffc520392c +[NSButton(NSButtonConvenience) _buttonWithTitle:image:target:action:] + 421
15  AppKit                               0x00007fffc5203a05 +[NSButton(NSButtonConvenience) buttonWithTitle:target:action:] + 199
16  Deliveries                           0x0000000103b4c655 +[JUNTouchBar cancelButtonItemWithIdentifier:] (JUNTouchBar.m:75)
17  Deliveries                           0x0000000103b67e9b -[JUNEditWindowController touchBar:makeItemForIdentifier:] (JUNEditWindowController.m:183)
18  AppKit                               0x00007fffc57d7d2a __32-[NSTouchBar itemForIdentifier:]_block_invoke + 34
19  AppKit                               0x00007fffc4e71bd0 +[NSAppearance _performWithCurrentAppearance:usingBlock:] + 79
20  AppKit                               0x00007fffc57d7b9b -[NSTouchBar itemForIdentifier:] + 1158
21  AppKit                               0x00007fffc57d868e -[NSTouchBar(NSEscapeKeyReplacementOld) escapeKeyReplacementItem] + 51
22  AppKit                               0x00007fffc5250e80 -[NSApplicationFunctionRowController _updateEscapeKeyItem] + 238
23  AppKit                               0x00007fffc5250f49 -[NSApplicationFunctionRowController _updateEscapeKeyItem] + 439
24  AppKit                               0x00007fffc5250f49 -[NSApplicationFunctionRowController _updateEscapeKeyItem] + 439
25  AppKit                               0x00007fffc5250f49 -[NSApplicationFunctionRowController _updateEscapeKeyItem] + 439
…
509 AppKit                               0x00007fffc5250f49 -[NSApplicationFunctionRowController _updateEscapeKeyItem] + 439
510 AppKit                               0x00007fffc5250f49 -[NSApplicationFunctionRowController _updateEscapeKeyItem] + 439
511 AppKit                               0x00007fffc5250f49 -[NSApplicationFunctionRowController _updateEscapeKeyItem] + 439

私のtouchBar:makeItemForIdentifier:方法はこれだけです:

- (nullable NSTouchBarItem *)touchBar:(NSTouchBar *)touchBar makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier {

    if ([identifier isEqualToString:JUNTouchBarItemIdentifierCancel]) {
        NSCustomTouchBarItem *item = [JUNTouchBar cancelButtonItemWithIdentifier:identifier];
        return item;
    }
    return nil;

}

そしてcancelButtonItemWithIdentifier:、これも非常に単純です:

+ (NSCustomTouchBarItem *)cancelButtonItemWithIdentifier:(NSString *)identifier {
    NSString *title = NSLocalizedString(@"Cancel", nil);
    NSButton *button = [NSButton buttonWithTitle:title target:nil action:@selector(cancelOperation:)];
    NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:button attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:80.0];
    constraint.priority = 950;
    constraint.active = YES;
    NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
    item.view = button;
    return item;
}

もちろん、このクラッシュを自分で再現することはできません。これは、macOS 10.12.2 から 10.12.5 のベータ版で発生します。レポートの多くは、私が自分でテストしている同じ 13 インチ モデルからのものです。クラッシュ レポートにコメントを含む少数の人々は、ほとんどの場合、新しいウィンドウを開くアクションの直後に発生していると言っています (したがって、エスケープ キーを変更します)。 — 1 人は、ウィンドウを閉じるアクションの後に発生したと言いました. 1 人は、クラッシュする前に 10 秒間ハングアップしたことに言及しました — 同じメソッドへの 500 回の呼び出しを考えると、これは理にかなっています.もちろん、彼らは連絡先情報を残していなかったので、私は彼らにフォローアップする方法がありません.

カスタム エスケープ キーを削除することでクラッシュを回避できることはわかっていますが、削除したくありません。これに対処する方法について他にアイデアはありますか?

更新:最初にこれを投稿して以来、制約を削除するようにアプリを更新したので、ボタンを作成するためのコードは今できる限り単純です。

+ (NSCustomTouchBarItem *)cancelButtonItemWithIdentifier:(NSString *)identifier {
    NSString *title = JUNLocalizedString(@"Cancel", nil);
    NSButton *button = [NSButton buttonWithTitle:title target:nil action:@selector(cancelOperation:)];
    NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
    item.view = button;
    return item;
}

残念ながら、同じスタック トレースを含む、新しいバージョンからのクラッシュ レポートをまだ取得しています。したがって、問題は私が提供しているボタンにあるとは思いません。

4

1 に答える 1

1

申し訳ありませんが、コメントには長すぎます。

スタックの下部が無限再帰によって吹き飛ばされているために表示されていないクラッシュの原因を特定するために、_updateEscapeKeyItem メソッドをスウィズルする、クラッシュを経験したユーザー向けのデバッグ バージョンを作成しました。

私の推測では、彼らは 10.13 の実装を根本的に変更し (彼らは "KVO running amok" について何か言及していました)、確実な手がかりがない限り 10.12 のクラッシュを調査しない可能性があります。

これは、ドロップインできる簡単で汚いコードです (主にHow to swizzle a method of a private classから借用) で、無限再帰を停止します。結果として得られるクラッシュ レポートは、より役立つ可能性があります。

@interface NSObject (swizzle_touchbar_stuff)
@end

static NSInteger updateEscapeKeyItem = 0;

@implementation NSObject (swizzle_touchbar_stuff)
+ (void)load
{
    static dispatch_once_t onceToken = 0;
    dispatch_once(&onceToken, ^{
        Method original, swizzled;

        original = class_getInstanceMethod(objc_getClass("NSApplicationFunctionRowController"), NSSelectorFromString(@"_updateEscapeKeyItem"));
        swizzled = class_getInstanceMethod(self, @selector(sparkle_updateEscapeKeyItem));
        method_exchangeImplementations(original, swizzled);
    });
}

- (void)sparkle_updateEscapeKeyItem
{
    updateEscapeKeyItem++;
    NSLog(@"sparkle_updateEscapeKeyItem %ld", updateEscapeKeyItem);
    assert(updateEscapeKeyItem < 10);
    [(NSObject *)self sparkle_updateEscapeKeyItem];
    updateEscapeKeyItem--;
}

@end
于 2017-09-30T20:16:09.403 に答える