Objective-C и Quartz Composer; [qcView pauseRendering] вызывает Bad_Access

заранее спасибо.

У меня есть Quartz Composer View (qcView ниже) и я перемещаю изображение (муравья, если вас интересует код) в случайном направлении, пока оно не найдет «дом» в середине QCView. Пауза Rendering необходима для того, чтобы мы могли видеть, как муравей движется дюйм за дюймом; без него муравей просто появится у своего «дома».

while([self distance] > acceptableOffset){
    [qcView pauseRendering];
    [self moveTowardsDestination:@"home"];
    [qcView resumeRendering];
}

Это прекрасно работает для одного муравья.

Когда я добавляю в уравнение еще одного муравья, я использую очередь отправки и два блока.

    dispatch_async(queue, ^{
        [theAnt findCenter];
    });

    dispatch_async(queue, ^{
        [otherAnt findCenter];
    });

Когда этот код запускается, две тетушки одновременно бегут к своим домам — именно то поведение, которое мы ищем. Однако, когда я останавливаю выполнение и снова строю, я немедленно получаю Exc_Bad_Access где-то внутри метода [qcView pauseRendering]. После очистки и сборки он будет работать еще один раз. Если пауза и возобновление рендеринга удалены, муравьи мгновенно появятся в своем доме.

По-видимому, существует массив, локальный для метода QCView pauseRendering, который постоянно увеличивается и уменьшается, и с помощью одного QCView и нескольких блоков, обращающихся к нему, вы можете увидеть корень проблемы.

Я изучил QCView документацию и, похоже, не находит там вдохновения; документация по pauseRendering минимальна. Хотя я уверен, что никто из вас не пробовал что-то столь же глупое, как это, я надеюсь, что у кого-то будет опыт прагматической модификации QCView, и он сможет указать мне правильное (ошибаюсь... читай "ЛЮБОЕ!") направление. .

[Редактировать: я пробовал варианты «пока (! [qcView isPausedRendering])», если это помогает.]


person Rubber Duck    schedule 06.02.2011    source источник


Ответы (2)


Вы уверены, что экземпляры QCView действительно поддерживают параллелизм?

Очень вряд ли. Если вы удаляете представления из отдельных потоков или очередей — даже не одновременно из фоновой очереди/потока — вы, скорее всего, нарушаете правила параллелизма QCView.

Я подозреваю, что вы должны манипулировать представлением из основного потока или, по крайней мере, из одного потока за раз.

(Конкретной информации по этому поводу я, к сожалению, не нашел).

person bbum    schedule 06.02.2011
comment
Спасибо за быстрый ответ. Документация кажется скудной, и последующие поиски в Google не дают релевантных результатов по «qcview concurrency». Интуитивно, не могли бы вы предположить, что процедуры блокировки могут решить проблему приостановки? - person Rubber Duck; 06.02.2011
comment
Возможно нет; как правило, вы не можете сделать что-то потокобезопасным, установив вокруг него блокировки, потому что у вас нет контроля над внутренней реализацией. Я думаю, что список Quartz Composer может быть на lists.apple.com. Если это так, то запрос с большей вероятностью дойдет до одного из инженеров QC. - person bbum; 06.02.2011

Решил это.

Оказывается, я сильно переоценил проблему. Простое исправление использования

     usleep(10000);

Иди разберись.

Первоначально это было в коде, однако оно было заменено на dispatch_suspend(). Желаемая активность достигается за счет сна на линии непосредственно перед приостановкой.

Если у кого-то возникнут подобные проблемы, пишите мне на почту.

person Rubber Duck    schedule 06.02.2011
comment
Если вы используете usleep() в качестве примитива синхронизации, вы делаете это неправильно. Гарантированно сломается когда-нибудь в будущем по, казалось бы, неизвестным причинам. - person bbum; 03.10.2011