閱讀547 返回首頁    go iPhone_iPad_Mac_apple


obj-c編程09:塊的語法

    在obj-c中,有一種和C截然不同的東西——塊。塊可以在外邊定義,也可以在函數或方法內部定義,可以被賦值給一個變量,然後用該變量調用。默認情況下塊對外部變量的訪問隻能讀不能寫,除非用__block顯示聲明可寫。對於塊這麼個東東,讓我想到了ruby中的block,不過ruby中block是閉包,而且外部變量變化會影響block的值,但obj-c的塊不會,即obj-c塊的外部變量是編譯時求值而不是運行時求值哦:

#import <Foundation/Foundation.h>

int main(int argc,char *argv[])
{
	@autoreleasepool{
		int i = 10;

		//foo是一個塊變量被賦值為一個塊。
		int (^foo)(int) = ^(int x) {
			int ret = x * i;
			//i = 100;	編譯錯誤,不能改寫外部變量的值
			NSLog(@"%d * i(%d) = %d",x,i,ret);
			return ret;
		};

		i = 1000;
		foo(11);	//i此時為10而不是1000哦。
	}
	return 0;
}

可以看到在塊內是不能寫外部i變量的,除非用__block修飾:

#import <Foundation/Foundation.h>

int main(int argc,char *argv[])
{
	@autoreleasepool{
		__block int i = 10;

		//foo是一個塊變量被賦值為一個塊。
		int (^foo)(int) = ^(int x) {
			i = 100;
			int ret = x * i;
			NSLog(@"%d * i(%d) = %d",x,i,ret);
			return ret;
		};

		i = 1000;
		NSLog(@"ret is %d",foo(11));	//i此時為100哦。
	}
	return 0;
}

如果是在ruby中則外部變量變化會導致block的結果發生變化,也給個例子吧:

apple@kissAir: objc_src$irb
2.1.1 :001 > $v = 100
 => 100 
2.1.1 :002 > b = ->(x){puts "#$v * #{x} = #{$v * x}"} 
 => #<Proc:0x0000010182c0d8@(irb):2 (lambda)> 
2.1.1 :003 > b[11]
100 * 11 = 1100
 => nil 
2.1.1 :004 > $v=11
 => 11 
2.1.1 :005 > b[11]
11 * 11 = 121
 => nil 

[2014.07.06第一次新增內容]:塊功能擴展

我們還可以用block來實現集合對象的map功能,比如ruby中數組或散列的map:

#import <Foundation/Foundation.h>

#define msg(...) NSLog(__VA_ARGS__)

NSArray *map(NSArray *ary,id (^block)(id))
{
	NSMutableArray *ary_ret = [NSMutableArray array];
	for(id x in ary)
		[ary_ret addObject:block(x)];
	return ary_ret;
}

int main(int argc,char *argv[])
{
	@autoreleasepool{
		NSArray *ary_init = [NSArray arrayWithObjects:@"big",@"small",\
			@"love",@"pluck",@"save",nil];
		NSArray *ary = map(ary_init,^(id item){\
			return [item capitalizedString];});
		msg(@"%@",ary);
	}
	return 0;
}

運行結果如下:

apple@kissAir: objc_src$./blk

2014-07-06 14:47:57.758 blk[1009:507] (

    Big,

    Small,

    Love,

    Pluck,

    Save

)


塊能做的事可不止這些哦,我們可以借助GCD中對塊的支持並發的執行任務:

#import <Foundation/Foundation.h>

#define msg(...) NSLog(__VA_ARGS__)

int main(int argc,char *argv[])
{
	@autoreleasepool{
		NSMutableArray *ary_m = [NSMutableArray array];

		//獲取GCD全局隊列
		dispatch_queue_t g_queue = dispatch_get_global_queue(0,0);
		//創建新的執行組
		dispatch_group_t grp = dispatch_group_create();

		srand(time(NULL));
		__block int s = 0;

		for(int i = 0;i < 1000;++i){
			dispatch_block_t block = ^{
				s = rand() % 5;
				sleep(s);
				msg(@"at %4d:sleeped %d s",i,s);
			};

			//在組中異步執行塊
			dispatch_group_async(grp,g_queue,block);
		}
		//等待組中所有塊任務執行完畢
		dispatch_group_wait(grp,DISPATCH_TIME_FOREVER);
	}
	return 0;
}

