Список синтаксиса декларации блока
Блочный синтаксис в Objective C (и, как я полагаю, C), как известно, неуместен. Передача блоков в качестве аргументов выглядит иначе, чем объявление блоков как ivars, что выглядит иначе, чем typedef
блоки.
Существует ли полный список синтаксиса объявления блока, который я мог бы держать под рукой для быстрого ознакомления?
7 ответов
Список синтаксисов объявления блоков
Во всем, пусть
return_type
быть типом объекта / примитива / и т.д. вы хотели бы вернуться (обычноvoid
)blockName
быть именем переменной блока, который вы создаетеvar_type
быть типом объекта / примитива / и т.д. вы хотели бы передать в качестве аргумента (оставьте пустым, без параметров)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)
{
// ...
}
Дополнения
Если я что-то пропустил, пожалуйста, дайте мне знать в комментариях, и я исследую / добавлю их.
Ох, и в Свифте...
blockName = (varName: var_type) -> (return_type)
Это почти как языковая особенность.
Мне лично нравится использовать этот сайт ( http://fuckingblocksyntax.com/). Имя легче запомнить, чем сам синтаксис блока:
http://fuckingblocksyntax.com
и если вы не можете загрузить URL с плохими словами в них, вы можете использовать это зеркало: http://goshdarnblocksyntax.com/
Операторы typedef:
typedef void (^block)(NSString *arg);
В соответствии:
void (^block)(NSString *) = ^(NSString *param) {
// do something....
};
Метод:
- (void)method:(void (^)(NSString *param))handler
Библиотека фрагментов Xcode 4 содержит шаблоны для определения типов блоков и встроенных блоков в качестве переменных. Они также доступны через автозаполнение (typedefblock
а также inlineblock
).
Для блоков в качестве аргументов методов, я бы рекомендовал объявить typedef
а затем просто используя это. Это делает код намного проще для чтения.
Я написал блок завершения для класса, который будет возвращать значения кубиков после их встряхивания:
Определить 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
передать ему предопределенную переменную Type (не забудьте проверить,completionBlock
существует)if( self.completeDiceRolling ){ self.completeDiceRolling(self.dieValue); }
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;
Если вам нужно вернуться обратно в Xcode 4.2, вы также можете @synthesize блок, объявленный как свойство, точно так же, как и со свойством non block. Не позволяйте синтаксису блока бросить вас.
Если ваше свойство блока это:
@property (copy) return_type (^blockName) (var_type);
Тогда ваш @synthesize это:
@property blockName;
Приветствия.