Блоки и Переменные - PullRequest
       4

Блоки и Переменные

4 голосов
/ 10 февраля 2012

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

1) Не работает. Нужно __block, потому что я хочу изменить объект. И самообеспечение сохраняется (правильно?) И в блогах меня пугает сохранение цикла самообслуживания. Это так?

NSDictionary *result = nil;
dispatch_async(queue, ^{
    result = [self sendRequest:apiRequest];
});

2) Не работает. Я не понимаю о области видимости переменной dispatch_async (dispatch_get_main_queue (), ^ {}) ;. Он видит все локальные переменные в основном потоке или это отдельный блок от основного потока, но исключен в основном потоке? Как dispatch_async (dispatch_get_main_queue () ^ {}); копирует все локальные переменные в dispatch_async (очередь, ^ {}); и переключает семафор в основной поток.

NSDictionary *result = nil;
dispatch_async(queue, ^{
    NSDictionary *data = [self sendRequest:apiRequest];
    dispatch_async(dispatch_get_main_queue(), ^{
        result=[data retain];
    });
}); 

3) И примеры из блогов и Стэнфордского курса, которые меня особенно запутывают, потому что они работают.

- (void)viewWillAppear:(BOOL)animated
{
    dispatch_queue_t downloadQueue = dispatch_queue_create(“image downloader”, NULL);
    dispatch_async(downloadQueue, ^{
         NSData *imageData = [NSData dataWithContentsOfURL:networkURL];
         dispatch_async(dispatch_get_main_queue(), ^{
             UIImage *image = [UIImage imageWithData:imageData];
             self.imageView.image = image;
             self.imageView.frame = CGRectMake(0, 0, image.size.width, image.size.height);
             self.scrollView.contentSize = image.size;
         });
    });
    dispatch_release(downloadQueue);
}

Я не понимаю, потому что сначала они не упоминают о __block для себя в статьях и на уроках, во-вторых, этот код изменяет переменные, но через свойства и компилятор не дает клятву, что переменные не присваиваются и свойства изменяют ссылку, а не значение. Окончательно это работает. Заранее спасибо.

Ответы [ 2 ]

5 голосов
/ 20 октября 2012

Старый вопрос, но я чувствую, что новые читатели могли бы получить более точный ответ, чем текущий:

1) result - это указатель на объект, а не сам объект. Предварительно __block необходимо, потому что этот указатель назначен в пределах блока. Изменение объектов, на которые указывают переменные-указатели вне блока, не является проблемой, например,

NSMutableDictionary* result = [NSMutableDictionary new];

и затем изменение объекта в блоке с помощью [result setObject...] будет в порядке. И вот почему работает 3): изменяются только переменные объекта, на который указывает self. Указатель self никогда не назначается.

Относительно сохранения под ARC объектов, на которые ссылается блок, см., Например ::

ARC с блоками и циклами удержания

ARC, блоки и циклы удержания

блоков и ARC - копирование или сбой при сборке релиза (вызвано уровнем оптимизации)

2 голосов
/ 10 февраля 2012

1) Да, вам нужно объявить:

__block NSDictionary *results = nil;

Если вы используете ARC, он должен автоматически позаботиться о сохранении и освобождении объекта результатов.Если вы не используете ARC, выполните retain как первое, что вы делаете, и release как последнее, что вы сделаете в блоке.

2) Блок должен иметь видимость всех переменных / объектовдоступны для родительского охвата.Таким образом, в методе вы должны иметь возможность видеть все локальные переменные этого метода и объект, которому принадлежит этот метод (как self).

3) Не слишком уверен в этом.Переменные исчезают, как только вы покидаете функцию / метод (что будет так, как если бы большинство блоков вызывалось , а не завершалось выполнение), а все, что является частью self, не будет.Может быть, это как-то связано с этим.

...