iOS,Android,Java教育訓練,期待與您的交流
塊(block)是OC對ANSI C所做的擴充,使用塊可以更好地簡化OC程式設計,而且OC的很多API都依賴于塊。
1 塊的使用方法
塊的文法格式如下:
^ [塊傳回值類型] (形參1,形參2,...)
{
}
塊必須以^開頭,傳回值類型通常都被省略,如果沒有形參,建議使用void作為占位符。
如果程式需要多次調用已經定義的塊,那麼應該將塊指派給一個塊變量,定義塊變量的文法格式如下:
塊傳回值類型 (^塊變量名) (形參類型1,形參類型2,...);
定義塊變量時,不需要聲明形參名,隻需要指定形參類型。類似的,如果塊變量不需要形參,建議使用void作為占位符。
//main.c
int main()
{
// 如果block沒有形參,可以省略後面的(),塊變量後面的()不能省略
void (^myblock)() = ^{
NSLog(@"----------------");
NSLog(@"----------------");
};
// 利用block變量調用block内部的代碼
myblock();
// 有傳回值、有形參的block
int (^sumblock)(int, int) = ^(int a, int b){
return a + b;
};
int c = sumblock(1,2);
return 0;
}
2 塊與局部變量
塊可以通路局部變量的值,當塊通路局部變量的值時,不允許修改局部變量的值。給局部變量加上__block關鍵字,這個局部變量就可以在block内部修改。
//main.c
int main()
{
int a = 10;
__block int b = 20;
void (^block)();
block = ^{
// block内部可以通路外面的變量
NSLog(@"a = %d", a);
// 預設情況下,block内部不能修改外面的局部變量
// a = 20;
// 給局部變量加上__block關鍵字,這個局部變量就可以在block内部修改
b = 25;
NSLog(@"b = %d", b);
};
block();
return 0;
}
3 協定
協定用于定義多個類應該遵守的規範,協定不提供任何實作。協定展現的是規範和實作分離的設計哲學。協定用來用來聲明一大堆方法,不能聲明成員變量。 隻要某個類遵守了這個協定,就相當于擁有這個協定中的所有方法聲明。隻要某個類遵守了這個協定,就相當于擁有這個協定中的所有方法聲明。
1、協定的格式;
@protocol 協定名稱 <其他協定名稱1, 其他協定名稱2>
// 方法聲明清單....
@end
2、協定中方法聲明的關鍵字
1> @required (預設)要求實作,如果沒有實作,會發出警告
2> @optional 不要求實作,
3、類遵守協定的格式:
@interface 類名 : 父類名 <協定名稱1, 協定名稱2>
@end
//Protocol1.h,繼承NSObject協定,建議每個協定都遵守該協定
@protocol Protocol1 <NSObject>
// @required 要求實作,不實作就會發出警告,預設是
// @optional 不要求實作
- (void)eat;
@optional
- (void)test3;
@end
//Protocol2.h
@protocol Protocol2 <NSObject>
- (void)cry;
@end
//Person.h,隻要一個類遵守了某一份協定,就能擁有這份協定中的所有方法聲明
// : 繼承父類
// <> 遵守協定
@interface Person : NSObject <Protocol1,Protocol2>
@end
//Person.m
@implementation Person
- (void)eat
{
NSLog(@"Person eat");
}
- (void)cry
{
NSLog(@"Person cry");
}
@end
如果需要使用協定來定義變量,有兩種方法:
NSObject<協定1,協定2...> *obj;
id<協定1,協定2...> *obj;
@property中聲明的屬性也可用做一個遵守協定的限制:
@property (nonatomic, strong) 類名<協定1,協定2...> *屬性名;
@property (nonatomic, strong) id<協定1,協定2...> 屬性名;
4 代理設計模式
1、代理的設計原理:某個類不想親自實作某些方法,就定義成員變量或者屬性,該成員變量實作了這些方法,就可以通過成員變量去調用方法。這個成員變量指向的對象就叫做代理對象。
2、設計原則:
(1) 得擁有某個代理對象屬性
(2)清楚代理有哪些方法
(3)要保證能解耦
3、實作方案:
(1) 定義一個protocol,在其中聲明一些和代理溝通的方法
(2) 擁有一個代理屬性id delegate
(3) 讓代理遵守protocol
//TicketDelegate.h 聲明一些跑腿方法
@protocol TicketDelegate <NSObject>
// 傳回票價
- (double) ticketPrice;
// 還剩多少張票
- (int) leftTicketsNumber;
@end
//Agent.h,代理對象
@interface Agent : NSObject <TicketDelegate>
@end
@implementation Agent
//Agent.m
// 剩餘的票數
- (int)leftTicketsNumber
{
// ... 親自跑電影院\或者打電話
return 1;
}
// 每一張票多少錢
- (double)ticketPrice
{
// ... 親自跑電影院\或者打電話
return 1000;
}
@end
//NextAgent.h,代理對象
@interface Agent : NSObject <TicketDelegate>
@end
@implementation Agent
//NextAgent.m
// 剩餘的票數
- (int)leftTicketsNumber
{
return 500;
}
// 每一張票多少錢
- (double)ticketPrice
{
return 10;
}
@end
//Person.h
@interface Person : NSObject
- (void) buyTicket;
// 擁有一個代理屬性
// id代表代理的類名随便
// 但必須遵守TicketDelegate協定
@property (nonatomic, retain) id<TicketDelegate> delegate;
@end
//Person.m
@implementation Person
// 買電影票
- (void)buyTicket
{
// 叫代理去幫自己買票(詢問一下票價、詢問一下票的剩餘張數)
double price = [_delegate ticketPrice];
int number = [_delegate leftTicketsNumber];
NSLog(@"通過代理的幫忙,票價=%f,還剩%d張票", price, number);
}
- (void)dealloc
{
[_delegate release];
[super dealloc];
}
@end
int main(int argc, const char * argv[])
{
// 人
Person *p = [[Person alloc] init];
// 代理
Agent *a = [[Agent alloc] init]; //第一個代理
NextAgent *na = [[NextAgent alloc] init]; //第二個代理
// 設定人的代理
p.delegate = a;
// 人打算看電影
[p buyTicket];
// 設定人的代理
p.delegate = na;
// 人打算看電影
[p buyTicket];
[a release];
[na release];
[p release];
return 0;
}
iOS,Android,Java教育訓練,期待與您的交流