運行如下:

apple@kissAir: objc_src$./blk

2014-07-06 15:25:07.318 blk[1231:3903] at   19:sleeped 0 s

2014-07-06 15:25:07.318 blk[1231:3303] at   17:sleeped 0 s

2014-07-06 15:25:07.319 blk[1231:4703] at   21:sleeped 0 s

2014-07-06 15:25:07.319 blk[1231:4c03] at   22:sleeped 0 s

2014-07-06 15:25:07.319 blk[1231:4003] at   20:sleeped 0 s

2014-07-06 15:25:07.322 blk[1231:3e03] at   31:sleeped 0 s

2014-07-06 15:25:07.323 blk[1231:5e03] at   36:sleeped 0 s

2014-07-06 15:25:07.324 blk[1231:6403] at   40:sleeped 0 s

2014-07-06 15:25:07.325 blk[1231:6803] at   43:sleeped 0 s

2014-07-06 15:25:07.327 blk[1231:7a03] at   53:sleeped 0 s

2014-07-06 15:25:07.328 blk[1231:7a03] at   56:sleeped 0 s

2014-07-06 15:25:07.328 blk[1231:7a03] at   58:sleeped 2 s

2014-07-06 15:25:07.330 blk[1231:8a03] at   64:sleeped 0 s

2014-07-06 15:25:07.333 blk[1231:9e03] at   75:sleeped 0 s

2014-07-06 15:25:07.333 blk[1231:9e03] at   77:sleeped 0 s

2014-07-06 15:25:07.333 blk[1231:9e03] at   78:sleeped 0 s

2014-07-06 15:25:08.315 blk[1231:1903] at    4:sleeped 2 s

2014-07-06 15:25:08.315 blk[1231:1103] at    1:sleeped 2 s

2014-07-06 15:25:08.315 blk[1231:1503] at    3:sleeped 2 s

2014-07-06 15:25:08.315 blk[1231:1f03] at    7:sleeped 2 s

2014-07-06 15:25:08.315 blk[1231:2303] at    9:sleeped 2 s

2014-07-06 15:25:08.317 blk[1231:2f03] at   15:sleeped 2 s

2014-07-06 15:25:08.319 blk[1231:2303] at   84:sleeped 0 s

2014-07-06 15:25:08.323 blk[1231:4c03] at   28:sleeped 2 s

2014-07-06 15:25:08.323 blk[1231:5203] at   30:sleeped 2 s

2014-07-06 15:25:08.323 blk[1231:5803] at   32:sleeped 2 s

2014-07-06 15:25:08.323 blk[1231:5c03] at   35:sleeped 2 s

2014-07-06 15:25:08.324 blk[1231:5e03] at   38:sleeped 2 s

2014-07-06 15:25:08.324 blk[1231:6603] at   41:sleeped 2 s

2014-07-06 15:25:08.325 blk[1231:5203] at   88:sleeped 0 s

2014-07-06 15:25:08.325 blk[1231:6a03] at   44:sleeped 0 s

2014-07-06 15:25:08.325 blk[1231:5c03] at   90:sleeped 0 s

2014-07-06 15:25:08.325 blk[1231:6c03] at   46:sleeped 0 s

2014-07-06 15:25:08.326 blk[1231:7003] at   48:sleeped 1 s

2014-07-06 15:25:08.327 blk[1231:6a03] at   94:sleeped 0 s

2014-07-06 15:25:08.328 blk[1231:5c03] at   97:sleeped 0 s

2014-07-06 15:25:08.328 blk[1231:5c03] at   99:sleeped 0 s

2014-07-06 15:25:08.329 blk[1231:7a03] at   61:sleeped 3 s

2014-07-06 15:25:08.330 blk[1231:8c03] at   65:sleeped 3 s

2014-07-06 15:25:08.331 blk[1231:8c03] at  102:sleeped 0 s

2014-07-06 15:25:08.333 blk[1231:a003] at   76:sleeped 4 s

2014-07-06 15:25:08.333 blk[1231:9a03] at   73:sleeped 4 s

2014-07-06 15:25:08.334 blk[1231:9a03] at  105:sleeped 0 s


最後更新:2017-04-03 05:38:53

  上一篇:go [它山之石] 一件事情,如果你不能說清楚,十有八九你就做不好
  下一篇:go spring使用注解時配置文件的寫法