2013-07-17 2 views
2

Это фрагмент из примеров кода AFNetworking в:нужно объяснение этого использования блока в качестве параметра метода

+ (void)globalTimelinePostsWithBlock:(void (^)(NSArray *posts, NSError *error))block { 
    [[AFAppDotNetAPIClient sharedClient] getPath:@"stream/0/posts/stream/global" parameters:nil success:^(AFHTTPRequestOperation *operation, id JSON) { 
     NSArray *postsFromResponse = [JSON valueForKeyPath:@"data"]; 
     NSMutableArray *mutablePosts = [NSMutableArray arrayWithCapacity:[postsFromResponse count]]; 
     for (NSDictionary *attributes in postsFromResponse) { 
      Post *post = [[Post alloc] initWithAttributes:attributes]; 
      [mutablePosts addObject:post]; 
     } 

     if (block) { 
      block([NSArray arrayWithArray:mutablePosts], nil); 
     } 
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) { 
     if (block) { 
      block([NSArray array], error); 
     } 
    }]; 
} 

То, что я не понимаю, являются:

  1. (void (^)(NSArray *posts, NSError *error))block часть. Предполагая, что это блок, означает ли это, что блок является параметром метода globalTimelinePostsWithBlock?

  2. Следуя первому вопросу, может ли кто-нибудь объяснить синтаксис для меня? Почему в конце есть ключевое слово block?

ответ

2

, если вы не знаете, как работают блоки .. тогда не беспокойтесь, пытаясь понять это, просто посмотрев на код (даже если вы использовали лямбда-анонимные функции на других языках, таких как javascript или ruby). b/c синтаксис object-c - это класс на нем собственный ..

Я бы порекомендовал вам потратить время, чтобы понять синтаксис блока в obj-c на своем собственном .. затем взгляните на примеры, которые их используют. Это tutorial отменно (две части) ..

Я сделал то, что вы делали раньше .. и вытащил половину моих волос .. посмотрев на указанном учебнике .. мои волосы росли обратно вверх :)


просто для удовольствия я постараюсь решить ваши конкретные вопросы:

1.The (вакуум (^) (NSArray * сообщения, NSError * ошибка)) часть блока. Предполагая, что это блок, означает ли это, что блок является параметром метода globalTimelinePostsWithBlock?

да это .. так что это способ вызова этого метода:

// first define the block variable 
void(^block)(NSArray *posts, NSError *error) = (NSArray *posts,NSError *error) { 

    // block body 
    // posts and error would have been passed to this block by the method calling the block. 
    // so if you look at the code sample below.. 
    // posts would be [NSArray arrayWithArray:mutablePosts] 
    // and error would just be nil 
} 

// call the function 
[AFNetworking globalTimelinePostsWithBlock:block];  

2. После первого вопроса, может кто-нибудь объяснить синтаксис для меня? Почему в конце есть ключевое слово block?

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

if (block) { 
      block([NSArray arrayWithArray:mutablePosts], nil); 
     } 

снова, чтобы понять, как/почему .. я рекомендую вам посмотреть на выше статья .. обучающие блоки в obj-c имеет немного кривой обучения .. но как только вы овладеете им, это потрясающий инструмент.пожалуйста, взгляните на мой answer здесь, чтобы увидеть пример использования образцов для блоков.

Here также является образцовым вопросом/ответом, в котором приводится пример преобразования делегирования в блок-подход, который также может иллюстрировать работу блоков.

+0

Спасибо за ответ! Поэтому я предполагаю, что следующий вопрос заключается в следующем примере: '(int) (^ name) (int)', где имя расположено после типа возврата, почему это происходит в AFNetworking выше , имя ('block') записывается после параметра? – hfz

+1

это две разные вещи .. '(int) (^ name) (int)' - это имя переменной, указывающей на блок, тогда как '(void (^) (NSArray * posts, NSError * error)) block' является аргументом * type *, и этот аргумент называется «block» .. он занимает некоторое время, чтобы утонуть в .. не торопите его :) теперь я могу получить мой +1? ;) – abbood

+0

@hfz, если вы все еще смотрите в блоки .. проверьте [this] (http://stackoverflow.com/questions/17773067/how-to-add-an-extra-argument-to-a-block) вне! – abbood

1

Блок передается в метод как нечто вызываемое при успешном вызове API. globalTimelinePostsWithBlock будет вызывать блок, прошедший с данными (и, возможно, NSError)

block В этом случае это не ключевое слово, это просто имя переменной.

Если вы хотите использовать globalTimelinePostsWithBlock, вы могли бы назвать его как

[ClassName globalTimelinePostsWithBlock:^(NSArray *posts, NSError *error) { 
    // Check error, then do something with posts 
}]; 

(где ClassName это имя класса globalTimelinePostsWithBlock определяется на)

+2

Чтобы уточнить, 'block' никогда не является ключевым словом. '__block' - это ключевое слово. –

1

Определение блока аналогично C-функциям.

(void (^)(NSArray *posts, NSError *error))block 
  • Начальная void определяет тип возвращаемого функцией.
  • ^ - указатель блока. Подобно * для объектов.
  • (NSArray *posts, NSError *error) - это параметры с именами переменных.
  • block - это переменная, в которой этот блок сохраняется. (Плохие имена здесь)
+1

Спасибо, что ответили, особенно часть «плохое имя здесь». Это смутило меня больше всего, и мне было трудно найти, почему он был использован так. – hfz

Смежные вопросы