标签:
参考书籍:《精通Objective-C》【美】 Keith Lee
块是一个实现的闭包,一个允许访问其常规范围之外变量的函数。此外,一个Objective-C块实际上就是一个对象,它是NSObject类的子类,拥有NSObject类的相关属性。
块的声明:
int (^oneParamBlock)(int); // 声明一个名为oneParamBlock的块,该块接收一个int型参数,返回值也是int型的
void (^twoParamBlock)(int,int); // 接收两个int型参数,无返回值
void (^twoParamBlock2)(int parm1, int parm2); // 声明中可以含有参数名称
int (^noParamBlock)(void); // 没有参数需要写上void,不能省略
块的定义和调用:
// 将块常量赋值给之前声明的块(参数与返回值类型均需一致)
oneParamBlock = ^(int addend){
return addend + 1;
};
// 将块的声明和定义组合到一起(如果块常量没有参数,可以省略)
void (^noParamBlock2)(void) = ^{
NSLog(@"Hello,World!");
};
// 块的调用
int value = oneParamBlock(5);
NSLog(@"%d",value);
// 定义并调用块表达式
^(NSString *user){
NSLog(@"Greetings,%@!",user);
}(@"Earthing");
将块常量表达式用作调用方法的参数:
// 创建一个名为AdderBlock的块类型用作方法中的参数类型
typedef int (^AdderBlock)(int);
@interface Calculator : NSObject
-(int)process:(int)count withBlock:(AdderBlock)adder;
@end
@implementation Calculator
-(int)process:(int)count withBlock:(AdderBlock)adder{
return adder(count);
}
@end
Calculator *clac = [Calculator new];
int result = [clac process:2 withBlock:^int(int addend) {
return addend + 1;
}];
NSLog(@"%d",result);
局部变量的声明需要放在使用该局部变量的块之前。默认情况下,块常量表达式中不能对局部变量进行修改,使用__block
修改符可以将这些变量切换为读写模式,但__block
修改符不能与auto、register和static组合使用。
int myVar = 10;
void (^logValueBlock)(void) = ^{
NSLog(@"Variable value = %d", myVar);
};
logValueBlock();
__block int myVar2 = 10;
void(^intBlock)(int) = ^(int amount){
myVar2 += amount;
NSLog(@"New value = %d", myVar2);
};
intBlock(5);
在运行程序时,块常量表达式会获得栈内存,因而会拥有与局部变量相同的生命周期。因此它们必须被复制到永久存储区域(即堆)中,才能定义它们的范围之外使用。例如,如果你想要从方法获得类型为块常量的返回值或者存储块常量,就必须将块复制到堆中并在不再使用它们时释放这些块。
在MRR内存管理方式中,块的copy和release需要达到平衡
void (^greetingBlock)(void);
{
greetingBlock = [^{
NSLog(@"Hello,World!");
} copy];
}
greetingBlock();
[greetingBlock release]; // 释放块,防止内存泄漏
而在ARC内存管理方式中,编译器会自动执行块的复制和释放操作
下面是两个使用块的例子:
#import <Foundation/Foundation.h>
#include <stdlib.h>
#define ArrayElements 10
int main(int argc, const char * argv[]) {
@autoreleasepool {
// 创建一个含有随机数值(0~99)的数组
NSMutableArray *numbers = [NSMutableArray arrayWithCapacity: ArrayElements];
for (int elem = 0; elem < ArrayElements; elem++) {
unsigned int value = arc4random() % 100;
[numbers addObject:[NSNumber numberWithUnsignedInt:value]];
}
NSLog(@"Values:%@",numbers); // 记录未排序的数值
// 以升序方式为数组数值排序
[numbers sortUsingComparator:^(id obj1, id obj2){
if ([obj1 integerValue] > [obj2 integerValue]) {
return (NSComparisonResult)NSOrderedDescending;
}
if ([obj1 integerValue] < [obj2 integerValue]) {
return (NSComparisonResult)NSOrderedAscending;
}
return (NSComparisonResult)NSOrderedSame;
}];
NSLog(@"Values:%@",numbers); //记录未排序的数值
}
return 0;
}
#import <Foundation/Foundation.h>
#define YahooURL @"http://www.yahoo.com/index.html"
#define ApressURL @"http://www.apress.com/index.html"
typedef void (^DownloadURL)(void);
// 获取用于下载URL的块
DownloadURL getDownloadURL(NSString *url){
NSString *urlString = url;
return ^{
// 下载URL
NSDate *startTime = [NSDate date];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:urlString]];
NSError *error;
// 注意,NSURLConnection在iOS9中已被废除,推荐使用NSURLSession,后面有NSURLSession的使用方法
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&error];
if (data == nil) {
NSLog(@"Error loading request %@",[error localizedDescription]);
}
else{
NSDate *endTime = [NSDate date];
NSTimeInterval timeInterval = [endTime timeIntervalSinceDate:startTime];
NSLog(@"Time taken to download %@ = %f seconds", urlString, timeInterval);
}
};
}
int main(int argc, const char * argv[]) {
@autoreleasepool {
// 创建任务请求
dispatch_queue_t queue1 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_queue_t queue2 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// 创建任务分组
dispatch_group_t group = dispatch_group_create();
// 获取度量的当前时间
NSDate *startTime = [NSDate date];
// 创建并分派异步任务
dispatch_group_async(group, queue1, getDownloadURL(YahooURL));
dispatch_group_async(group, queue2, getDownloadURL(ApressURL));
// 等待,直到分组中的所有任务完成为止
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
// 为并行操作和日志检索时间信息
NSDate *endTime = [NSDate date];
NSTimeInterval timeInterval = [endTime timeIntervalSinceDate:startTime];
NSLog(@"Time taken to download URLs concurrently = %f seconds", timeInterval);
}
return 0;
}
使用NSURLSession:
// NSURLSession在命令行程序中可能无法正常使用,可以在iOS环境下调试
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSLog(@"123");
if (data == nil) {
NSLog(@"Error loading request %@",[error localizedDescription]);
}
else{
NSDate *endTime = [NSDate date];
NSTimeInterval timeInterval = [endTime timeIntervalSinceDate:startTime];
NSLog(@"Time taken to download %@ = %f seconds", urlString, timeInterval);
}
}];
[dataTask resume];
运行结果:
2016-07-14 16:03:50.780 BlockConcurrentTasks[20262:170183] Time taken to download http://www.apress.com/index.html = 1.259164 seconds
2016-07-14 16:03:54.485 BlockConcurrentTasks[20262:170182] Time taken to download http://www.yahoo.com/index.html = 4.965020 seconds
2016-07-14 16:03:54.486 BlockConcurrentTasks[20262:170152] Time taken to download URLs concurrently = 4.965577 seconds
可以看出并行方式执行任务的时间比以异步方式所消耗的时间更少。
标签:
原文地址:http://blog.csdn.net/sps900608/article/details/51911625