title: OC_Note date: 2014-10-21 21:16:49tags: OC-NOTESimageNSLog 與 printf的不同1. NSLog接收oc字符串作為參數(shù),printf接收c語(yǔ)言的字符串作為參數(shù)2. NSLog輸出后會(huì)自動(dòng)換行,printf在輸出后不會(huì)自動(dòng)換行3. 使用NSLog時(shí),需要包含頭文件#import;而使用printf時(shí),需要包含頭文件#include4. NSLog可以輸出日期,時(shí)間戳,進(jìn)程號(hào)等信息,而printf不能輸出這些信息
常用術(shù)語(yǔ)
面向過(guò)程 : Procedure Oriented
面向?qū)ο?: Object Oriented ,簡(jiǎn)稱(chēng)OO
面向編程 : Object Oriented Programming,簡(jiǎn)稱(chēng)OOP
OC 語(yǔ)法
類(lèi)的聲明
@interface 類(lèi)名:父類(lèi)(默認(rèn)為 NSObject 該類(lèi)時(shí)根類(lèi))
{
定義成員變量;(默認(rèn)情況下,成員變量為protect類(lèi)型,)
}
( 可以用@public將其定義為public類(lèi)型,此時(shí)定義的屬性或變量允許被外界訪問(wèn))
@property(nonatomic/atomic,readonly/readwrite,assign/strong/retain/wake)類(lèi)型 屬性名;(定義屬性可以自動(dòng)生成setter和getter方法)
聲明類(lèi)方法;(標(biāo)識(shí) + 該方法向類(lèi)發(fā)消息)
聲明實(shí)例方法; (標(biāo)識(shí) - 該方法向?qū)ο蟀l(fā)消息) 聲明類(lèi)方法時(shí) 返回值最好定義為`instancetype`類(lèi)型
@end
類(lèi)的實(shí)現(xiàn)
@implemention 類(lèi)名
- 實(shí)例方法
{
實(shí)現(xiàn)代碼;
}
+ 類(lèi)fangfa
{
實(shí)現(xiàn)代碼;
}
重寫(xiě)父類(lèi)方法;
如:descripition、 dealloc、init等
@end
3.創(chuàng)建對(duì)象
1.包含所創(chuàng)建類(lèi)的頭文件
2.類(lèi)名 *對(duì)象名;
2.1 類(lèi)名 *對(duì)象名 = [[類(lèi)名 alloc]init];(創(chuàng)建對(duì)象并為其分配內(nèi)存、初始化)
2.2 類(lèi)名 *對(duì)象名 = [類(lèi)名 new];(每次都會(huì)創(chuàng)建出新的對(duì)象,并且返回對(duì)象的地址。)
3. 給對(duì)象賦值;(可以調(diào)用相應(yīng)的類(lèi)方法);
4. 給對(duì)象發(fā)消息,完成所需要進(jìn)行的操作;[對(duì)象 方法];
匿名對(duì)象
方法調(diào)用:
[[類(lèi)名 new]方法];/[[[類(lèi)名 alloc]init]方法];
屬性訪問(wèn):
[類(lèi)名 new]->屬性 = 賦值;(外界訪問(wèn)定義為public類(lèi)型的屬性)
OC方法和函數(shù)的區(qū)別
1. OC方法的聲明只能在@interface 和 @end之間,只能在@implementation 和 @end之間。即OC方法獨(dú)立于類(lèi)存在。
2. C函數(shù)不屬于類(lèi),跟類(lèi)沒(méi)有聯(lián)系,C函數(shù)所有權(quán)只屬于定義函數(shù)的文件
3. C函數(shù)不能訪問(wèn)OC對(duì)象的成員變量。
OC語(yǔ)法細(xì)節(jié)
1. 成員變量不能在{}中進(jìn)行初始化、不能直接拿去訪問(wèn)
2. 方法的聲明不能寫(xiě)在@end之后
3. 方法不能當(dāng)作函數(shù)一樣調(diào)用
4. 成員變量、方法不能用static等關(guān)鍵字進(jìn)行修飾
OC方法注意點(diǎn)
方法只有聲明,沒(méi)有實(shí)現(xiàn)(經(jīng)典錯(cuò)誤,系統(tǒng)提示警告)
方法沒(méi)有聲明,只有實(shí)現(xiàn)(編譯器警告,但是可以調(diào)用,OC的弱語(yǔ)法)
編譯的時(shí)候,訪問(wèn)沒(méi)有定義的成員變量直接報(bào)錯(cuò),調(diào)用沒(méi)有的方法,只是警告
沒(méi)有@interface,紙偶@implemenation也可以成功定義一個(gè)類(lèi)
@implemenation Dog : NSObject
{
int _age;
NSString *_name;
}
- (void)print
{
NSLog(@"The dog's name is %@,ang de it's %d years old!",_name,_age);
}
@end
@implemenation 中不能聲明和@interface一樣的成員變量
!!! OC中有BOOL基本數(shù)據(jù)類(lèi)型,其值是YES和NO,而不是true 和false,它實(shí)際上是一種對(duì)帶符號(hào)的自負(fù)類(lèi)型(signed char)的定義(typedef),它使用8為存儲(chǔ)空間。YES定義為1,NO定義為0;
image
類(lèi)方法he實(shí)例方法
類(lèi)方法
* 該方法是直接可以用類(lèi)名來(lái)執(zhí)行的方法(類(lèi)本身會(huì)在內(nèi)存中占據(jù)存儲(chǔ)空間,里面有類(lèi)/對(duì)象方法列表)
* 以加號(hào) + 開(kāi)頭
* 只能用類(lèi)名調(diào)用,對(duì)象不能調(diào)用
* 類(lèi)方法不能訪問(wèn)實(shí)例變量(成員變量)
* 使用場(chǎng)合:當(dāng)不需要訪問(wèn)成員變量時(shí),盡量使用類(lèi)方法
* 類(lèi)方法和對(duì)象方法可以同名
實(shí)例方法
* 該方法是用對(duì)象名來(lái)執(zhí)行的方法
* 以減號(hào) — 開(kāi)頭
* 只能用對(duì)象名調(diào)用,類(lèi)不能調(diào)用,該方法沒(méi)有對(duì)象是不能被執(zhí)行的
* 對(duì)象方法能訪問(wèn)實(shí)例變量(成員變量)
setter和getter方法
setter和getter方法的使用場(chǎng)合
@public的成員可以隨意被賦植,應(yīng)該使用set和get方法來(lái)管理成員變量的訪問(wèn)
setter方法
作用:用來(lái)設(shè)置成員變量,可以在方法里面過(guò)濾一些不合理的值
命名規(guī)范:方法以set開(kāi)頭,而且后面跟上成員變量名,成員變量名必須首字母大寫(xiě),盡量形參名稱(chēng)不要與成員變量名重名(成員變量名最好以下劃線 _ 開(kāi)頭)
返回值:一般為void
getter方法
作用:返回對(duì)象內(nèi)部的成員變量
命名規(guī)范:方法名和成員變量名同名
返回值:一般與成員變量的類(lèi)型相同
self關(guān)鍵字
成員變量和局部變量同名
當(dāng)成員變量和局部變量同名時(shí),采取就近原則,訪問(wèn)的是局部變量
當(dāng)self訪問(wèn)成員變量,區(qū)分同名的局部變量
使用細(xì)節(jié)
1. 出現(xiàn)的地方:所有的OC方法中(對(duì)象方法/類(lèi)方法),不能出現(xiàn)在函數(shù)
2. 作用:
使用“self.屬性”訪問(wèn)當(dāng)前方法中的成員變量
使用“self-> 成員變量”訪問(wèn)當(dāng)前方法中public成員變量
使用“[self 方法]”調(diào)用方法(類(lèi)方法/實(shí)例方法)
3. 類(lèi)方法中self只能調(diào)用類(lèi)方法,實(shí)例方法中self只能調(diào)用實(shí)例方法
繼承
繼承的概念
1. is-a機(jī)制
2. 即當(dāng)創(chuàng)建的多個(gè)類(lèi)有共同的屬性和行為時(shí),可以抽出一個(gè)類(lèi)作為父類(lèi),在父類(lèi)中定義相同的屬性,聲明實(shí)現(xiàn)相同的行為(方法);
3. 子類(lèi)可以使用父類(lèi)的所有屬性和方法,并且子類(lèi)可以在父類(lèi)的基礎(chǔ)上拓補(bǔ)自己的屬性和方法,包括重寫(xiě)父類(lèi)方法。重寫(xiě)父類(lèi)方法時(shí),子類(lèi)對(duì)象會(huì)優(yōu)先調(diào)用子類(lèi)重寫(xiě)后的方法。
4. 子類(lèi)屬性和方法訪問(wèn)的過(guò)程: 如果子類(lèi)沒(méi)有相應(yīng)的方法或?qū)傩?,則去訪問(wèn)父類(lèi),一次遞進(jìn)知道找到NSObject根類(lèi),如果仍然沒(méi)有找到相對(duì)應(yīng)的方法和屬性,則報(bào)錯(cuò)。
繼承的專(zhuān)業(yè)術(shù)語(yǔ)
父類(lèi)/超類(lèi) superclass
子類(lèi) subclass/subclasses
繼承的細(xì)節(jié)
單繼承,不支持多繼承
子類(lèi)和父類(lèi)不能有相同的成員變量
子類(lèi)可以重寫(xiě)父類(lèi)中聲明的方法(在代碼運(yùn)行時(shí),oc確保調(diào)用相應(yīng)類(lèi)的重寫(xiě)方的實(shí)現(xiàn))
繼承的優(yōu)缺點(diǎn)
優(yōu)點(diǎn):
在不改變?cè)瓉?lái)模型的基礎(chǔ)上,拓充方法
建立了類(lèi)與類(lèi)的聯(lián)系
抽取了公共代碼
缺點(diǎn):
耦合性強(qiáng)
super關(guān)鍵字
super既不是參數(shù),也不是實(shí)例變量,而是oc編譯器提供的功能
用于提供一種在子類(lèi)中顯示調(diào)用父類(lèi)的方法
繼承的局限性
父類(lèi)不能訪問(wèn)子類(lèi)屬性、調(diào)用子類(lèi)方法
不能繼承累簇(如 NSString累簇)
多態(tài)
多態(tài)的基本概念
某一類(lèi)事物的多種形態(tài)
OC對(duì)象具有多態(tài)性
多態(tài)的體現(xiàn)
子類(lèi)對(duì)象可以賦值給父類(lèi)指針;
如:Father *f = [children new];
父類(lèi)指針可以訪問(wèn)對(duì)應(yīng)的屬性和方法
如: f.age = 23;
[f study];
多態(tài)的好處
用父類(lèi)接收參數(shù),節(jié)省代碼
多態(tài)的局限性
不能訪問(wèn)子類(lèi)的屬性(可以考慮強(qiáng)制轉(zhuǎn)換)
多態(tài)的細(xì)節(jié)
動(dòng)態(tài)綁定,在運(yùn)行時(shí)根據(jù)對(duì)象的類(lèi)型確定動(dòng)態(tài)調(diào)用的方法
復(fù)合
復(fù)合包括組合和聚合
has-a機(jī)制
組合和聚合表示將各個(gè)部分組合在一起,用于表達(dá)整體與部分的關(guān)系。在面向?qū)ο蟮木幊趟枷肜铮褪怯靡延蓄?lèi)的對(duì)象封裝新的類(lèi)。
組合 :表示一種強(qiáng)的、嚴(yán)格的整體與部分的關(guān)系,部分和整體的生命周期一樣。 比如:人和人頭
聚合 :表示一種弱的整體與部分的關(guān)系,比如: 汽車(chē)和輪胎
Foundition框架
1. OC集合只能存儲(chǔ)OC對(duì)象,不能存儲(chǔ)c語(yǔ)言中的基本數(shù)據(jù)類(lèi)型,如int,float,enum,struct,且不能在集合中存儲(chǔ)nil。
字符串
不可變字符串 : NSString *string1;
可變字符串 : NSMutableString *string2;
對(duì)可變字符串的操作:
2.1 增加元素
string2 appendFormat:@"hello"];
2.2 刪除元素
[string2 replaceCharacterInRange:NAMakeRange(2,3)];
2.3 修改元素(替換)
[string2 replaceCharacterInRange:NAMakeRange(2,3)withString:@"word"];
字符串的操作
3.1 比較
//判斷兩個(gè)字符串是否相等,返回的是BOOL值
[str1 isEqualTo:str2];
NSCompareResult res = [str1 copmare:str2];
不區(qū)分大小寫(xiě)的比較:caseInsensitiveCompare
有選擇參數(shù)的比較: [str compare:str2 option:NSStringCompareOption]
NSStringCompareOption選項(xiàng)可以傳入的參數(shù)
enum {
NSCaseInsensitiveSearch = 1,? 不區(qū)分大小寫(xiě)
NSLiteralSearch = 2,? ? ? ? ? 對(duì)于相等的字符串逐個(gè)比較
NSBackwardsSearch = 4,? ? ? 從后向前比較
NSAnchoredSearch = 8,? ? ? ? 限制比較從開(kāi)始還是結(jié)尾
NSNumericSearch = 64,? ? ? ? 對(duì)于數(shù)字按數(shù)字比較
NSDiacriticInsensitiveSearch = 128,? 不區(qū)分音節(jié)
NSWidthInsensitiveSearch = 256,? ? ? 忽略full-width half-width (如 Unicode code point U+FF41 和 Unicode code point U+0061 的字母 “a”is equal)
NSForcedOrderingSearch = 512,? ? ? ? ? 對(duì)于不區(qū)分大小寫(xiě)比較相等的字符串,強(qiáng)制返回NSOderedAscending or NSOrderedDeascending (如“aa” is grater than “AA”)
NSRegularExpressionSearch = 1024? ? ? ? treated as an ICU-compatible regular expression
};
NSCompareResult 有三種值:
NSOrderedSame? 兩字符串相等
NSOrderedAscending? str1 < str2
NSOrderedDeascending? str1 > str2;
3.2 求長(zhǎng)度
NSUInteger strlen = [str1 length];
3.3 大小寫(xiě)轉(zhuǎn)換
str2 = [str1 uupercaseString];
str2 = [str1 lowercaseString];
3.4 獲取文件前綴、后綴
str2 =[str1 hasPrefix:@"word"];
str2 = [str1 hasSuffix:@"txt"];
3.5 獲取子串
//獲取str2在str1中的位置,即range.location and range.length
range = [str1 rangOfString:str3];
range = [str1 rangOfString:@"hello"];
//獲取str1 第6個(gè)位置之后的字符串賦值給str2
str2 = [str1 substringFromIndex:6];
//獲取str1 從開(kāi)始到第6個(gè)位置之間的字符串賦值給str2
str2 = [str1 substringTOIndex:6];
//獲取str1 從第6個(gè)位置開(kāi)始長(zhǎng)度為5的字符串賦值給str2
str2 = [str1 substringWithRange:NSMakeRange(6,7)];
3.6 文件路徑的轉(zhuǎn)換
//間文件路徑字符串str1 = @“~/test.html”的路徑轉(zhuǎn)換為絕對(duì)路徑賦值給str2
str2 = [str1 stringByExpandingTildeInPath];
//間文件路徑字符串str1 = @“/users/qingyun/test.html”的路徑轉(zhuǎn)換為相對(duì)路徑賦值給str2
str2 = [str1 stringByAbbreviatingWithTildeInPath];
3.7 文件路徑的擴(kuò)展名
str2 = [str1 pathExtension]; 此時(shí) str2 = @“html”;
3.7 刪除文件路徑的后綴
str2 = [str1 stringByDeletePathExtension]; 此時(shí) str2 = @“~/test”;
3.9 追加字符串
str1 = @"hello word";
str2 = [str1 stringByAppendingFormat:@"wellcom"]; 此時(shí) str2 = @“hello word wellcom”;
數(shù)組
不可變數(shù)組 : NSArray *array1;
可變數(shù)組 : NSMutableArray *array2;
數(shù)組初始化:
NSArray *array1 = [NSArray arrayWithObjects:@"hello",@"word",@"two",nil];
NSArray *array1 = @[@12,@34,@"hello",@"error"];
//創(chuàng)建空數(shù)組
NSMutableArray *array2 = [NSMutableArray array];
//用已有的數(shù)組創(chuàng)建新數(shù)組
NSMutableArray *array2 = [NSMutableArray arrayWithArray:array];
//創(chuàng)建一個(gè)數(shù)組,并預(yù)分配內(nèi)存
NSMutableArray *array2 = [NSMutableArray arrayWithCapacity:40];
對(duì)可變數(shù)組的操作:
2.1 增加元素
[array2 addObjects:@"hello"];
2.2 刪除元素
//刪除下標(biāo)為2的對(duì)象
[array2 removeObjectsAtIndex:2];
//刪除一定范圍內(nèi)的所有@“hello”
[array2 removeObject:@"hello" inRange:NSMakeRange(2, 3)];
[array3 removeObjectIdenticalTo:@"is" inRange:NSMakeRange(1, 5)];
//刪除該數(shù)組內(nèi)的所有@“hello”
[array2 removeObjectIdenticalTo:@"hello"];
2.3 修改元素(替換)
[array2 removeObjectsAtIndex:2 withObject:@"dog"];
[array2 removeObjectsAtIndex:2 withObject:str];
[array2 removeObjectsInRange:NSMakeRang(0,2) withObjectFromArray:array];
2.4 插入元素
[array2 insertObjects:str1 AtIndex:2];
2.5 訪問(wèn)數(shù)組某個(gè)對(duì)象
array2[下標(biāo)]
字典
不可變數(shù)組 : NSDictionary *dictionary1;
可變數(shù)組 : NSMutableDictionary *dictionary2;
字典初始化:
Dictionary *dictionary1 = [NSDictionary dictionaryWithObjectsAndKeys:str1,@"hello",str2,@"word",str3,@"two",nil];
Dictionary *dictionary1 = @{@"num1":@12,@"num2":@34,@"str1":@"hello",@"str2":@"error"};
//創(chuàng)建空字典
NSMutableDictionary *dictionary2 = [NSMutableDictionary dictionary];
//用已有的字典創(chuàng)建新字典
NSMutableDictionary *dictionary2 = [NSMutableDictionary dictionaryWithDictionary:array];
//創(chuàng)建一個(gè)字典,并預(yù)分配內(nèi)存
NSMutableDictionary *dictionary2 = [NSMutableDictionary dictionaryWithCapacity:40];
對(duì)可變字典的操作:
2.1 增加元素
[dictionary2 addObjects:(id)forKey:@"key"];
2.2 刪除元素
[dictionary2 removeObjectForKey:@"key"];
2.3 修改元素(替換)
[dictionary2 setObject:(id)forKey:@"key"];
2.4 訪問(wèn)字典
dictionary2[@“key”];
[dictionary2 objectForKey:@"key"]
裝箱-開(kāi)箱
對(duì)基本數(shù)據(jù)類(lèi)型的裝箱-NSNumber
//裝箱方法1
NSNumber *number = [NSNumber numberWithChar:'X'];
NSNumber *number = [NSNumber numberWithINT:23];
NSNumber *number = [NSNumber numberWithBOOL:YES];
NSNumber *number = [NSNumber numberWithDouble:34.5];
//裝箱方法2
@23,@34.5
//開(kāi)箱
[number charValue];
[number intValue];
[number BOOLValue];
[number DoubleValue];
對(duì)所有非對(duì)象類(lèi)型的裝箱(包括基本數(shù)據(jù)類(lèi)型)- NSValue
//對(duì)NSRect,NSPoint,NSRange裝箱,也可以對(duì)基本數(shù)據(jù)類(lèi)型進(jìn)行裝箱
NSRect rect = NSMakeRect(10,20,30,40);
NSValue *value = [NSvalue valueWithBytes:&rect objCType:@encode(NSRect)];
int a = 5;
NSValue *value = [NSvalue valueWithBytes:&a objCType:@encode(int)];
//開(kāi)箱
NSRect rect2 = {0};
[value getValue:&rect];
int b = 0;
[value getValue:&b];
//僅對(duì)NSRect,NSPoint,NSRange裝箱
NSValue *value = [NSValue valueWithRect];
NSValue *value = [NSValue valueWithRange];
NSValue *value = [NSValue valueWithPoint];
//開(kāi)箱
NSRect rect2 = {0};
[value rectValue];
NSRange range = {0};
[value rangeValue];
NSPoint point = {0};
[value pointValue];
枚舉
//normal enumerator
NSEnumerator *enumer = [array objectEnumerator];
id obj;
while (obj = [enumer nextObject]) {
NSLog(@"%@",obj);
}
NSEnumerator *enumer2 = [array reverseObjectEnumerator];
while (obj = [enumer2 nextObject]) {
NSLog(@"%@",obj);
}
//fast enumerator
for (id obj2 in array) {
NSLog(@"%@",obj2);
}
類(lèi)別
類(lèi)別的簡(jiǎn)述
為現(xiàn)有的類(lèi)(自定義的類(lèi)、第三方的類(lèi)或者是系統(tǒng)定義的類(lèi))添加一些新的行為;
類(lèi)別可以解決繼承不能為累簇添加新方法的問(wèn)題。
類(lèi)別的聲明和實(shí)現(xiàn)
格式: 類(lèi)名 + 類(lèi)別名
如:為NSString 創(chuàng)建一個(gè)類(lèi)別 NSString+NumberConvenience;
只要保證類(lèi)別名稱(chēng)唯一,可以向一個(gè)類(lèi)中添加任意數(shù)量的類(lèi)別。
聲明:
@interface NSString (NumberConvenience)
- (NSNumber *)lengthAsNumber;
@end
實(shí)現(xiàn):
@implementation NSString (NumberConvenience)
- (NSNumber *)lengthAsNumber {
}
@end
類(lèi)別的優(yōu)缺點(diǎn)
缺點(diǎn):
* 只能添加方法,只可以訪問(wèn)原始類(lèi)的實(shí)例變量,無(wú)法向類(lèi)別中添加新的實(shí)例變量
* 名稱(chēng)沖突。類(lèi)別具有最高優(yōu)先級(jí),即當(dāng)類(lèi)別中定義與對(duì)應(yīng)類(lèi)中已有的方法同名的方法,對(duì)象調(diào)用該方法時(shí),會(huì)優(yōu)先調(diào)用類(lèi)別中定義的方法。
* 多個(gè)Category中如果實(shí)現(xiàn)了相同的方法,只有最后一個(gè)參與編譯的才會(huì)有效
優(yōu)點(diǎn):
* 將類(lèi)的實(shí)現(xiàn)代碼分散到多個(gè)不同文件或框架中。
* 可以創(chuàng)建對(duì)類(lèi)中私有方法的前向引用,
* 向?qū)ο筇砑臃钦絽f(xié)議。
使用類(lèi)別實(shí)現(xiàn)類(lèi)的擴(kuò)展
類(lèi)的擴(kuò)展等同于在類(lèi)聲明的源代碼中聲明一個(gè)無(wú)名的(即括號(hào)“ () ”里面為空)類(lèi)別,并實(shí)現(xiàn);
類(lèi)的擴(kuò)展可以在源代碼中使用
可以添加實(shí)例變量作為類(lèi)的私有變量和方法
可以將只讀權(quán)限改為讀寫(xiě)權(quán)限
創(chuàng)建數(shù)量不限
利用類(lèi)別分散實(shí)現(xiàn)代碼的優(yōu)點(diǎn)
. 在大型的項(xiàng)目中, 一個(gè)類(lèi)的實(shí)現(xiàn)可能非常大,并且.m文件不能分離。但是使用類(lèi)別可以將一個(gè)類(lèi)的實(shí)現(xiàn)分散且有規(guī)律的組織在不同的文件中。還可以將一個(gè)類(lèi)的實(shí)現(xiàn)分散到不同的框架中。
. 編程人員可以更加容易閱讀代碼并實(shí)現(xiàn)多人合作編碼
. 版本管理降低沖突
. 維護(hù)人員更容易理解代碼
非常正式協(xié)議
非正式協(xié)議就是為NSObject類(lèi)創(chuàng)建一個(gè)類(lèi)別;
響應(yīng)選擇器
使用@selector()編譯指令來(lái)指定選擇器,圓括號(hào)里是具體的方法名。如:
@selector(setEngine:)
@selector(setTire:atIndex)
選擇器的類(lèi)型關(guān)鍵字:SEL
(BOOL)respondsToSelector:(SEL)@Selector; 使用此方法可以判斷某一對(duì)象是否可以執(zhí)行指定的方法。
QYStudent *student = [[QYStudent alloc]init];
如: [student respondToSelector:(SEL)@selector(study)];
協(xié)議
基本用途
可以用來(lái)聲明一大堆方法(不能聲明成員變量)
只要某個(gè)類(lèi)遵守了這個(gè)協(xié)議,就相當(dāng)于擁有這個(gè)協(xié)議中的所有方法聲明
只要父類(lèi)遵守了某個(gè)協(xié)議,就相當(dāng)于子類(lèi)也遵守了
格式 @protocol 協(xié)議名
方法聲明列表
@end
某個(gè)類(lèi)遵守某個(gè)協(xié)議
@interface 類(lèi)名 : 父類(lèi)名<協(xié)議名>
@end
關(guān)鍵字
協(xié)議中有2個(gè)關(guān)鍵字可以控制方法是否要實(shí)現(xiàn)(默認(rèn)是@required),在大多數(shù)情況下,用途在于程序員之間的交流
@required: 該關(guān)鍵字以下且@optional關(guān)鍵字以上的方法必須要實(shí)現(xiàn)(若不實(shí)現(xiàn),編譯器會(huì)發(fā)出警告
@optional: 該關(guān)鍵字以下且@required關(guān)鍵字以上的方法可以選擇性的實(shí)現(xiàn)
協(xié)議遵守協(xié)議
一個(gè)協(xié)議可以遵守其他多個(gè)協(xié)議,多個(gè)協(xié)議之間用逗號(hào) , 隔開(kāi)
一個(gè)協(xié)議遵守了其他協(xié)議,就相當(dāng)于擁有了其他協(xié)議中的方法聲明
@protocol 協(xié)議名稱(chēng) <協(xié)議1, 協(xié)議2>
@end
基協(xié)議
NSObject是一個(gè)基類(lèi),最根本最基本的類(lèi),任何其他類(lèi)最終都要繼承它
其實(shí)還有一個(gè)協(xié)議,名字也叫NSObject,它是一個(gè)基協(xié)議,最根本最基本的協(xié)議
NSObject協(xié)議中聲明很多最基本的方法,比如description、retain、release等
建議每個(gè)新的協(xié)議都要遵守NSObject協(xié)議
定義變量時(shí)指定協(xié)議
// NSObject類(lèi)型的對(duì)象,并且要遵守NSCopying協(xié)議
NSObject *obj;
// 任何OC對(duì)象,并且要遵守NSCoding協(xié)議
id obj2;
內(nèi)存管理
內(nèi)存管理機(jī)制:引用計(jì)數(shù)
引用計(jì)數(shù)的計(jì)算
alloc 、new 、copy(copy生成接收對(duì)象的一個(gè)副本) //使用這三個(gè)方法創(chuàng)建對(duì)象時(shí),對(duì)象的引用計(jì)數(shù)器為1
(id) retain; //給對(duì)象發(fā)送retain消息后,對(duì)象的引用計(jì)數(shù)器加1
(void) release; //給對(duì)像發(fā)送release消息后,對(duì)象的引用計(jì)數(shù)器減1
-(void)dealloc; //當(dāng)一個(gè)對(duì)象的引用計(jì)數(shù)器變?yōu)?而即將被銷(xiāo)毀時(shí),Objective-C自動(dòng)向?qū)?象發(fā)送一條dealloc消息,我們通常都會(huì)在自己的對(duì)象中重寫(xiě)dealloc方法
(unsigned) retainCount;//獲取當(dāng)前對(duì)象的引用計(jì)數(shù)器的值
非ARC環(huán)境下內(nèi)存的管理
當(dāng)某個(gè)對(duì)象被持有有,[對(duì)象名 retain]; 當(dāng)某個(gè)對(duì)象不再被持有時(shí),[對(duì)象名 release];
ARC環(huán)境下內(nèi)存的管理
規(guī)則
只要還有一個(gè)強(qiáng)指針變量指向?qū)ο?,?duì)象就會(huì)保持在內(nèi)存中
強(qiáng)引用,弱引用
? 默認(rèn)所有實(shí)例變量和局部變量都是Strong指針
? 弱指針指向的對(duì)象被回收后,弱指針會(huì)自動(dòng)變?yōu)閚il指針,不會(huì)引發(fā)野指針錯(cuò)誤。其修飾符號(hào)為_(kāi)_weak;
注意點(diǎn)
? 不能調(diào)用release、retain、autorelease、retainCount
? 可以重寫(xiě)dealloc,但是不能調(diào)用[super dealloc]
? @property : 想長(zhǎng)期擁有某個(gè)對(duì)象,應(yīng)該用strong,其他對(duì)象用weak
? 其他基本數(shù)據(jù)類(lèi)型依然用assign
? 兩端互相引用時(shí),一端用strong、一端用weak
自動(dòng)釋放池
自動(dòng)釋放池是一個(gè)存放實(shí)體的集合,這些實(shí)體可能是對(duì)象,這些對(duì)象能夠被自動(dòng)釋放。
/ - (id) autorelease; //是NSObject類(lèi)提供的方法,此方法在某一個(gè)預(yù)定的時(shí)候,向?qū)ο蟀l(fā)送release消息,返回值是接收消息的對(duì)象。實(shí)際上當(dāng)給一個(gè)對(duì)象發(fā)送autorelease消息的時(shí)候,就是將這個(gè)對(duì)象添加到的自動(dòng)釋放池(NSAutoreleasePool)中,當(dāng)自動(dòng)釋放池銷(xiāo)毀時(shí),會(huì)向該池中的所有對(duì)象發(fā)送release消息。
如: - (NSString ) description
{
NSString desc;
desc = [[NSString alloc] initWithFormat: @” I am %d years old”,29];
return ([desc autorelease]);
}
內(nèi)存管理規(guī)則
如果我使用了new , alloc 或者copy方法獲得一個(gè)對(duì)象,則我必須釋放或自釋放該對(duì)象。
如果你對(duì)對(duì)象調(diào)用了retain消息,那么你必須負(fù)責(zé)釋放(release)這個(gè)對(duì)象,保證retain和release的使用次數(shù)相等。
拷貝
淺拷貝(shallow copy)
不會(huì)復(fù)制所引用的對(duì)象,新復(fù)制的對(duì)象只會(huì)指向現(xiàn)有的引用對(duì)象上。(引用計(jì)數(shù)加 1 ,地址不變)
深拷貝(deep copy)
真正意義的復(fù)制概念。得到的結(jié)果是多個(gè),而非只是對(duì)象的引用。(引用計(jì)數(shù) 不變 ,地址發(fā)生變化)
關(guān)鍵字
copy:對(duì)不可變的集合copy為淺拷貝,對(duì)可變的集合copy為深拷貝
mutableCopy:對(duì)可變的或不可變的集合mutableCopy都是深拷貝,但是對(duì)于集合內(nèi)部對(duì)象的拷貝時(shí)淺拷貝。
BLOCK
基本概念
代碼塊本質(zhì)上是和其他變量類(lèi)似。不同的是,代碼塊存儲(chǔ)的數(shù)據(jù)是一個(gè)函數(shù)體。使用代碼塊時(shí),可以像調(diào)用其他標(biāo)準(zhǔn)函數(shù)一樣,傳入?yún)?shù)數(shù),并得到返回值。
Block封裝了一段代碼,可以在任何時(shí)候執(zhí)行
Block可以作為函數(shù)參數(shù)或者函數(shù)的返回值,而其本身又可以帶輸入?yún)?shù)或返回值。
蘋(píng)果官方建議盡量多用block。在多線程、異步任務(wù)、集合遍歷、集合排序、動(dòng)畫(huà)轉(zhuǎn)場(chǎng)用的很多
定義
int (^MySum)(int, int) = ^(int a, int b) {
return a+b;
};
定義了一個(gè)叫MySum的blocks對(duì)象,它帶有兩個(gè)int參數(shù),返回int。等式右邊就是blocks的具體實(shí)現(xiàn)
對(duì)變量的訪問(wèn)權(quán)限
對(duì)全局變量具有讀寫(xiě)權(quán)限
對(duì)靜態(tài)變量具有讀寫(xiě)權(quán)限
對(duì)局部變量只有訪問(wèn)權(quán)限(可以用__block修飾局部變量,這樣可以對(duì)其進(jìn)行修改)
與函數(shù)指針的對(duì)比
定義函數(shù)指針
int (*p)(int,int);
定義Blocks
int (^Blocks)(int,int);
調(diào)用函數(shù)指針
(*p)(10, 20);
調(diào)用Blocks
Blocks(10, 20);
typedef和賦值
在聲明的同時(shí)定義變量,然后賦值
int (^MySum)(int,int) = ^(int a,int b) {
return a + b;
};
也可先用typedef先聲明類(lèi)型,再定義變量進(jìn)行賦值
typedef int (^MySum)(int,int);
MySum sum = ^(int a,int b) {
return a + b;
};
KVC(Key Valuble Coding)
基本概念
是一種間接更改對(duì)象狀態(tài)(或者說(shuō)是屬性值)的方式:key-value coding 簡(jiǎn)稱(chēng)KVC.
主要本質(zhì)特點(diǎn)是采用字符串來(lái)標(biāo)識(shí)對(duì)象的屬性變量,并可以利用這個(gè)標(biāo)識(shí)來(lái)更改對(duì)象的狀態(tài)(或者說(shuō)是屬性值)
基本用法
(id)valueForKey:(NSString *)key //以key作為標(biāo)識(shí)符,獲取其對(duì)應(yīng)的屬性值
(void)setValue:(id)value forKey:(NSString *)key //以key作為標(biāo)識(shí)符設(shè)置其對(duì)應(yīng)的屬性值。
調(diào)用機(jī)制
valueForKey:會(huì)首先查找以參數(shù)名命名(格式為-key或者isKey)的getter方法,如果找到的話(huà)則調(diào)用這個(gè)方法;如果沒(méi)有找到這樣的getter方法,它將會(huì)在對(duì)象內(nèi)部尋找名稱(chēng)格式為_(kāi)key或者key的實(shí)例變量,然后返回。
setValue:forKey:的機(jī)制跟valueForKey相似。它首先查找參數(shù)名命名的setter方法,如果找到的話(huà)則完成設(shè)置;如果沒(méi)有找到setter方法, 則直接在類(lèi)中找到名稱(chēng)格式為_(kāi)key或者key的實(shí)例變量, 然后將value賦值給它。
鍵路徑
鍵路徑的概念和表示:可以在對(duì)象和不同的變量名稱(chēng)之間用圓點(diǎn)分開(kāi)來(lái)表示。
-(id)valueForKeyPath:(NSString *)keyPath //以keyPath作為標(biāo)識(shí)符,獲取其對(duì)應(yīng)的屬性值
-(void)setValue:(id)value forKeyPath:(NSString *)keyPath //以keyPath為標(biāo)識(shí)符,設(shè)置其對(duì)應(yīng)的屬性的值。
謂詞