Любой основной вызов MIDI приводит к тому, что приложение перестает отвечать на запросы - PullRequest
4 голосов
/ 08 мая 2019

У меня возникла проблема с Core MIDI в нескольких приложениях для iOS, над которыми я работаю, и в другом приложении, которое я скачал из App Store.

То, что появляется , происходит, когда происходит сбой Core MIDI-сервера. После этого любое взаимодействие с основными MIDI-функциями или свойствами делает вызывающее приложение не отвечающим. Следующая строка в AppDelegate's didFinishLaunchingWithOptions::

[MIDINetworkSession defaultSession].enabled = YES;

На этом этапе выполнение останавливается, что приводит к зависанию навсегда при отладке или к аварийному завершению #8badf00d.

Это происходит, даже если функция Core MIDI должна возвращать OSStatus - возвращаемое значение никогда не возвращается:

OSStatus s = MIDIObjectGetStringProperty(ref, kMIDIPropertyDisplayName, (CFStringRef*)&string);

Этот вызов (который находится в библиотеке PGMidi) также зависает, s не возвращается. Единственный способ решить эту проблему - перезагрузить устройство.

Основной MIDI-сервер перестает отвечать на запросы, похоже, связан с запуском нескольких сетевых сессий с подключенного Mac, но я не смог точно определить способ надежной репликации. Как и мои собственные приложения (которые используют библиотеку MIKMIDI), я столкнулся с не отвечающим поведением с midimittr, загруженным из App Store.

Конечно, я не контролирую, перестает ли Core MIDI Server отвечать на запросы. Но есть ли способ проверить состояние MIDI-сервера перед тем, как совершит вызовы, которые могут сделать мое приложение не отвечающим на запросы?


Обновление: 2019-05-10

Я обнаружил, что могу перевести MIDI-сервер iOS Core в это состояние без ответа, выполнив следующие действия:

  1. Установите сетевой сеанс MIDI на Mac в настройках Audio / MIDI.
  2. В приложении iOS подключитесь к этому сетевому MIDI-сеансу.
  3. Пусть Mac засыпает естественным образом (вызов режима сна из меню Apple не приводит к возникновению проблемы).
  4. Когда Mac перейдет в спящий режим, сделайте что-нибудь в приложении для iOS, которое будет называться Core MIDI.

Похоже, что MIDI-сервер iOS Core потерял соединение с MIDI-сетью Mac, но продолжает пытаться выполнить.


Обновление: 2019-05-17

Apple ответила на мой отчет об ошибке (# 50657978), сказав, что он дублирует другой отчет (# 49583498) и будет закрыт. По крайней мере, они знают об ошибке.


Обновление: 2019-07-17

В это состояние зависания Core MIDI можно также войти быстрее (для целей отладки), подключив сеть Core MIDI через Audio Music Setup, затем добавив фоновое изображение в свое приложение и включив режим полета на устройстве iOS.

1 Ответ

1 голос
/ 28 мая 2019

Мне удалось найти частичное решение этой проблемы. (Увы, поскольку основная причина, по-видимому, заложена в коде 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 минут, поэтому у вас будет достаточно времени, чтобы отобразить предупреждение и рекомендовать пользователю перезагрузить устройство.

...