objective c block
TRANSCRIPT
BlockKhoa Pham - 2359Media
BlockDefinitionSyntaxCaptureUsage
Definition
BlockThe closure that Apple adds to CIs an object (NSBlock)The compiler translate block literals into struct and functions. So we don’t see the alloc call
BlockIt is said to be the only object that can be allocated on the stack, by default.
It is moved to heap when copied.
Blockstruct + captured state information
Syntax
SyntaxThe syntax of Objective C block http://arigrant.com/blog/2014/1/18/the-syntax-of-objective-c-blocks
From C declarators to Objective C block syntaxhttp://nilsou.com/blog/2013/08/21/objective-c-blocks-syntax/
Cheatsheethttp://fuckingblocksyntax.com/
Syntax*[]()^
Syntax() > [] > *, ^Start from the variable name to rightThen to the leftOperator precedence http://unixwiz.net/techtips/reading-cdecl.html
CDECL http://cdecl.org/
Syntaxint a;
Syntaxint a;
a is an int
Syntaxint *a;
Syntaxint *a;
a is a pointer to an int
Syntaxint a[];
Syntaxint a[];
a is an array of int
Syntaxint f();
Syntaxint f();
f is a function that returns an int
Syntaxint f(long);
f is a function that returns an int, and accepts a long
Syntaxint *a[];
Syntaxint *a[];
a is an array of pointers to int
Syntaxint *(a[]);
a is an array of pointers to int
Syntaxint (*)a[];
Syntaxint (*)a[];
a is a pointer to an array of ints
Syntaxint *f();
Syntaxint *f();
f is function that returns a pointer to an int
Syntaxint *(f());
f is function that returns a pointer to an int
Syntaxint (*f)();
Syntaxint (*f)();
f is a pointer to a function which accepts nothing and returns an int
Syntaxvoid (^successBlock)(NSDictionary *response);
successBlock is a block pointer to a function which takes a dictionary and returns nothing
Syntax^ is the block pointer, which can only be applied to function
int ^f(); // Error
^ unary operatorint (^doubleMe)(int) = ^(int a){
return a * 2;}
int b = doubleMe(2);
^ unary operatorTransform function implementation into a blockInfer the return type
^ unary operatorBOOL (^customBlock)(NSArray *) = ^(NSArray *array) {
// return array.count == 3; // Please don’t
if (array.count == 3) {
return YES;
}
return NO;
};
__blockWhat does the block keyword meanhttp://stackoverflow.com/questions/7080927/what-does-the-block-keyword-mean
__blockAccess to __block variablehttp://clang.llvm.org/docs/Block-ABI-Apple.html#layout-of-block-marked-variables
By default, variables used withtin the block are copied Rewrite access,
__block (Kiwi example)describe(@"it takes a while", ^{
__block NSDictionary *apiResponse = nil;
beforeAll(^{
__block BOOL requestCompleted = NO;
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request
success:̂ (NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
requestCompleted = YES;
apiResponse = JSON;
}
failure:̂ (NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
requestCompleted = YES;
}
];
[operation start];
[KWSpec waitWithTimeout:3.0 forCondition:̂ BOOL() {
return requestCompleted;
}];
});
it(@"includes the related objects in the response", ^{
[[[apiResponse objectForKey:@"children"] should] containObjects:@"foo", @"bar", @"baz", nil];
});
});
Capture
CaptureThe ability to capture values from the enclosing scope, making them similar to closures or lambdas in other programming languages.
weakSelf vs strongSelf__weak __typeof__(self) weakSelf = self;
self.block = ^{
__typeof__(self) strongSelf = weakSelf;
[strongSelf doSomething];
[strongSelf doSomethingElse];
};
The block property is declared as “copy”
weakSelf vs strongSelfUnderstand weakSelf and strongSelfhttp://www.fantageek.com/1090/understanding-weak-self-and-strong-self/
weakSelf vs strongSelfBlock is allocated on the stack. It has no effect on the storage of lifetime of anything it accesses.
When they are copied, they take their captured scope with them, retaining any objects they refer
weakSelf vs strongSelfBlock captures the variable along with its decorators (i.e. weak qualifier),
weakSelf vs strongSelfBlock captures the variable along with its decorators (i.e. weak qualifier),
weakSelf vs strongSelfYou should only use a weak reference to self, if self will hold on to a reference of the block.
Take care
UIView animation block[UIView animateWithDuration:0.5 delay:1.0 options: UIViewAnimationCurveEaseOut animations:^{ self.basketTop.frame = basketTopFrame; self.basketBottom.frame = basketBottomFrame; } completion:^(BOOL finished){ NSLog(@"Done!"); }];
UIView animation block- (void)loopThisBlock { [UIView animateWithDuration:0.2 animations:^{ someView.alpha = (someView.alpha + 1.0) % 2; } completion:^(BOOL finished) { [self loopThisBlock]; }]; }
What if the block is executed infinitely ?
AFNetworking callback blockAFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager
manager];
[manager GET:@"http://example.com/resources.json" parameters:nil success:^
(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(@"JSON: %@", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"Error: %@", error);
}];
Notification handler block[[NSNotificationCenter defaultCenter]
addObserverForNotificationName:@"NotificationName"
object:nil
queue:[NSOperationQueue mainQueue]
block:^(NSNotification *notification) {
//reload the table to show the new whiz bangs
NSAssert(notification, @"Notification must not be nil");
[self.tableView reloadData];
}];
Usage
DSLMasonryKiwiFTGValidator
DSLREQUIRE_STRING(@"90001").to.matchRegExWithPattern(@"^[0-9][0-9][0-9][0-9][0-
9]$").with.message(@"Value must be US zip code format"),
[view1 mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(superview).with.insets(padding);
}];
DSL- (FTGStringRule * (^)(NSString *anotherValue))equalTo { return ^(NSString *anotherValue){ [self setValidation:^BOOL(NSString *value) { return [value isEqualToString:anotherValue]; }]; return self; };}
Syntactic sugarhttps://github.com/supermarin/ObjectiveSugar
[@3 times:^{
NSLog(@"Hello!");
}];
[cars each:^(id object) {
NSLog(@"Car: %@", object);
}];
Syntactic sugarhttps://github.com/supermarin/ObjectiveSugar
[@3 times:^{
NSLog(@"Hello!");
}];
[cars each:^(id object) {
NSLog(@"Car: %@", object);
}];
Conditionhttp://blog.vikingosegundo.de/2012/10/05/pattern-switch-value-object/
NSArray *filter = @[caseYES, caseNO];id obj1 = @"YES";id obj2 = @"NO";[obj1 processByPerformingFilterBlocks:filter];[obj2 processByPerformingFilterBlocks:filter];
Mapping with blockhttp://www.merowing.info/2014/03/refactoring-tricks/#.VNw2IlOUc8Y
NSString *(^const format)(NSUInteger, NSString *, NSString *) = ^(NSUInteger value, NSString
*singular, NSString *plural) {
return [NSString stringWithFormat:@"%d %@", value, (value == 1 ? singular : plural)];
};
Reference1. http://www.galloway.me.uk/2012/10/a-look-inside-blocks-episode-1/2. https://blackpixel.com/writing/2014/03/capturing-myself.html3. http://albertodebortoli.github.io/blog/2013/04/21/objective-c-blocks-
under-the-hood/4. http://stackoverflow.com/questions/20134616/how-are-nsblock-objects-
created5. http://nilsou.com/blog/2013/08/21/objective-c-blocks-syntax/6. http://clang.llvm.org/docs/Block-ABI-Apple.html#blocks-as-objects7. http://albertodebortoli.github.io/blog/2013/08/03/objective-c-blocks-
caveat/
Thanks