NSTabView 内嵌的 NSCollectionView 崩溃时的神秘观察者
Mystery observer in crash of NSCollectionView embedded in NSTabView
我在 NSTabView 的选项卡之一中嵌入了 NSCollectionView。 collection 已加载并正确显示,但在切换到任何其他选项卡后,应用程序崩溃并显示以下崩溃日志。崩溃指出无法为关键路径“firstResponder”删除观察者(ProjectTabLeadersCollection,它是我的 NSCollectionView 的 class)。我不确定到底发生了什么,因为我没有明确地为这个选项卡注册任何观察者,所以我假设 AppKit 在幕后做一些事情,以及我在 Interface Builder 或我的初始化代码中的设置不太正确。希望有人能在这里提供一些指导。
有什么想法吗?
2022-04-12 07:21:53.861124-0700 APBA Baseball[78639:4002869] [General] Cannot remove an observer <ProjectTabLeadersCollection 0x7f9e6b8df1e0> for the key path "firstResponder" from <NSWindow 0x7f9e7c044500> because it is not registered as an observer.
2022-04-12 07:21:53.864095-0700 APBA Baseball[78639:4002869] [General] (
0 CoreFoundation 0x00007ff809bf41e3 __exceptionPreprocess + 242
1 libobjc.A.dylib 0x00007ff809954c13 objc_exception_throw + 48
2 Foundation 0x00007ff80a9bf1ff -[NSObject(NSKeyValueObserverRegistration) _removeObserver:forProperty:] + 700
3 Foundation 0x00007ff80a9beeff -[NSObject(NSKeyValueObserverRegistration) removeObserver:forKeyPath:] + 129
4 AppKit 0x00007ff80c77f736 -[NSCollectionView viewWillMoveToWindow:] + 274
5 AppKit 0x00007ff80c5b449a -[NSView _setWindow:] + 277
6 AppKit 0x00007ff80ce04884 __21-[NSView _setWindow:]_block_invoke.425 + 299
7 CoreAutoLayout 0x00007ff811211cf3 -[NSISEngine withBehaviors:performModifications:] + 84
8 AppKit 0x00007ff80c5b4b04 -[NSView _setWindow:] + 1919
9 AppKit 0x00007ff80ce04884 __21-[NSView _setWindow:]_block_invoke.425 + 299
10 CoreAutoLayout 0x00007ff811211cf3 -[NSISEngine withBehaviors:performModifications:] + 84
11 AppKit 0x00007ff80c5b4b04 -[NSView _setWindow:] + 1919
12 AppKit 0x00007ff80c62f07e -[NSScrollView _setWindow:] + 93
13 AppKit 0x00007ff80ce04884 __21-[NSView _setWindow:]_block_invoke.425 + 299
14 CoreAutoLayout 0x00007ff811211cf3 -[NSISEngine withBehaviors:performModifications:] + 84
15 AppKit 0x00007ff80c5b4b04 -[NSView _setWindow:] + 1919
16 AppKit 0x00007ff80c5e3d8f -[NSView removeFromSuperview] + 158
17 AppKit 0x00007ff80c7a230f __56-[NSView replaceSubview:with:options:completionHandler:]_block_invoke + 40
18 AppKit 0x00007ff80c7a2106 -[NSView replaceSubview:with:options:completionHandler:] + 735
19 AppKit 0x00007ff80c77996b -[NSTabView _switchTabViewItem:oldView:withTabViewItem:newView:initialFirstResponder:lastKeyView:] + 859
20 AppKit 0x00007ff80c772e21 -[NSTabView selectTabViewItem:] + 512
21 AppKit 0x00007ff80c7791b3 -[NSTabViewController setSelectedTabViewItemIndex:] + 637
22 AppKit 0x00007ff80c7a16fe -[NSApplication(NSResponder) sendAction:to:from:] + 288
23 AppKit 0x00007ff80c7a15a4 -[NSControl sendAction:to:] + 86
24 AppKit 0x00007ff80c7a14d6 __26-[NSCell _sendActionFrom:]_block_invoke + 131
25 AppKit 0x00007ff80c7a13df -[NSCell _sendActionFrom:] + 171
26 AppKit 0x00007ff80c89c311 -[NSSegmentedCell _sendActionFrom:] + 161
27 AppKit 0x00007ff80c79e19f NSControlTrackMouse + 1813
28 AppKit 0x00007ff80c79da66 -[NSCell trackMouse:inRect:ofView:untilMouseUp:] + 121
29 AppKit 0x00007ff80c89ba45 -[NSSegmentedCell trackMouse:inRect:ofView:untilMouseUp:] + 712
30 AppKit 0x00007ff80c79cd06 -[NSControl mouseDown:] + 678
31 AppKit 0x00007ff80c79b1f1 -[NSWindow(NSEventRouting) _handleMouseDownEvent:isDelayedEvent:] + 4859
32 AppKit 0x00007ff80c70f39e -[NSWindow(NSEventRouting) _reallySendEvent:isDelayedEvent:] + 2582
33 AppKit 0x00007ff80c70e76e -[NSWindow(NSEventRouting) sendEvent:] + 352
34 AppKit 0x00007ff80c70cb44 -[NSApplication(NSEvent) sendEvent:] + 352
35 AppKit 0x00007ff80c9c596b -[NSApplication _handleEvent:] + 65
36 AppKit 0x00007ff80c58e35e -[NSApplication run] + 623
37 AppKit 0x00007ff80c5622b7 NSApplicationMain + 817
38 APBA Baseball 0x00000001058f8e22 main + 34
39 dyld 0x0000000109b1951e start + 462
我的选项卡视图设置如下:
NSCollection 位于名为 Leaders 的选项卡中,连接如下所示:
这是 collection 的 header:
@interface ProjectTabLeadersCollection : NSCollectionView <NSCollectionViewDataSource, NSCollectionViewDelegate> {
NSMutableArray *ar;
}
@end
接下来,.m 文件:
#import "ProjectTabLeadersCollection.h"
#import "ProjectTabLeadersCollectionItem.h"
@implementation ProjectTabLeadersCollection
-(void) viewDidMoveToWindow {
self.delegate = self;
self.dataSource = self;
ar = [[NSMutableArray alloc] init];
for (int i = 0; i < 100; ++i)
[ar addObject:@"Hello"];
}
- (void)collectionView:(NSCollectionView *)collectionView willDisplayItem:(nonnull NSCollectionViewItem *)item forRepresentedObjectAtIndexPath:(nonnull NSIndexPath *)indexPath {
}
- (void)collectionView:(NSCollectionView *)collectionView didEndDisplayingItem:(nonnull NSCollectionViewItem *)item forRepresentedObjectAtIndexPath:(nonnull NSIndexPath *)indexPath {
}
- (NSInteger) numberOfSectionsInCollectionView:(NSCollectionView *)collectionView {
return (1);
}
- (NSInteger) collectionView:(NSCollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return (ar.count);
}
- (NSCollectionViewItem *) collectionView:(NSCollectionView *)collectionView itemForRepresentedObjectAtIndexPath:(NSIndexPath *)indexPath
{
ProjectTabLeadersCollectionItem *item = [collectionView makeItemWithIdentifier:@"ProjectTabLeadersCollectionItem" forIndexPath:indexPath];
item->StatNameLabel.stringValue = [ar objectAtIndex:[indexPath item]];
return (item);
// ProjectTabStandingsCollectionItem *item = [collectionView makeItemWithIdentifier:@"ProjectTabStandingsCollectionItem" forIndexPath:indexPath];
// ProjectTeamObject *pto = [standings objectAtIndex:[indexPath item]];
//
// item->StandingsLabel.stringValue = pto.profile.city;
// return (item);
}
- (void)drawRect:(NSRect)dirtyRect {
[super drawRect:dirtyRect];
// Drawing code here.
}
@end
viewDidMoveToWindow
的文档指出
The default implementation does nothing
但 [NSCollectionView viewDidMoveToWindow]
已实施并开始观察 window 的 firstResponder
。 -[ProjectTabLeadersCollection viewDidMoveToWindow]
必须调用 super
.
我在 NSTabView 的选项卡之一中嵌入了 NSCollectionView。 collection 已加载并正确显示,但在切换到任何其他选项卡后,应用程序崩溃并显示以下崩溃日志。崩溃指出无法为关键路径“firstResponder”删除观察者(ProjectTabLeadersCollection,它是我的 NSCollectionView 的 class)。我不确定到底发生了什么,因为我没有明确地为这个选项卡注册任何观察者,所以我假设 AppKit 在幕后做一些事情,以及我在 Interface Builder 或我的初始化代码中的设置不太正确。希望有人能在这里提供一些指导。
有什么想法吗?
2022-04-12 07:21:53.861124-0700 APBA Baseball[78639:4002869] [General] Cannot remove an observer <ProjectTabLeadersCollection 0x7f9e6b8df1e0> for the key path "firstResponder" from <NSWindow 0x7f9e7c044500> because it is not registered as an observer.
2022-04-12 07:21:53.864095-0700 APBA Baseball[78639:4002869] [General] (
0 CoreFoundation 0x00007ff809bf41e3 __exceptionPreprocess + 242
1 libobjc.A.dylib 0x00007ff809954c13 objc_exception_throw + 48
2 Foundation 0x00007ff80a9bf1ff -[NSObject(NSKeyValueObserverRegistration) _removeObserver:forProperty:] + 700
3 Foundation 0x00007ff80a9beeff -[NSObject(NSKeyValueObserverRegistration) removeObserver:forKeyPath:] + 129
4 AppKit 0x00007ff80c77f736 -[NSCollectionView viewWillMoveToWindow:] + 274
5 AppKit 0x00007ff80c5b449a -[NSView _setWindow:] + 277
6 AppKit 0x00007ff80ce04884 __21-[NSView _setWindow:]_block_invoke.425 + 299
7 CoreAutoLayout 0x00007ff811211cf3 -[NSISEngine withBehaviors:performModifications:] + 84
8 AppKit 0x00007ff80c5b4b04 -[NSView _setWindow:] + 1919
9 AppKit 0x00007ff80ce04884 __21-[NSView _setWindow:]_block_invoke.425 + 299
10 CoreAutoLayout 0x00007ff811211cf3 -[NSISEngine withBehaviors:performModifications:] + 84
11 AppKit 0x00007ff80c5b4b04 -[NSView _setWindow:] + 1919
12 AppKit 0x00007ff80c62f07e -[NSScrollView _setWindow:] + 93
13 AppKit 0x00007ff80ce04884 __21-[NSView _setWindow:]_block_invoke.425 + 299
14 CoreAutoLayout 0x00007ff811211cf3 -[NSISEngine withBehaviors:performModifications:] + 84
15 AppKit 0x00007ff80c5b4b04 -[NSView _setWindow:] + 1919
16 AppKit 0x00007ff80c5e3d8f -[NSView removeFromSuperview] + 158
17 AppKit 0x00007ff80c7a230f __56-[NSView replaceSubview:with:options:completionHandler:]_block_invoke + 40
18 AppKit 0x00007ff80c7a2106 -[NSView replaceSubview:with:options:completionHandler:] + 735
19 AppKit 0x00007ff80c77996b -[NSTabView _switchTabViewItem:oldView:withTabViewItem:newView:initialFirstResponder:lastKeyView:] + 859
20 AppKit 0x00007ff80c772e21 -[NSTabView selectTabViewItem:] + 512
21 AppKit 0x00007ff80c7791b3 -[NSTabViewController setSelectedTabViewItemIndex:] + 637
22 AppKit 0x00007ff80c7a16fe -[NSApplication(NSResponder) sendAction:to:from:] + 288
23 AppKit 0x00007ff80c7a15a4 -[NSControl sendAction:to:] + 86
24 AppKit 0x00007ff80c7a14d6 __26-[NSCell _sendActionFrom:]_block_invoke + 131
25 AppKit 0x00007ff80c7a13df -[NSCell _sendActionFrom:] + 171
26 AppKit 0x00007ff80c89c311 -[NSSegmentedCell _sendActionFrom:] + 161
27 AppKit 0x00007ff80c79e19f NSControlTrackMouse + 1813
28 AppKit 0x00007ff80c79da66 -[NSCell trackMouse:inRect:ofView:untilMouseUp:] + 121
29 AppKit 0x00007ff80c89ba45 -[NSSegmentedCell trackMouse:inRect:ofView:untilMouseUp:] + 712
30 AppKit 0x00007ff80c79cd06 -[NSControl mouseDown:] + 678
31 AppKit 0x00007ff80c79b1f1 -[NSWindow(NSEventRouting) _handleMouseDownEvent:isDelayedEvent:] + 4859
32 AppKit 0x00007ff80c70f39e -[NSWindow(NSEventRouting) _reallySendEvent:isDelayedEvent:] + 2582
33 AppKit 0x00007ff80c70e76e -[NSWindow(NSEventRouting) sendEvent:] + 352
34 AppKit 0x00007ff80c70cb44 -[NSApplication(NSEvent) sendEvent:] + 352
35 AppKit 0x00007ff80c9c596b -[NSApplication _handleEvent:] + 65
36 AppKit 0x00007ff80c58e35e -[NSApplication run] + 623
37 AppKit 0x00007ff80c5622b7 NSApplicationMain + 817
38 APBA Baseball 0x00000001058f8e22 main + 34
39 dyld 0x0000000109b1951e start + 462
我的选项卡视图设置如下:
NSCollection 位于名为 Leaders 的选项卡中,连接如下所示:
这是 collection 的 header:
@interface ProjectTabLeadersCollection : NSCollectionView <NSCollectionViewDataSource, NSCollectionViewDelegate> {
NSMutableArray *ar;
}
@end
接下来,.m 文件:
#import "ProjectTabLeadersCollection.h"
#import "ProjectTabLeadersCollectionItem.h"
@implementation ProjectTabLeadersCollection
-(void) viewDidMoveToWindow {
self.delegate = self;
self.dataSource = self;
ar = [[NSMutableArray alloc] init];
for (int i = 0; i < 100; ++i)
[ar addObject:@"Hello"];
}
- (void)collectionView:(NSCollectionView *)collectionView willDisplayItem:(nonnull NSCollectionViewItem *)item forRepresentedObjectAtIndexPath:(nonnull NSIndexPath *)indexPath {
}
- (void)collectionView:(NSCollectionView *)collectionView didEndDisplayingItem:(nonnull NSCollectionViewItem *)item forRepresentedObjectAtIndexPath:(nonnull NSIndexPath *)indexPath {
}
- (NSInteger) numberOfSectionsInCollectionView:(NSCollectionView *)collectionView {
return (1);
}
- (NSInteger) collectionView:(NSCollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return (ar.count);
}
- (NSCollectionViewItem *) collectionView:(NSCollectionView *)collectionView itemForRepresentedObjectAtIndexPath:(NSIndexPath *)indexPath
{
ProjectTabLeadersCollectionItem *item = [collectionView makeItemWithIdentifier:@"ProjectTabLeadersCollectionItem" forIndexPath:indexPath];
item->StatNameLabel.stringValue = [ar objectAtIndex:[indexPath item]];
return (item);
// ProjectTabStandingsCollectionItem *item = [collectionView makeItemWithIdentifier:@"ProjectTabStandingsCollectionItem" forIndexPath:indexPath];
// ProjectTeamObject *pto = [standings objectAtIndex:[indexPath item]];
//
// item->StandingsLabel.stringValue = pto.profile.city;
// return (item);
}
- (void)drawRect:(NSRect)dirtyRect {
[super drawRect:dirtyRect];
// Drawing code here.
}
@end
viewDidMoveToWindow
的文档指出
The default implementation does nothing
但 [NSCollectionView viewDidMoveToWindow]
已实施并开始观察 window 的 firstResponder
。 -[ProjectTabLeadersCollection viewDidMoveToWindow]
必须调用 super
.