ARC __bridge cast Block_copy & Block_release - PullRequest
4 голосов
/ 14 марта 2012

По какой-то причине я хочу, чтобы блок выполнялся во время следующей итерации цикла выполнения, поэтому я придумал:

typedef void (^resizer_t)() ;

- (void) applyResizer: (resizer_t) resizer {
    resizer() ;
    Block_release(resizer) ;
}

- (void) usage {
    ...
    resizer_t resizer = ^() {
        // stuff
    } ;

    [self performSelectorOnMainThread:@selector(applyResizer:)
                           withObject:(__bridge id) Block_copy((__bridge void *) resizer)
                        waitUntilDone:NO] ;
}
  1. Разве это не иронично, что я должен привести к аннулированию * аргумент Блок _copy?
  2. Почему компилятор доволен моим Block_release, когда он задыхается на Block_copy без моста void * cast?

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

Ответы [ 2 ]

13 голосов
/ 14 марта 2012

Блок обрабатывается как объекты, поэтому ARC не позволяет вам приводить их к void * без явного связывания.Странно, что ваш компилятор не жалуется на Block_release: он должен (на моем компьютере это делает).

Поскольку ARC рассматривает блок как объекты, вам не нужно использовать Block_copy и Block_release больше.Скопируйте блок (с помощью -[NSObject copy]), когда вы хотите, чтобы он переместился в кучу, и позвольте компилятору управлять остатком.

-[NSObject performSelectorOnMainThread:withObject:waitUntilDone:] сохраняет получатель и объект параметра, пока метод не будет вызван.Таким образом, ваш блок будет сохранен и освобожден при необходимости.Все, что вам нужно сделать, это убедиться, что блок не сохранен в стеке, отправив сообщение copy перед передачей его методу.

Более того, существует более простой способ диспетчеризации выполненияблок: это libdispatch (он же GCD).

dispatch_async(dispatch_get_main_queue(), resizer);
4 голосов
/ 14 марта 2012

Я хочу, чтобы блок выполнялся во время следующей итерации цикла выполнения

Вот почему у вас есть dispatch_after.Если вы укажете крошечное значение времени, оно будет иметь именно тот эффект, который вам нужен: вы даете блок, и блок будет выполняться, как только закончится текущий цикл выполнения и наступит момент перерисовки.

Или еслиВы можете жить, не настаивая на блоке, используйте performSelector:withObject:afterDelay: с небольшим значением задержки (даже ноль).Это имеет тот же эффект.

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

...