iOS開(kāi)發(fā)高級(jí)語(yǔ)法之分類讯赏,拓展,協(xié)議冷尉,代碼塊詳解
一:分類
什么是分類Category漱挎?
分類就是類的補(bǔ)充和擴(kuò)展部分
補(bǔ)充和擴(kuò)展的每個(gè)部分就是分類
分類本質(zhì)上是類的一部分
分類的定義
分類也是以代碼的形式保存在文件中
分類文件命名主類類名+分類類名
分類文件也分為*.h文件和*.m文件
*.h文件存放分類的聲明部分內(nèi)容
@interface?主類類名(分類類名)
//添加方法聲明
@end
.m文件存放分類的實(shí)現(xiàn)部分內(nèi)容
@implementation 主類類名(分類類名)
//添加方法實(shí)現(xiàn)
@end
分類中是不可以創(chuàng)建實(shí)例變量的,自然也不可以創(chuàng)建自屬性雀哨。
在分類中是可以訪問(wèn)主類的屬性磕谅,但不可以訪問(wèn)主類的實(shí)例變量。
下面是簡(jiǎn)單的使用實(shí)例:
.h文件
#import "SomeClass.h"
@interface SomeClass (Hello)
-(void)hello;
@end
.m文件
#import "SomeClass+Hello.h"
@implementationSomeClass (Hello)
-(void)hello{
NSLog (@"name:%@ ", @"iCocos");
}
@end
其中Hello是Category的名稱雾棺,如果你用XCode創(chuàng)建Category膊夹,那么需要填寫(xiě)的內(nèi)容包括名稱和要擴(kuò)展的類的名稱。這里還有一個(gè)約定成俗的習(xí)慣捌浩,將聲明文件和實(shí)現(xiàn)文件名稱統(tǒng)一采用“原類名+Category”的方式命名放刨。
調(diào)用也非常簡(jiǎn)單,毫無(wú)壓力尸饺,如下:
首先引入Category的聲明文件进统,然后正常調(diào)用即可。
#import "SomeClass+Hello.h"
SomeClass * sc =[[SomeClass alloc] init];
[sc hello]
執(zhí)行結(jié)果是:
name:iCocos
Category的使用場(chǎng)景:
1浪听、當(dāng)你在定義類的時(shí)候螟碎,在某些情況下(例如需求變更),你可能想要為其中的某個(gè)或幾個(gè)類中添加方法迹栓。
2掉分、一個(gè)類中包含了許多不同的方法需要實(shí)現(xiàn),而這些方法需要不同團(tuán)隊(duì)的成員實(shí)現(xiàn)
3克伊、當(dāng)你在使用基礎(chǔ)類庫(kù)中的類時(shí)叉抡,你可能希望這些類實(shí)現(xiàn)一些你需要的方法。
遇到以上這些需求答毫,Category可以幫助你解決問(wèn)題。當(dāng)然季春,使用Category也有些問(wèn)題需要注意洗搂,
1、Category可以訪問(wèn)原始類的實(shí)例變量,但不能添加變量耘拇,如果想添加變量撵颊,可以考慮通過(guò)繼承創(chuàng)建子類。
2惫叛、Category可以重載原始類的方法倡勇,但不推薦這么做,這么做的后果是你再也不能訪問(wèn)原來(lái)的方法嘉涌。如果確實(shí)要重載妻熊,正確的選擇是創(chuàng)建子類。
3仑最、和普通接口有所區(qū)別的是扔役,在分類的實(shí)現(xiàn)文件中可以不必實(shí)現(xiàn)所有聲明的方法,只要你不去調(diào)用它警医。
用好Category可以充分利用Objective-C的動(dòng)態(tài)特性亿胸,編寫(xiě)出靈活簡(jiǎn)潔的代碼。
二; 拓展
二预皇、擴(kuò)展(延展)
1.概念
擴(kuò)展其實(shí)就是分類的一種特殊形式侈玄,擴(kuò)展是沒(méi)有名字的。
extension可以 理解成匿名的category吟温,同樣需要括號(hào)序仙。
2.使用方式
a.擴(kuò)展中可以聲明實(shí)例變量,所以可以聲明屬性
b.擴(kuò)展通常定義在文件的.m中溯街,不能分開(kāi)诱桂。
c.擴(kuò)展是用來(lái)聲明私有的屬性和方法
區(qū)別:
分類:是不可以聲明實(shí)例變量,通常是公開(kāi)的呈昔,文件名通常為:"主類類名+分類類名.h"
擴(kuò)展:是可以聲明實(shí)例變量挥等,是私有的,文件名通常為:"主類類名_擴(kuò)展標(biāo)識(shí).h"堤尾,注意擴(kuò)展沒(méi)有名的肝劲。
區(qū)別分類與擴(kuò)展
1.都可以在主類中聲明使用
2.通常來(lái)講由于分類不能創(chuàng)建實(shí)例變化,本質(zhì)上與主類有區(qū)別郭宝,所以不建議寫(xiě)在主類中辞槐。
3.擴(kuò)展與主類緊密聯(lián)系在一起,可以創(chuàng)建實(shí)例變量粘室,所以通常來(lái)講會(huì)把擴(kuò)展和主類創(chuàng)建在一起榄檬。
實(shí)例代碼:
.h文件
#import
@interface NSString (Extend)
-(NSString *)stringByTrim;
@end
.m文件
#import "NSString+Extend.h"
@implementation NSString (Extend)
-(NSString *)stringByTrim{
NSCharacterSet *character= [NSCharacterSet whitespaceCharacterSet];
return [self stringByTrimmingCharactersInSet:character];
}
@end
.main文件
#import
#import "NSString+Extend.h"
int main(int argc, const char * argv[]) {
NSString *name=@" Kenshin Cui ";
name=[name stringByTrim];
NSLog(@"I'm %@!",name); //結(jié)果:I'm Kenshin Cui!
return 0;
}
三:協(xié)議
1.概念
協(xié)議就是規(guī)則,定義一個(gè)協(xié)議就相當(dāng)于制定規(guī)則衔统。
OC中類可以遵守協(xié)議鹿榜,遵守了一個(gè)協(xié)議的類相當(dāng)于擁有了一種能力海雪。
2.語(yǔ)法
@protocal協(xié)議名
@required聲明必須遵守的屬性和方法
@optional聲明可選(可以)遵守的屬性和方法
默認(rèn)?@required
@end
3.一個(gè)類遵守一個(gè)協(xié)議
a.@interface類名(分類類名):父類名<協(xié)議名>
b.實(shí)現(xiàn)協(xié)議中聲明的方法
4.使用協(xié)議類型的引用指向?qū)崿F(xiàn)了協(xié)議或者遵守了協(xié)議的對(duì)象
id p = [[MyClass]init];
[p …];可以向協(xié)議的引用發(fā)送消息,只能發(fā)送協(xié)議要求的消息舱殿。
5.協(xié)議的繼承
協(xié)議的繼承相當(dāng)于協(xié)議的合并奥裸。
@protocol TRTarena2
-(void)learn;
@end
6.一個(gè)類可以同時(shí)遵守多個(gè)協(xié)議,協(xié)議之間使用","分隔符分開(kāi)沪袭。
@interface TRStudent :?NSObject
7.協(xié)議的使用和多態(tài)相類似湾宙,可以用于數(shù)組、參數(shù)冈绊、返回值類型侠鳄,只不過(guò)多態(tài)返回的對(duì)象,一定要有繼承關(guān)系焚碌,協(xié)議類型返回的對(duì)象畦攘,一定要有遵守協(xié)議或?qū)崿F(xiàn)協(xié)議。
實(shí)例代碼:
.h文件
@protocol ProcessDataDelegate?
//必須實(shí)現(xiàn)的方法
@required
- (void) processSuccessful: (BOOL)success;
//選擇實(shí)現(xiàn)的方法
@optional
- (id) submitOrder: (NSNumber *) orderid;
@end
在h文件中引入包含Protocol的h文件十电,之后聲明采用這個(gè)Protocol即可知押,如下:
@interface TestAppDelegate : NSObject;
@end
.m文件
@implementation TestAppDelegate
- (void) processSuccessful: (BOOL)success{
if (success) {
NSLog(@"成功");
}else {
NSLog(@"失敗");
}
}
@end
四:代碼塊
在C#異步編程時(shí)我們經(jīng)常進(jìn)行函數(shù)回調(diào),由于函數(shù)調(diào)用是異步執(zhí)行的鹃骂,我們?nèi)绻胱屢粋€(gè)操作執(zhí)行完之后執(zhí)行另一個(gè)函數(shù)台盯,則無(wú)法按照正常代碼書(shū)寫(xiě)順序進(jìn)行編程,因?yàn)槲覀儫o(wú)法獲知前一個(gè)方法什么時(shí)候執(zhí)行結(jié)束畏线,此時(shí)我們經(jīng)常會(huì)用到匿名委托或者lambda表達(dá)式將一個(gè)操作作為一個(gè)參數(shù)進(jìn)行傳遞静盅。其實(shí)在ObjC中也有類似的方法,稱之為代碼塊(Block)寝殴。Block就是一個(gè)函數(shù)體(匿名函數(shù))蒿叠,它是ObjC對(duì)于閉包的實(shí)現(xiàn),在塊狀中我們可以持有或引用局部變量(不禁想到了lambda表達(dá)式)蚣常,同時(shí)利用Block你可以將一個(gè)操作作為一個(gè)參數(shù)進(jìn)行傳遞(是不是想起了C語(yǔ)言中的函數(shù)指針)
上面代碼中使用Block同樣實(shí)現(xiàn)了按鈕的點(diǎn)擊事件市咽,關(guān)于Block總結(jié)如下:
Block類型定義:返回值類型(^ 變量名)(參數(shù)列表)(注意Block也是一種類型);
Block的typedef定義:返回值類型(^類型名稱)(參數(shù)列表)抵蚊;
Block的實(shí)現(xiàn):^(參數(shù)列表){操作主體}施绎;
Block中可以讀取塊外面定義的變量但是不能修改,如果要修改那么這個(gè)變量必須聲明_block修飾贞绳;
實(shí)例代碼:
void?(^printBlock)(NSString?*x);
printBlock?=?^(NSString*?str)
{
NSLog(@"print:%@",?str);
};
printBlock(@"hello?world!");