CALayer и внеэкранный рендеринг

У меня есть Paging UIScrollView с размером contentSize, достаточно большим, чтобы вместить несколько маленьких UIScrollView для масштабирования, viewForZoomingInScrollView - это viewController, который содержит CALayer для рисования страницы PDF. Это позволяет мне перемещаться по PDF так же, как в программе для чтения PDF-файлов ibooks.

Код, который рисует PDF (мозаичные слои), находится в:

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx;

И простое добавление «страницы» на видимый экран вызывает этот метод автоматически. Когда я меняю страницу, происходит некоторая задержка перед отрисовкой всех плиток, даже если объект (страница) уже был создан.

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

Есть здесь какие-нибудь идеи / общие ошибки?

Я пробовал:

[viewController.view.layer setNeedsLayout]; 
[viewController.view.layer setNeedsDisplay];

NB: Каждый метод является потокобезопасным при автономном использовании. Теперь я пытаюсь понять, как справиться с тем, где вызывающий класс хочет вызвать:

for (Object o : example.getAll()) {
    // problems if multiple threads perform this operation concurrently
    example.remove(b); 
}

Но, как уже отмечалось, нет гарантии, что состояние будет согласованным между вызовом getAll () и вызовами удалять(). Если это вызовут несколько потоков, у меня будут проблемы. Итак, мой вопрос - Как мне разрешить разработчику выполнять операцию потокобезопасным способом? В идеале я хочу обеспечить безопасность потоков таким образом, чтобы разработчику было сложно избежать / пропустить, но в то же время достичь несложно. Пока я могу придумать три варианта:

A: Сделайте блокировку «this», чтобы объект синхронизации был доступен для вызывающего кода, который затем может обернуть блоки кода. Недостаток: трудно обеспечить соблюдение во время компиляции:

synchronized (example) {
    for (Object o : example.getAll()) {
        example.remove(b);
    }
}

B: Поместите объединенный код в класс Example - и получите возможность оптимизировать реализацию, как в этом случае. Недостаток: боль при добавлении расширений и возможное смешивание несвязанной логики:

public class Example {
   ...
   public void removeAll() { 
       synchronized (lock) { Runtime.exec(program + " -clear"); } 
   }
}

C: Предоставьте класс Closure. Недостаток: избыточный код, потенциально слишком большой для блока синхронизации, на самом деле может облегчить взаимоблокировки:

public interface ExampleClosure {
    public void execute(Example example);
}
public Class Example {
    ...
    public void execute(ExampleClosure closure) { 
        synchronized (this) { closure.execute(this); } 
    }
}

example.execute(new ExampleClosure() {
        public void execute(Example example) { 
            for (Object o : example.getAll()) {
                example.remove(b);
            }
        }
    }
);

Что-то мне не хватает? Как следует ограничить область действия синхронизации, чтобы обеспечить потокобезопасность кода?

5
задан Mike 30 September 2010 в 14:46
поделиться