ОБНОВЛЕНИЕ: нижеприведенное решение, на самом деле, не работало на iOS 4. По какой-то причине оно работало на 5, но не на 4, поэтому я придумал лучшее решение.
Проблема вызвана разрушением блока в фоновом режиме, поэтому я помещаю его в локальную переменную и в фоновом блоке вызываю его, а затем асинхронно передаю в блок основного потока, чтобы онвыпущен там.Это также грязно, но выглядит следующим образом:
void(^block)(void) = ^{/*do all the things*/};
dispatch_async(queue, ^{
block();
dispatch_async(dispatch_get_main_queue(), ^{
if ([block isKindOfClass:[NSString class]])
NSLog(@"Whoa, bro");
});
});
Код в основном потоке - это всего лишь уловка, чтобы убедиться, что компилятор не просто полностью оптимизирует код;Мне нужно, чтобы объект блока был наконец освобожден основным потоком.Похоже, этот код работает с уровнем оптимизации компилятора -Os
.
Так что я нашел решение своей проблемы, хотя это супер-хакерский вариант.После этого исправления я не смог воспроизвести проблему, хотя я думаю, что это очень плохой архитектурный дизайн.
Напомним, проблема в том, что у меня есть блок в фоновой очереди, который разрушается.Этот блок является объектом, и он имеет сильную ссылку на блок обратного вызова, который содержит сильную ссылку на себя.Фоновый блок освобождается из фоновой очереди.Поэтому я перевел вызов в другой диспетчерский вызов в основную очередь.Итак, мой метод извлечения исходит из этого:
dispatch_async(backgroundQueue, ^{
/* do all the things */
});
К этому:
dispatch_async(dispatch_get_main_queue(), ^{
dispatch_async(backgroundQueue, ^{
/* do all the things */
});
});
Код асинхронно отправляет блок в основную очередь, а затем отправляет блок в фоновую очередь.Поскольку фоновый блок является объектом и принадлежит области видимости основной очереди, он освобождается в основном потоке, вызывая возможное освобождение UITextView, в результате чего происходит сбой в основной очереди, что также решает мою проблему.
Очевидное архитектурное решение заключается в использовании ссылки __weak
на себя в моем блоке обратного вызова, но мне придется подождать, пока я не откажусь от поддержки iOS 4.3.