任何 Core MIDI 调用都会导致应用程序无响应
Any Core MIDI call causes app to become unresponsive
我在使用的几个 iOS 应用程序以及从 App Store 下载的另一个应用程序中遇到了 Core MIDI 问题。
似乎 正在发生的是核心 MIDI 服务器崩溃。发生这种情况后,与核心 MIDI 函数或属性的任何交互都会使调用应用程序无响应。以下行在 AppDelegate 的 didFinishLaunchingWithOptions:
:
[MIDINetworkSession defaultSession].enabled = YES;
执行在此时停止,导致调试时永远挂起,否则 #8badf00d
崩溃。
即使核心 MIDI 功能应该 return OSStatus 也会发生这种情况 - return 值永远不会返回:
OSStatus s = MIDIObjectGetStringProperty(ref, kMIDIPropertyDisplayName, (CFStringRef*)&string);
此调用(在 PGMidi 库中)也挂起,s
未被 returned。解决此问题的唯一方法是重新启动设备。
核心 MIDI 服务器变得无响应似乎与来自已连接 Mac 的 运行 多个网络会话有关,但我无法确定可靠复制的方法。除了我自己的应用程序(使用 MIKMIDI 库),我还遇到过从 App Store 下载的 midimittr 无响应行为。
当然,我无法控制核心 MIDI 服务器是否变得无响应。但是有没有办法在进行可能使我的应用程序无响应的调用之前检查 MIDI 服务器的状态?
更新时间:2019-05-10
我发现我可以通过以下步骤使 iOS 核心 MIDI 服务器进入这种无响应状态:
- 在 Audio/MIDI 设置中的 Mac 上设置网络 MIDI 会话。
- 在 iOS 应用程序中,连接到该网络 MIDI 会话。
- 让 Mac 自然进入睡眠状态(从 Apple 菜单调用睡眠似乎不会触发问题)。
- 一旦 Mac 进入睡眠状态,在 iOS 应用程序中执行一些操作,这将调用 Core MIDI。
所以就像 iOS 核心 MIDI 服务器失去了与 Mac 的 MIDI 网络的连接,但继续尝试和执行。
更新时间:2019-05-17
Apple 回复了我的错误报告 (#50657978),称它与另一份报告 (#49583498) 重复,将被关闭。至少他们知道这个错误。
更新时间:2019-07-17
通过音频音乐设置连接 Core MIDI 网络,然后在 iOS 设备上打开飞行模式并打开应用程序后台,也可以更快地进入此 Core MIDI 挂起状态(用于调试目的)。
请参阅下面的最新更新和最终解决方案
我已经想出了一个部分解决这个问题的方法。 (唉,因为根本原因似乎嵌入在 Apple 的代码中,所以不可能有完整的解决方案。)
在我的 AppDelegate 中,我现在 运行 一个可以检测对 Core MIDI 的调用是否超时的例程:
func enableMIDINetworkSession() {
let midiNetworkGroup = DispatchGroup()
midiNetworkGroup.enter()
DispatchQueue.global(qos: .background).async {
MIDINetworkSession.default().isEnabled = true
midiNetworkGroup.leave()
}
// If `midiNetworkGroup.leave()` is not reached in the closure above, then the result below will be `.timeOut`
let midiNetworkTimeoutResult = midiNetworkGroup.wait(timeout: DispatchTime.now() + 10.0)
switch midiNetworkTimeoutResult {
case .timedOut:
{ ... } // Calls to Core MIDI will cause app to hang. Handle as required. Note: app will crash anyway at some point in the future.
case .success:
break // All good, continue as before
}
}
这里要注意一件事:如果您打算在 midiNetworkTimeoutResult == .timeOut
的情况下显示警报,请记住在此之后立即发生的任何对 Core MIDI 的调用都可能导致不显示警报(因为主队列将被阻塞)。
更新时间:2019-07-17
重要的是要提到上面的解决方案,如果你最终遇到上面的 .timedOut
情况,应用程序将在未来的某个时候崩溃 无论如何,因为它赶上了 MIDINetworkSession.default().isEnabled
调用。
崩溃前的间隔大约为 5 分钟,因此有足够的时间显示警报并建议用户重启设备。
更新时间:2019-08-14
推荐的解决方案
Apple 在 iOS 12.4 中似乎已经解决了这个问题。解决方案是建议您的用户更新到 iOS 12.4 或更高版本。
(此外,这个问题似乎只影响 iOS 12.2 和 12.3 版本。)
我在使用的几个 iOS 应用程序以及从 App Store 下载的另一个应用程序中遇到了 Core MIDI 问题。
似乎 正在发生的是核心 MIDI 服务器崩溃。发生这种情况后,与核心 MIDI 函数或属性的任何交互都会使调用应用程序无响应。以下行在 AppDelegate 的 didFinishLaunchingWithOptions:
:
[MIDINetworkSession defaultSession].enabled = YES;
执行在此时停止,导致调试时永远挂起,否则 #8badf00d
崩溃。
即使核心 MIDI 功能应该 return OSStatus 也会发生这种情况 - return 值永远不会返回:
OSStatus s = MIDIObjectGetStringProperty(ref, kMIDIPropertyDisplayName, (CFStringRef*)&string);
此调用(在 PGMidi 库中)也挂起,s
未被 returned。解决此问题的唯一方法是重新启动设备。
核心 MIDI 服务器变得无响应似乎与来自已连接 Mac 的 运行 多个网络会话有关,但我无法确定可靠复制的方法。除了我自己的应用程序(使用 MIKMIDI 库),我还遇到过从 App Store 下载的 midimittr 无响应行为。
当然,我无法控制核心 MIDI 服务器是否变得无响应。但是有没有办法在进行可能使我的应用程序无响应的调用之前检查 MIDI 服务器的状态?
更新时间:2019-05-10
我发现我可以通过以下步骤使 iOS 核心 MIDI 服务器进入这种无响应状态:
- 在 Audio/MIDI 设置中的 Mac 上设置网络 MIDI 会话。
- 在 iOS 应用程序中,连接到该网络 MIDI 会话。
- 让 Mac 自然进入睡眠状态(从 Apple 菜单调用睡眠似乎不会触发问题)。
- 一旦 Mac 进入睡眠状态,在 iOS 应用程序中执行一些操作,这将调用 Core MIDI。
所以就像 iOS 核心 MIDI 服务器失去了与 Mac 的 MIDI 网络的连接,但继续尝试和执行。
更新时间:2019-05-17
Apple 回复了我的错误报告 (#50657978),称它与另一份报告 (#49583498) 重复,将被关闭。至少他们知道这个错误。
更新时间:2019-07-17
通过音频音乐设置连接 Core MIDI 网络,然后在 iOS 设备上打开飞行模式并打开应用程序后台,也可以更快地进入此 Core MIDI 挂起状态(用于调试目的)。
请参阅下面的最新更新和最终解决方案
我已经想出了一个部分解决这个问题的方法。 (唉,因为根本原因似乎嵌入在 Apple 的代码中,所以不可能有完整的解决方案。)
在我的 AppDelegate 中,我现在 运行 一个可以检测对 Core MIDI 的调用是否超时的例程:
func enableMIDINetworkSession() {
let midiNetworkGroup = DispatchGroup()
midiNetworkGroup.enter()
DispatchQueue.global(qos: .background).async {
MIDINetworkSession.default().isEnabled = true
midiNetworkGroup.leave()
}
// If `midiNetworkGroup.leave()` is not reached in the closure above, then the result below will be `.timeOut`
let midiNetworkTimeoutResult = midiNetworkGroup.wait(timeout: DispatchTime.now() + 10.0)
switch midiNetworkTimeoutResult {
case .timedOut:
{ ... } // Calls to Core MIDI will cause app to hang. Handle as required. Note: app will crash anyway at some point in the future.
case .success:
break // All good, continue as before
}
}
这里要注意一件事:如果您打算在 midiNetworkTimeoutResult == .timeOut
的情况下显示警报,请记住在此之后立即发生的任何对 Core MIDI 的调用都可能导致不显示警报(因为主队列将被阻塞)。
更新时间:2019-07-17
重要的是要提到上面的解决方案,如果你最终遇到上面的 .timedOut
情况,应用程序将在未来的某个时候崩溃 无论如何,因为它赶上了 MIDINetworkSession.default().isEnabled
调用。
崩溃前的间隔大约为 5 分钟,因此有足够的时间显示警报并建议用户重启设备。
更新时间:2019-08-14
推荐的解决方案
Apple 在 iOS 12.4 中似乎已经解决了这个问题。解决方案是建议您的用户更新到 iOS 12.4 或更高版本。
(此外,这个问题似乎只影响 iOS 12.2 和 12.3 版本。)