Зачем было бы вызывать что-то с переднего плана cra sh, когда это не вызывается из фона? - PullRequest
0 голосов
/ 04 августа 2020

Хорошо, относительно новая (опять же) цель C, пришедшая из фона Swift. В нашей кодовой базе у нас есть эта строка кода ...

return _queryURL && ![[UIApplication sharedApplication] canOpenURL:_queryURL];

, и пока она работает, при отладке Xcode выдает предупреждение о том, что canOpenURL должен быть выполнен из потока переднего плана.

'Достаточно просто', я думаю ... 'Я просто вызову его синхронно в потоке переднего плана!' и я обновляю код следующим образом ...

__block BOOL result = NO;
  
dispatch_sync(dispatch_get_main_queue(), ^{
  result = _queryURL && ![[UIApplication sharedApplication] canOpenURL:_queryURL];
});

return result;

... но теперь, когда я выполняю строку, которая вызывает canOpenURL, я получаю это ...

Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)

А ?! Почему толкание его в основной поток вызовет EXC_BAD_INSTRUCTION cra sh? Это отвлекающий маневр?

Что еще более важно, как вы решаете эту проблему?

Ответы [ 2 ]

1 голос
/ 04 августа 2020

Я видел, что неправильная инструкция ошибка возникает, когда вы sync вызываете что-то в основном потоке, когда вы уже в основном потоке.

Я думаю, что на основании ошибки и предупреждения, которое вы получаете, вы вызываете это иногда из фона, а иногда и в основном. Таким образом, вам необходимо проверить, например,

NSThread.isMainThread

или подобное, прежде чем звонить, а затем, исходя из этого, возможно,

if ( NSThread.isMainThread )
{
  // my call
}
else
{
  dispatch_sync( dispatch_get_main_queue (), ^ {
    // my call
  } );
}

Однако, если это действительно так, вы иногда звоните из основного, а иногда и из фона, вам также необходимо убедиться, что лог c за ним имеет смысл.

0 голосов
/ 04 августа 2020

Просто чтобы добавить к правильному ответу, я достаточно часто сталкиваюсь с этим (обычно в обозревателях свойств), что создал для него функцию:

void ExecuteOnMain( dispatch_block_t block )
{
    // Shorthand for synchronously executing a block on the main thread before returning.
    // Unlike dispatch_sync(), this won't deadlock if executed on the main thread.
    if (NSThread.isMainThread)
        block(); // main thread: execute the block immediately
    else
        dispatch_sync(dispatch_get_main_queue(),block); // not the main thread, queue the block
}

Тогда все, что вам нужно написать, это

__block BOOL result = NO;
  
ExecuteOnMain(), ^{
  result = _queryURL && ![[UIApplication sharedApplication] canOpenURL:_queryURL];
});

return result;
...