macos - NSTableView 未在 OSX 10.9 上更新

标签 macos cocoa nstableview

我最初在 OSX 10.8 下编写了一个小型应用程序,它通过 MidiEventCallback 接收 MIDI 事件,并将数据放入 NSMutableArray(NSTableViewDataSource 的成员)中。

this video你可以看到它是如何在 OSX 10.8 上毫无问题地工作的。

现在我有一台运行 OSX 10.9 的新 MacBook,安装了 XCode 并获取了所有项目文件并编译了应用程序。

已将我的 MIDI Controller 连接到我的 MacBook,启动应用程序并按下 MIDI Controller 上的按键。

问题:

  • NSTableView 没有按应有的方式更新。如果我按下钢琴键,则不会显示 MIDI 消息,几秒钟后我会收到异常。下面是 XCode 向我展示的屏幕截图:

Exception when playing my MIDI piano without resizing the window of my application.

  • 我停止应用程序并重新启动它。现在,当按下按键时,我会不断调整应用程序窗口的大小,并且 NSTableView 会正确更新,没有异常(exception),一切都很好。
  • 当我按一些钢琴键几次时也是如此。然后将其他一些应用程序放在前面,然后再将我的应用程序放在前面。同样,所有 MIDI 消息都正确显示在我的 NSTableView 中。

知道这是什么吗?这是 OSX 10.9 相关问题还是更换新 MacBook 时出现的问题。我已经没有选择了。

我尝试过的是将应用程序的 NSWindow 作为 IBOutlet 连接到充当 NSTableViewDataSource 的 Controller ,并在执行[tableView reloadData]后立即尝试以下调用

  • [窗口更新]
  • [窗口显示]
  • [窗口flushWindow]

但没有任何帮助。非常感谢任何帮助。

编辑

根据评论进行了一些更多的调试,实际上看到了错误的地方。

这里有一些代码以了解更多上下文:

我的 Controller 有一个名为 MidiEventListener 的属性,它接收所有 MIDI 事件并将它们放入 eventList 中。

@interface MidiAidController()
  ...
  @property NSMutableArray *eventList;
  @property MidiEventListener* listener;
@end

在 Controller 的 init 方法中,我执行以下操作

_eventList = [[NSMutableArray alloc] init];
MidiEventCallback eventCallback = ^(MidiEvent* midiEvent)
{
  [[self eventList] addObject:midiEvent];
  [[self tableView] reloadData];
};
...
self.listener = [[MidiEventListener alloc] initWithCallback:eventCallback];

MidiEventListener 中的 initWithCallback 中,会发生以下情况:

result = MIDIInputPortCreate(_midiClient, CFSTR("Input"), midiInputCallback, (__bridge_retained void *)(self), &_inputPort);

现在,让我们看看midiInputCallback:

static void midiInputCallback(const MIDIPacketList* list, void *procRef, void *srcRef)
{
  MidiEventListener *midiEventListener = (__bridge MidiEventListener*)procRef;
  @autoreleasepool {
    const MIDIPacket *packet = &list->packet[0];

    for (unsigned int i = 0; i < list->numPackets; i++)
    {
        MidiEvent* midiEvent = [[MidiEvent alloc] initWithPacket:packet];
        midiEventListener.midiEventCallback(midiEvent);
        packet = MIDIPacketNext(packet);
    }
  }
}

基本上就是这样。异常发生在 midiEventListener.midiEventCallback(midiEvent);。我总是查看 *[tableView reloadData],因为这是在 Thread 6 - 19__25... 下单击时的行(请参见上面的屏幕截图)。但是当我点击Thread 6 - 20 midiInputCallback时,我会突出显示这一行。

解决方案

重新加载数据必须从主线程完成:

MidiEventCallback eventCallback = ^(MidiEvent* midiEvent)
{
  [[self eventList] addObject:midiEvent];
  dispatch_async(dispatch_get_main_queue(), ^(void){[[self tableView] reloadData];});
};

最佳答案

*Thread 6 - 19__25...* and reloadData

仅在主线程上调用重新加载

例如

void MyCallback(...) {
    dispatch_async(dispatch_get_main_queue(), ^{
        ...
    }
}

关于macos - NSTableView 未在 OSX 10.9 上更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21206511/

相关文章:

php - xDebug 似乎安装正常,但无法与 NetBeans 连接

Mac OS X 上的 python 套接字给出 AttributeError : 'module' object has no attribute 'IF_INET'

objective-c - 删除 cocoa TableView 上的数据

macos - Powerlevel10k 的 transient 提示是否应该保留在窗口底部?

cocoa - 如果没有将 WebView 添加到窗口,NSWindowController 无法捕获 ESC

cocoa - NSTableView 不响应向上/向下箭头键

iphone - 获取 UIView 中的 subview

cocoa - 对 NSArrayController 支持的 NSTableView 进行排序

cocoa - 使 NSTableView 滚动的行为类似于 UITableView 滚动

shell - 修改 *plist 文件中的子键