程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C >> 關於C >> OC之Block的使用

OC之Block的使用

編輯:關於C

一.Block定義

1.1定義

(1)Block是OC中的一種數據類型,在iOS開發中被廣泛使用

(2)^是Block的特有標記

(3)Block的實現代碼包含在{}之間

(4)大多情況下,以內聯inline函數的方式被定義和使用

(5)Block與C語言的函數指針有些相似,但使用起來更加靈活

1.2示例代碼

void(^demoBlock)() =^ {
   NSLog(@"demo");
};
int(^addBlock)(int, int) =^(int x, int y) {
   return x +y;
};

說明: (1)(返回類型)(^塊名稱)(參數類型)=^(參數列表){代碼實現}; (2)如果沒有參數,等號後面參數列表的()可以省略


.Block使用

2.1 Block被當做參數直接傳遞

NSArray *array= @[@"張三",@"李四",@"王五",@"趙六"];
[array enumerateObjectsUsingBlock:^(id obj, NSUIntegeridx, BOOL*stop) {
   NSLog(@"第 %d 項內容是 %@",(int)idx, obj);
   if ([@"王五"isEqualToString:obj]) {
        *stop = YES;
   }
}];


說明: 遍歷並NSLog()array中的內容,當obj 為"王五"時停止遍歷
2.2 對象傳遞進Block的方式

NSString *stopName =@"王五";
NSArray *array= @[@"張三",@"李四",@"王五",@"趙六"];
[array enumerateObjectsUsingBlock:^(idobj, NSUInteger idx,BOOL *stop) {
   NSLog(@"第 %d 項內容是 %@",(int)idx, obj);
   if ([stopName isEqualToString:obj] || idx == stopIndex) {
        *stop = YES;
   }
}];


說明: 為保證Block中的代碼正常運行,在將stopName的指針傳遞給Block時,Block會自動對stopName的指針做強引用

2.3 Block使用局部變量 在被當做參數傳遞時,Block同樣可以使用在定義之前聲明的局部變量

intstopIndex = 1;
NSArray *array = @[@"張三", @"李四", @"王五", @"趙六"];
[arrayenumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
    NSLog(@"第 %d 項內容是 %@", (int)idx, obj);
    if ([@"王五" isEqualToString:obj] || idx == stopIndex) {
        *stop = YES;
    }
}];

注意: 默認情況下,Block外部的變量,在Block中是只讀的!

BOOL flag = NO;
[arrayenumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
    if([@"王五" isEqualToString:obj] || idx == stopIndex) {
        *stop = YES;
        flag = YES;      // 編譯錯誤!!!
        }
}];

如果要修改Block之外的局部變量,需要使用__block關鍵字!

__block BOOL flag = NO;
[arrayenumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
    if([@"王五" isEqualToString:obj] || idx == stopIndex) {
        *stop = YES;
        flag = YES;      // 現在可以修改了!!!
        }
}];


無需使用__block關鍵字,在塊代碼中可以修改成員變量的數值(比較少用)

2.4 使用typedef定義Block 使用typedef定義一個Block的類型,便於在後續直接使用

typedef double(^MyBlock)(double, double);
MyBlock area = ^(double x, double y) {
    return x * y;
};
MyBlock sum = ^(double a, double b) {
    return a + b;
};
NSLog(@"%.2f", area(10.0, 20.0));
NSLog(@"%.2f", sum(10.0, 20.0));


說明: (1)typedef是關鍵字用於定義類型,MyBlock是定義的Block類型 (2)area、sum分別是MyBlock類型的兩個Block變量 (3)盡管,typedef可以簡化Block的定義,但在實際開發中並不會頻繁使用typedef關鍵字這是因為Block具有非常強的靈活性,尤其在以參數傳遞時,使用Block的目的就是為了立即使用

2.5 添加到數組 Block是一種數據類型,可以將Block當做比較特殊的對象

#pragma mark 定義並添加到數組
@property (nonatomic, strong) NSMutableArray *myBlocks;
int(^sum)(int, int) =^(int x, int y) {
   return [self sum:x y:y];
};
[self.myBlocks addObject:sum];
int(^area)(int, int) =^(int x, int y) {
   return [self area:x y:y];
};
[self.myBlocks addObject:area];
#pragma mark 調用保存在數組中的Block
int(^func)(int, int) = self.myBlocks[index];
return func(x,y);



2.6 Block循環引用問題
直接上代碼:

@property(nonatomic, strong) NSMutableArray *myBlocks;
#pragma mark 將代碼改為調用self的方法
int(^sum)(int, int) = ^(int x, int y) {
    return [self sum:x y:y];
};
[self.myBlocks addObject:sum];
#pragma mark 對象被釋放時自動調用
- (void)dealloc
{
   NSLog(@"DemoObj被釋放");
}
說明:

上面的代碼出現的問題,循環引用的結果就是對象無法被釋放!

(1)self對myBlocks的強引用

(2)sum對self的強引用

(3)對象被添加到數組中,會被數組強引用

\


<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHA+zsrM4r3ivvY6PC9wPgo8cD6+1rK/seTBv8SsyM+2vMrHx7/S/dPDtcSjrMDrv6rG5Mv51Nq1xNf308PT8tauuvO+zbvhsbvKzbfFLMq508NfX3dlYWu52Lz819ajrL/J0tS9q77Wsr+x5MG/yfnD986qyPXS/dPDPC9wPgo8cD48cHJlIGNsYXNzPQ=="brush:java;"> __weak DemoObj *weakSelf =self;

在Block中引用weakSelf,則Block不會再對self做強引用

int(^sum)(int, int) = ^(int x, int y) {
    	return [weakSelf sum:x y:y];
	};


2.7 Block在iOS中使用場景

(1)遍歷數組或者字典
(2)視圖動畫
(3)排序
(4)通知
(5)錯誤處理

(6)多線程等等...



























  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved