Список синтаксических объявлений блока

Синтаксис блока в Objective C (и, действительно, C, я полагаю), как известно, несоответствующий. Передача блоков в качестве аргументов выглядит иначе, чем объявление блоков как ivars, которое выглядит иначе, чем typedef ing блоки.

Есть ли полный список синтаксиса объявления блока, который я мог бы держать под рукой для быстрой справки?

Ответ 1

Синтаксис декларации блоков блока

Всюду, пусть

  • return_type - тип объекта/примитива/и т.д. вы хотели бы вернуться (обычно void)
  • blockName - имя переменной создаваемого блока.
  • var_type - тип object/primitive/etc. вы хотите передать аргумент (оставьте пустым без параметров)
  • varName - имя переменной данного параметра

И помните, что вы можете создать столько параметров, сколько захотите.

Блоки как переменные

Возможно, наиболее распространенный для объявления.

return_type (^blockName)(var_type) = ^return_type (var_type varName)
{
    // ...
};

Блокирует как свойства

Во многом как объявление блоков в качестве переменных, однако тонко отличается.

@property (copy) return_type (^blockName) (var_type);

Блоки как параметры

Обратите внимание, что это отличается от "Блоки как аргументы"; в этом случае вы объявляете метод, который хочет аргумент блока.

- (void)yourMethod:(return_type (^)(var_type))blockName;

Блоки как аргументы

Обратите внимание, что это отличается от "Блоки как параметры"; в этом случае вы вызываете метод, которому нужен блок-аргумент с анонимным блоком. Если вы уже объявили блочную переменную, достаточно передать имя переменной в качестве аргумента.

[someObject doSomethingWithBlock: ^return_type (var_type varName)
{
    //...
}];

Анонимный блок

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

^return_type (var_type varName)
{
    //...
};

typedef Блок

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

typedef return_type (^blockName)(var_type);

Чтобы затем использовать blockName вместо стандартного синтаксиса объявления блока, просто замените.

Встроенный блок

Это, возможно, менее полезное использование блоков, но тем не менее может иметь свое место. Встроенный блок представляет собой анонимный блок, вызываемый сразу после создания экземпляра.

^return_type (var_type varName)
{
    //...
}(var);

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

{
   //...
}

Рекурсивные блоки

Это позволяет вам вызывать блок из себя, создавая цикл, который можно использовать во время обратных вызовов и вызовов GCD. Этот метод создания экземпляров не содержит циклов сохранения в ARC.

__block return_type (^blockName)(var_type) = [^return_type (var_type varName)
{
    if (returnCondition)
    {
        blockName = nil;
        return;
    }

    // ...
} copy];
blockName(varValue);

Возвращаемые блоки

Метод может возвращать блок,

- (return_type(^)(var_type))methodName
{
    // ...
}

как функция, если немного странно.

return_type (^FunctionName())(var_type)
{
    // ...
}

Дополнения

Если я что-то пропустил, сообщите мне в комментариях, и я буду исследовать/добавлять их.

О, а в Swift...

blockName = (varName: var_type) -> (return_type)

Это почти как функция языка.

Ответ 2

Мне лично нравится использовать этот сайт (http://fuckingblocksyntax.com). Имя легче запомнить, чем сам синтаксис блока:

http://fuckingblocksyntax.com

и если вы не можете загружать URL-адреса с плохими словами в них, вы можете использовать это зеркало: http://goshdarnblocksyntax.com

fuckingblocksyntax website

Ответ 3

Typedef:

typedef void (^block)(NSString *arg);

Инлайн:

void (^block)(NSString *) = ^(NSString *param) {
  // do something....
};

Метод:

- (void)method:(void (^)(NSString *param))handler

Ответ 4

Библиотека фрагментов Xcode 4 содержит шаблоны для блоков typedefs и встроенных блоков в качестве переменных. Они также доступны через автозаполнение (typedefblock и inlineblock).

Для блоков в качестве аргументов для методов я бы рекомендовал объявить a typedef, а затем просто использовать это. Это упрощает чтение кода.

Ответ 5

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

  • Определите typedef с объявлением returnType (.h выше @interface)

    typedef void (^CompleteDiceRolling)(NSInteger diceValue);
    
  • Определите @property для блока (.h)

    @property (copy, nonatomic) CompleteDiceRolling completeDiceRolling;
    
  • Определите метод с finishBlock (.h)

    - (void)getDiceValueAfterSpin:(void (^)(NSInteger diceValue))finishBlock;
    
  • Вставить предыдущий определенный метод в файл .m и зафиксировать finishBlock до @property, определенный перед

    - (void)getDiceValueAfterSpin:(void (^)(NSInteger diceValue))finishBlock{
        self.completeDiceRolling = finishBlock;
    }
    
  • Чтобы запустить completionBlock передать предопределенный переменный тип ему (Не забудьте проверить, существует ли completionBlock)

    if( self.completeDiceRolling ){
        self.completeDiceRolling(self.dieValue);
    }
    

Ответ 6

typedef void (^OkBtnBlock)(id data);
typedef void (^CancelBtnBlock)();

@property (nonatomic, strong) OkBtnBlock okBtnBlock;
@property (nonatomic, strong) CancelBtnBlock cancelBtnBlock;

+ (void)foo:(OkBtnBlock)okBtn andCancel:(CancelBtnBlock)btnCancel;

Ответ 7

Если вам нужно вернуться в Xcode 4.2, вы также можете @synthesize блок, объявленный как свойство, как и с неблокируемым свойством. Не позволяйте синтаксису блока бросать вас.

Если ваше свойство блока:

@property (copy) return_type (^blockName) (var_type);

Тогда ваш @synthesize:

@property blockName;

Приветствия.