我最初在 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 向我展示的屏幕截图:
- 我停止应用程序并重新启动它。现在,当按下按键时,我会不断调整应用程序窗口的大小,并且 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];});
};
最佳答案
block 引用>*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/