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.判斷一個指針所指向的對象是否是某種類型
id obj = [[Person alloc] init];
BOOL bl2 = [obj isMemberOfClass:[Person class]];
if (bl2) {
NSLog(@"是的");
}else{
NSLog(@"不是的");
}
//3.判斷一個指針所指向的對象是否是某種類型或者它的子類【**常用**】
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)];
}