У меня есть метод, который принимает блок и блок завершения. Первый блок должен работать в фоновом режиме, а блок завершения должен выполняться в той очереди, в которой был вызван метод.
Последнее я всегда использовал dispatch_get_current_queue()
, но похоже, что он устарел в iOS 6 или выше. Что мне использовать вместо этого?
dispatch_get_current_queue()
это устарело в iOS 6? в документах ничего об этом не сказаноОтветы:
Шаблон «запускать в любой очереди, в которой находился вызывающий» привлекателен, но в конечном итоге не является хорошей идеей. Эта очередь может быть очередью с низким приоритетом, основной очередью или какой-либо другой очередью с нечетными свойствами.
Мой любимый подход к этому - сказать, что «блок завершения выполняется в очереди, определенной реализацией со следующими свойствами: x, y, z», и позволить блоку отправляться в конкретную очередь, если вызывающий хочет больше контроля, чем это. Типичный набор свойств, который нужно указать, будет чем-то вроде «последовательный, без повторного входа и асинхронный по отношению к любой другой видимой для приложения очереди».
** РЕДАКТИРОВАТЬ **
Catfish_Man поместил пример в комментариях ниже, я просто добавляю его к его ответу.
источник
Это принципиально неправильный подход к API, который вы описываете. Если API принимает блок и блок завершения для запуска, должны быть верными следующие факты:
«Блок для запуска» должен запускаться во внутренней очереди, например, в очереди, которая является частной для API и, следовательно, полностью находится под контролем этого API. Единственное исключение из этого - если API специально объявляет, что блок будет запускаться в основной очереди или одной из глобальных параллельных очередей.
Блок завершения всегда должен быть выражен как кортеж (очередь, блок), если не выполняются те же предположения, что и для # 1, например, блок завершения будет запущен в известной глобальной очереди. Кроме того, блок завершения должен быть отправлен асинхронно в очередь передачи.
Это не просто стилистические моменты, они совершенно необходимы, если ваш API должен быть защищен от взаимоблокировок или другого крайнего поведения, которое в противном случае когда-нибудь повесит вас на ближайшем дереве. :-)
источник
Другие ответы хороши, но для меня ответ структурный. У меня есть такой метод на Singleton:
который имеет две зависимости, а именно:
и
Таким образом я централизирую свои вызовы для отправки в другой поток.
источник
Вы должны быть осторожны с вашим использованием
dispatch_get_current_queue
в первую очередь. Из файла заголовка:Вы можете сделать одно из двух:
Сохраните ссылку на очередь, в которой вы изначально разместили (если вы создали ее через
dispatch_queue_create
), и используйте ее с тех пор.Используйте определенные системой очереди через
dispatch_get_global_queue
и отслеживайте, какую из них вы используете.Фактически, хотя раньше вы полагались на систему, чтобы отслеживать очередь, в которой вы находитесь, вам придется делать это самостоятельно.
источник
dispatch_get_current_queue()
чтобы узнать, какая это очередь? Иногда код, которому нужно знать, в какой очереди он запущен, не имеет никакого контроля или информации о нем. У меня есть много кода, который может (и должен) выполняться в фоновой очереди, но иногда мне нужно обновлять графический интерфейс (индикатор выполнения и т. Д.), И поэтому для этих операций необходимо использовать dispatch_sync () в основной очереди. Если он уже находится в основной очереди, dispatch_sync () заблокируется навсегда. На рефакторинг кода для этого у меня уйдут месяцы.Apple устарела
dispatch_get_current_queue()
, но оставила дыру в другом месте, поэтому мы все еще можем получить текущую очередь отправки:По крайней мере, это работает для основной очереди. Обратите внимание, что
underlyingQueue
свойство доступно с iOS 8.Если вам нужно выполнить блок завершения в исходной очереди, вы также можете использовать его
OperationQueue
напрямую, я имею в виду без GCD.источник
Для тех, кому еще нужно сравнение очередей, вы можете сравнить очереди по их метке или указателям. Отметьте это https://stackoverflow.com/a/23220741/1531141
источник
Это тоже мой ответ. Итак, я расскажу о нашем варианте использования.
У нас есть уровень сервисов и уровень пользовательского интерфейса (среди других слоев). Слой служб выполняет задачи в фоновом режиме. (Задачи обработки данных, задачи CoreData, сетевые вызовы и т. Д.). Уровень обслуживания имеет несколько очередей операций для удовлетворения потребностей уровня пользовательского интерфейса.
Уровень пользовательского интерфейса полагается на уровень сервисов для выполнения своей работы, а затем запускает блок успешного завершения. В этом блоке может быть код UIKit. Простой вариант использования - получить все сообщения с сервера и перезагрузить представление коллекции.
Здесь мы гарантируем, что блоки, которые передаются на уровень служб, будут отправлены в очередь, в которой была вызвана служба. Поскольку dispatch_get_current_queue является устаревшим методом, мы используем NSOperationQueue.currentQueue, чтобы получить текущую очередь вызывающего. Важное примечание об этой собственности.
Поскольку мы всегда вызываем наши службы в известной очереди (наши пользовательские очереди и основная очередь), это хорошо для нас работает. У нас действительно есть случаи, когда serviceA может вызвать serviceB, который может вызвать serviceC. Поскольку мы контролируем, откуда происходит первый вызов службы, мы знаем, что остальные службы будут следовать тем же правилам.
Таким образом, NSOperationQueue.currentQueue всегда будет возвращать одну из наших очередей или MainQueue.
источник