1.copy(自定義對象)
2.類的本質(zhì)【理解】—》Class類對象
3.選擇器 SEL【重點】
一 copy
對某個對象發(fā)送copy消息的時候揭芍,我們的目的是希望能夠拷貝出一份一模一樣的對象
【Demo】-【1-copy的使用】
什么是深拷貝和淺拷貝?
深拷貝:真正的復(fù)制出一份原來的對象,產(chǎn)生了一個新的對象跷叉;
淺拷貝:只拷貝了對象的地址,并沒有產(chǎn)生新的對象吠勘;(retain就屬于淺拷貝)
copy和retain的區(qū)別:
1.retain和copy都會讓對象的引用計數(shù)+1性芬,所以都應(yīng)該對應(yīng)的必須有一個release或 autorelease;
2.retain是讓原對象引用計數(shù)器+1剧防,這里只拷貝了對象的地址植锉,并沒有產(chǎn)生新對象,認為是“淺 拷貝”峭拘;
3.copy拷貝出了一個新對象俊庇,讓新對象的引用計數(shù)器的值為1,認為是“深拷貝”狮暑;
copy的運行機制
//希望能拷貝出一個新對象,跟per1所指向的對象的值一樣辉饱;
//當(dāng)一個對象指向copy方法的時候搬男,系統(tǒng)內(nèi)部會自動的調(diào)用copyWithZone:這個方法,這是 一個協(xié)議方法彭沼,該方法返回的對象就是拷貝出來的新對象缔逛;
//以后凡是遇到copy一個自定義的對象,或者遇到屬性使用copy修飾的自定義對 象姓惑,那么先對該對象遵守一個NSCopying協(xié)議褐奴,并實現(xiàn)協(xié)議方法;
#pragma mark - NSCopying協(xié)議方法
-(id)copyWithZone:(NSZone *)zone{
Person *per = [[Person alloc] initWithAge:self.age andWithName:self.name];
//在這里屬于特殊情況于毙,返回對象的時候不需要加入autorelease
return per;
}
二 類的本質(zhì)
當(dāng)程序一運行起來敦冬,系統(tǒng)就會默認吧工程中所有的類都加載一份到內(nèi)存中(這塊內(nèi)存中保存的是 所有的方法列表),我們可以把這塊內(nèi)存認為是類在內(nèi)存中的對象唯沮,稱為“類對象”脖旱;
類對象都對應(yīng)一種類型,Class類型介蛉;
Class-》所有的類對象都是Class類型萌庆;
類的加載和初始化【了解】
+(void)load;
+(void)initialize;
見【Demo】-【2-類的加載和初始化】
@implementation Dog
//當(dāng)程序啟動的時候,就會加載一次項目中所有的類到內(nèi)存中币旧,加載完畢后就會調(diào)用load方法(只會調(diào)用一次)踊兜,先調(diào)用父類,再調(diào)用子類佳恬;
+(void)load{
NSLog(@"Dog ----load 加載到了內(nèi)存中");
}
//當(dāng)?shù)谝淮问褂眠@個類(類對象)的時候捏境,就會調(diào)用initialize這個方法,且只調(diào)用一次毁葱,先調(diào)用父類垫言,再調(diào)用子類;
+(void)initialize{
NSLog(@"Dog --- initialize 進行初始化倾剿!");
}
@end
類對象:一個類在程序中只有一個類對象筷频;
類的對象:程序中可以有無數(shù)個類的對象;
如何獲得Class類型的類對象前痘;
1)直接向類的對象發(fā)送一個class消息凛捏,[per1 class];
2)直接向我們的類名發(fā)送class消息,[Person class];
見【Demo】-【3-類對象的使用場合】
//類對象的使用場合【**掌握下面的幾個方法**】
//1.判斷一個類是否是另一個類的子類
BOOL bl1 = [Person isSubclassOfClass:[NSObject class]];
if (bl1) {
NSLog(@"是的");
}else{
NSLog(@"不是的");
}
//2.判斷一個指針?biāo)赶虻膶ο笫欠袷悄撤N類型
id obj = [[Person alloc] init];
BOOL bl2 = [obj isMemberOfClass:[Person class]];
if (bl2) {
NSLog(@"是的");
}else{
NSLog(@"不是的");
}
//3.判斷一個指針?biāo)赶虻膶ο笫欠袷悄撤N類型或者它的子類【**常用**】
id str = @"1111222";
BOOL bl3 = [str isKindOfClass:[NSString class]];
if (bl3) {
NSLog(@"是的");
}else{
NSLog(@"不是的");
}
三 選擇器【重點】
3.1認識選擇器
1)選擇器是一種數(shù)據(jù)類型芹缔,這個類型寫作SEL
2)SEL聲明的變量是用來裝“成員方法”的坯癣,更確切的說,裝“消息”最欠,有點類似于“函數(shù) 指針”示罗;
【作用】
我們可以通過選擇器SEL數(shù)據(jù)類型實現(xiàn)動態(tài)的調(diào)用對象的成員方法惩猫。
【Demo】-【4-認識選擇器】
數(shù)組的排序
見【Demo】-【5-數(shù)組的排序】
// char buf[100];
// printf("請輸入您想調(diào)用的方法名:\n");
// scanf("%s",buf);
//
// //把C字符串轉(zhuǎn)換成OC字符串
// NSString *str = [NSString stringWithUTF8String:buf];
//把一個字符串反射出對應(yīng)的選擇器類型
// SEL sel = NSSelectorFromString(str); //***********重點
Person *per = [[Person alloc] init];
//定義一個SEL類型的變量;
//該變量里裝的是study這個成員方法蚜点;
// SEL sel = @selector(study);
//
//
// //通過選擇器調(diào)用成員方法轧房;
// [per performSelector:sel];
//
//
//
// SEL sel1 = @selector(setAge:);
// //調(diào)用帶一個參數(shù)的方法;
// [per performSelector:sel1 withObject:@10];
// NSLog(@"per = %d",[per.age intValue]);
//
//
//
// [per performSelector:@selector(setName:) withObject:@"小迪迪"];
// NSLog(@"name = %@",per.name);
//調(diào)用帶兩個參數(shù)的 ,最多只能帶兩個參數(shù)绍绘;
//如果有兩個以上的參數(shù)奶镶,可以考慮重新設(shè)計這個方法,比如傳數(shù)組陪拘,或者設(shè)計另一個類把這些多個參數(shù)都封裝在類里面实辑,一起作為參數(shù)傳過去;
// [per performSelector:<#(SEL)#> withObject:<#(id)#> withObject:<#(id)#>];
//選擇器常用的幾個方法
//1.判斷一個“類”是否存在某個方法
Person *per2 = [[Person alloc] init];
BOOL bl1 = [Person instancesRespondToSelector:@selector(study)];
if (bl1) {
NSLog(@"存在該方法");
[per2 performSelector:@selector(study)];
}else{
NSLog(@"不存在該方法");
}
//2. 判斷一個對象是否實現(xiàn)了某個方法 【***常用】
//常用在調(diào)用協(xié)議方法的時候藻丢,為了保證代碼的安全性,在調(diào)用代理的協(xié)議方法之前摄乒,最好是先判斷該代理對象是否實現(xiàn)了對應(yīng)的協(xié)議方法悠反;
BOOL bl2 = [per2 respondsToSelector:@selector(playGame)];
if (bl2) {
[per2 playGame];
}else{
NSLog(@"你沒有實現(xiàn)這個方法!");
}
//3.協(xié)議選擇器【了解】
//協(xié)議選擇器里面裝的是協(xié)議
Protocol *p = @protocol(NSCopying);
//判斷一個對象是否遵守了某個協(xié)議
BOOL bl3 = [per2 conformsToProtocol:p];
if (bl3) {
if ([per2 respondsToSelector:@selector(copyWithZone:)]) {
Person *perCopy = [per2 copy];
[perCopy release];
}
}else{
NSLog(@"這個類不具備拷貝對象的能力");
}
數(shù)組排序
-(id)initWithAge:(int)age andWithName:(NSString *)name{
if ([super init]) {
self.age = age;
self.name = name;
}
return self;
}
-(NSComparisonResult)compareAndName:(Student *)otherStudent{
return [self.name compare:otherStudent.name];
}
-(NSComparisonResult)compareAndAge:(Student *)otherStudent{
if (self.age == otherStudent.age) {
return [self.name compare:otherStudent.name];
}
// return -[self.age compare:otherStudent.age];
//和上面寫法一樣的效果
return [@(self.age) compare:@(otherStudent.age)];
}