NSTableView不在OSX 10.9上更新

时间:2014-01-18 16:09:03

标签: macos cocoa nstableview

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

this video中,你可以看到它在OSX 10.8上没有任何问题的方式。

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

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

问题:

  • NSTableView未按预期更新。如果按下我的钢琴键,则不会显示任何MIDI信息,几秒钟后我会收到异常。以下是XCode向我展示的截图:

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

  • 我停止了应用程序并重新启动它。现在,当按键时,我会不断调整应用程序窗口的大小,NSTableView会正确更新,没有例外,一切都很好。
  • 当我按几次钢琴键时相同。然后将一些其他应用程序带到前面,然后再将我的应用程序带到前面。同样,所有MIDI信息都在我的NSTableView中正确显示。

知道这是什么意思吗?它是OSX 10.9相关的问题,还是可以改成新的MacBook。我的选项用完了。

我尝试将我的应用程序的NSWindow作为IBOutlet连接到充当NSTableViewDataSource的控制器,并在我做了 [tableView reloadData] 之后立即尝试了以下调用

  • [窗口更新]
  • [橱窗展示]
  • [window flushWindow]

但没有任何帮助。任何帮助高度赞赏。

修改

在评论之后做了一些调试,实际上是在找错了地方。

这里有一些代码用于更多上下文:

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

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

在我的控制器的 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],因为那是在线程6 - 19__25 ... 下单击时的行(见上面的截图)。但是当我点击线程6 - 20 midiInputCallback 时,我会突出显示这一行。

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

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

1 个答案:

答案 0 :(得分:1)

  
    

*线程6 - 19__25 ...... *和reloadData

  

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

e.g。

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