1. 使用 #import 相對c的 include 是防止頭文件的重復導入
2. NSLog 相對于 printf 會自動換行 顯示當前時間與項目的基本信息
3. ?OC中的對象方法用 - 開頭表示 ?類方法用 + 開頭表示登淘, 對象方法只能通過對象來調用 也就是說 通過指針來調用 ?類方法只能通過類來調用
4. 使用對象方法,創(chuàng)建一個對象開辟一個存儲空間 ? 如果不想使用方法都需要創(chuàng)建對象開辟存儲空間少漆,可以把方法定義為類方法文留。 ? 類方法不需要去創(chuàng)建存儲空間 優(yōu)化性能 ?
5. 對象方法可以直接訪問屬性(成員變量)類方法不可以
6. 類方法的優(yōu)點 調用類方法的效率會比調用對象方法要高
7. 類方法和對象方法可以相互調用 對象方法可以直接調用類方法, 類方法中可以間接調用對象方法?
8. 創(chuàng)建對象: 1. 開辟存儲空間 2. 初始化所有屬性 3. 返回指針地址?
9. 存儲空間 : 代碼區(qū) ?堆區(qū) 棧區(qū) ?在堆區(qū)初始化對象 在棧區(qū)存放對象的地址
10. 創(chuàng)建對象的時候返回的地址其實就是類的第0個屬性的地址 ?尘分,但是類的第0個屬性其實是isa屬性(自動創(chuàng)建)isa是一個指針搁宾,占八個字節(jié)
11. 類對象是系統(tǒng)幫我們創(chuàng)建的猎唁,里面保存了當前的所有方法,實例對象是我們通過new方法自己創(chuàng)建的会放。
12. 寫在類聲明的大括號中的變量饲齐,我們稱之為成員變量(或者屬性,實例變量)咧最,成員變量只能通過對象來訪問捂人,成員變量不能離開類,離開類之后就不是成員變量窗市,成員變量不能再定義的時候進行初始化先慷, ?存儲在堆里面饮笛,存儲在堆中的數(shù)據(jù)咨察,不會被自動釋放,只能程序員手動釋放
13.寫在函數(shù)或者代碼塊中的變量福青,我們稱之為局部變量摄狱,作用域:從定義的那一行開始,一直到遇到大括號或者return无午,作用域變量可以先定義在初始化媒役,也可以定義的時候同時初始化, 存儲在棧里面宪迟, ?存儲棧中的數(shù)據(jù)有一個特點酣衷,系統(tǒng)會自動給我們釋放
14. 寫在函數(shù)和大括號外部的變量,我們稱之為全局變量次泽,作用域:從定義的那一行開始穿仪,一直到文件末尾,局部變量可以先定義在初始化啊片,也可以定義的同時初始化,存儲在靜態(tài)區(qū)中玖像,程序一啟動的時候就會分配存儲空間紫谷,直到程序結束才釋放. 存儲在當前對象對應的存儲空間中
15. 函數(shù)和方法的區(qū)別:函數(shù)屬于整個文件,方法屬于某一個類捐寥,方法只能通過對象或類調用笤昨, 函數(shù)可以直接調用,雖然函數(shù)屬于整個文件握恳,但是如果把函數(shù)寫在類的聲明中會不識別咬腋,不能把函數(shù)當做方法來調用,也不能把方法當做函數(shù)來調用
16. 方法:屬性方法睡互,類方法 ? ?方法可以沒有聲明只有實現(xiàn)根竿, 方法也可以只有聲明沒有實現(xiàn)陵像,第二種情況:編譯時不會報錯,運行會報錯 unrecoginized selector sent to class'0x12132' 發(fā)送了一個不能識別的消息
17. 函數(shù)中不能直接訪問成員變量寇壳, 成員變量和方法不能用static關鍵字修飾醒颖,不要和c語言混淆
18. 封裝:屏蔽內部實現(xiàn)的細節(jié),僅僅對外提供共有的方法/接口 好處:保證數(shù)據(jù)的安全性壳炎,對傳入的數(shù)據(jù)進行隔離泞歉。一般情況下不會對外直接暴露成員變量,都會提供一些共有的方法進行復制匿辩,成員變量都被封裝起來
19. 由于經常需要定義一些方法來操作成員變量腰耙,而每個方法都必須有一個有意義的名稱,所有就有了getter-setter方法(為了取名方便)程序員的一種規(guī)范
20. setter方法的作用:設置成員變量的值铲球,setter方法一定是對象方法挺庞,一定沒有返回值,一定以set開頭稼病,并且set后面跟上需要設置的成員變量的名稱去掉下劃線选侨,并且首字母大寫,一定有參數(shù)(為成員變量設置set和get方法)
21. getter方法:獲取成員變量的值然走,getter一定是對象方法援制,一定有返回值,而且返回值一定和獲取的成員變量的類型一致芍瑞,方法名稱就是獲取的成員變量的名稱去掉下劃線即可晨仑,一定沒有參數(shù)
22. 成員變量以下劃線開頭的好處,就是可以用于區(qū)分局部變量和成員變量
23. 如果給屬性提供了getter和setter方法拆檬,那么訪問屬性就可以用點語法進行訪問了
24. 點語法的本質就是調用setter和getter方法洪己,點語法是一個編譯器的特性,會在程序編譯成二進制的時候將點語法自動轉化成setter和getter方法秩仆。
25. 如果點語法在等號左邊码泛,那么系統(tǒng)會自動轉換成setter方法,如果點語法在等號右邊澄耍,或者沒有等號噪珊,那么編譯器就會自動轉換為getter方法
26. 點語法一般用于給成員變量賦值,如果不是給成員變量賦值一般情況下不建議使用齐莲,但也可以使用痢站。
27. ? self 會自動區(qū)分類方法和對象方法,如果在類方法中使用self調用對象 方法选酗,那么會直接報錯阵难。
28. super 是編譯器的指令符號,如果調用父類的方法的時候為了避免多余代碼 ? 用super去調用父類的方法芒填。呜叫。空繁。。如果想在子類中調用父類的方法用super ?朱庆, ?如果用self會先在子類中去找盛泡,如果出現(xiàn)和父類的方法重名,會出現(xiàn)死循環(huán)娱颊。super應用環(huán)境:已經重寫父類的方法傲诵,想保留父類的功能。
29. 程序中多態(tài):父類指針指向子類的對象箱硕,沒有繼承就沒有多態(tài)拴竹。 多態(tài)指一種事物的多種表現(xiàn)形態(tài)。多態(tài)具有動態(tài)類型剧罩,在編譯的時候編譯器只會檢查當前類型對應的類中有沒有需要調用的方法栓拜,在運行時,系統(tǒng)會自動判斷真實類型斑响。 如果想調用子類特有的方法必須強制類型轉換為子類才能調用菱属。優(yōu)點:提高了代碼的擴展性钳榨。
30. 實例變量修飾符:
@public 1. 可以在其他類中訪問被public修飾的成員變量 2. 也可以在本類中訪問被public修飾的成員變量 3. 可以在子類中訪問父類別public修飾的成員變量
@private 1. 不可以在其他類中訪問被private修飾的成員變量 2. 可以在本類中訪問被private修飾的成員變量 3.不可以在子類中訪問父類別private修飾的成員變量
@protected 1. 不可以在其他類中訪問被protected修飾的成員變量 2. 可以在本類中訪問被protected修飾的成員變量 3.可以在子類中訪問父類別private修飾的成員變量
@package 介于public與private之間的舰罚,如果是在其他包中訪問那么就是就是private的,如果實在當前代碼所在的包中訪問就是public的
實例變量修飾符作用域:從出現(xiàn)的位置開始薛耻,一直直到下一個修飾符出現(xiàn)营罢,如果沒有遇到下一個實例變量修飾符,那么就是修飾后面所有的實例變量饼齿。
31. %@是用來打印對象的饲漾,其實是用于打印字符串。(打印一個類缕溉,和一個對象的地址)只要給類發(fā)送class消息考传,就會返回當前類的類對象?
32. 只要利用%@打印某個對象,系統(tǒng)內部默認就會調用父類的description減號方法证鸥,調用該方法僚楞,該方法會返回一個字符串,字符串的默認格式 <類的名稱:對象的地址> ? 用%@打印某個類枉层,就會調用父類的(nsobject)的加號開頭的description ?兩種情況都可以重新父類的description方法泉褐。如果通過%@打印對象,就會調用減號開頭的鸟蜡,如果通過%@打印類就會調用加號開頭的膜赃。
33. self寫在對象方法中就代表當前調用該方法的對象。訪問屬性的三種方法:1. p.age 2. p->age 3. [p age];
34. 在description方法中盡量不要使用self來獲取成員變量揉忘,因為如果你經常在description方法中使用self可能不小心就寫成了%@跳座,self ? ? ? ?如果在description方法中利用%@輸出self會造成死循環(huán)端铛。
35. 私有變量和私有方法{
實例變量(成員變量)既可以在@interface中定義,也可以在@implementation中定義疲眷,寫在@implementation中定義的默認就是私有變量被@private修飾沦补,并且在其他類中無法查看, ?在interface中定義的在其他類中都可以查看咪橙,只不過有的不可以進行操作而已夕膀。
在OC中沒有真正的私有方法,因為OC是消息機制美侦。
}
36. @property: 是一個編譯器指令产舞,告訴xcode需要執(zhí)行什么命令,用property替換一些代碼 菠剩,在xcode4.4之前易猫,可以使用@property來代替getter/setter方法的聲明,也就是說我們只需要寫上@property就不要寫getter/setter方法的色具壮。 ?編譯器只要看到@property就知道我們要生成一個屬性getter/setter的方法的聲明 @property int age 用這種格式來替換age的set和get方法
37. @synthesize基本使用:是一個編譯器指令准颓,它可以簡化我們getter/setter方法的實現(xiàn)。實現(xiàn)在聲明后面寫上大括號代表被實現(xiàn). 1.在@synthesize age;后面告訴編譯器棺妓,需要實現(xiàn)哪一個@property生成的聲明攘已。2. 告訴synthesize,需要將傳入的值賦值給誰和返回的值給使用者 @synthesize age = _age; 如果@synthesize age;是這種形式的賦值怜跑,則系統(tǒng) 默認會賦值給和@synthesize后面寫的名稱相同的成員變量. 但是@property會默認賦值給_age帶有下滑線的age.
38. 在xcode4.4之后样勃,對@property進行了增強。只要利用一個@property就可以同時生成setter/getter的聲明和實現(xiàn)? . ?@property會默認賦值給_age帶有下滑線的age. @property有一個弊端性芬,它只會生成最簡單的getter/setter方法峡眶,不會對傳入的值進行判斷.如果想對傳入的數(shù)據(jù)進行過濾,那么我們就必須重寫getter/setter方法植锉。 如果重寫setter方法辫樱,那么property就只會生成getter方法,如果重寫了getter方法俊庇,那么property就只會生成setter方法狮暑。@property自動幫我們生成的成員變量是一個私有的成員變量(_age),也就是說在.m中生成的暇赤,而不是在.h中生成的心例。如果重寫了setter/getter方法,那么property就不會自動幫我們生成私有的成員變量鞋囊,下劃線開頭的age.(舉例age).
39. property修飾符:{
如果給一個屬性提供了getter/setter方法止后,那么我們稱這個屬性為可讀可寫屬性,如果只提供了getter方法,那么成這個屬性為只讀屬性译株,如果只提供了setter方法瓜喇,那么我們稱這個屬性為只寫屬性,如果都沒有提供歉糜,那么我們稱這個屬性為一個私有屬性乘寒。
readonly 不生成setter方法,只生成getter方法匪补,readwrite既生成setter方法伞辛,有生成getter方法。
格式:@property(屬性修飾符) 數(shù)據(jù)類型 變量名稱夯缺;默認修飾符readwrite
自定義getter方法名稱:
@property(getter = abc)int height;
}
readonly為只讀屬性蚤氏,如果想修改其值,?這個時候我們可以用KVC來給聲明為readonly的屬性重新賦值踊兜。?
[對象 setValue:"value" forKey:NSStringFromSelector(@selector("屬性名"))];
/// 就會變成新值
nslog(@"%@",對象.屬性名);
40. id 數(shù)據(jù)類型:是一個動態(tài)數(shù)據(jù)類型竿滨。
默認情況下所有的數(shù)據(jù)類型都是靜態(tài)數(shù)據(jù)類型,靜態(tài)數(shù)據(jù)類型的特點:在編譯時就知道變量的類型捏境,知道變量中有哪些屬性和方法于游。在編譯的時候就可以訪問這些屬性和方法,并且如果是通過靜態(tài)數(shù)據(jù)類型定義變量垫言,如果訪問了不屬于靜態(tài)數(shù)據(jù)類型的屬性和方法贰剥,那么編譯器就會報錯。
動態(tài)類型的特點: 在編譯的時候編譯器并不知道變量的真實類型骏掀,只有在運行的時候才知道他們的真實類型鸠澈,并且如果通過動態(tài)數(shù)據(jù)類型定義變量柱告,如果訪問了不屬于這種數(shù)據(jù)動態(tài)類型的方法和屬性截驮,編譯器不會報錯.
id 相當于 id = NSObject * ? ?屬于萬能指針。他們兩個的區(qū)別:id是動態(tài)類型际度,NSObject屬于靜態(tài)類型葵袭。通過靜態(tài)數(shù)據(jù)類型定義變量,不能調用子類特有的方法乖菱,通過動態(tài)數(shù)據(jù)類型定義變量坡锡,可以調用子類特有的方法。 ?通過動態(tài)數(shù)據(jù)類型定義的變量窒所,可以調用私有的方法鹉勒。
弊端:由于動態(tài)數(shù)據(jù)類型可以調用任意方法,所以可能調用不屬于自己的方法吵取,而編譯時又不會報錯禽额,所以可能導致運行時錯誤。id 一般用于多態(tài)「梗可以減少代碼量实辑,避免調用子類特有的需要強制轉換。為了避免數(shù)據(jù)類型引發(fā)的運行時的錯誤藻丢,一般情況下如果使用動態(tài)數(shù)據(jù)類型定義一個變量剪撬,在調用這個變量的方法之前會進行一次判斷,判斷當前變量是否能夠調用這個方法悠反。(使用iskindOfClass:【NSObject class】進行判斷)isMemberOfClass 也可以 ? 兩者的區(qū)別:isKindOfClass 用于判斷是否屬于本類或子類 ? isMemberOfClass 只用于判斷是否屬于本類残黑。
[Student isSubClassOfClass:[Person class]] ?用于判斷 student是否是person子類
41. new方法 1.開辟存儲空間(調用+alloc方法) ? 2.初始化所有的屬性 調用-init 方法(成員變量)3. 返回對象的地址 ?new 相當于【alloc init】
alloc做了什么事情:1. 開辟存儲空間 2. 將所有的屬性設置為0 ? ?3. 返回當前實例變量的地址 ? init做的事情:1. 初始化成員變量,但是默認情況下init的實現(xiàn)是什么都沒有做. 2. 返回初始化后的實例對象地址斋否。
注意:alloc和init返回的存儲空間是同一個 ?打印地址 %p?
42. 構造方法:init開頭的方法萍摊。用于初始化一個對象,讓某個對象一創(chuàng)建出來就擁有某些屬性和值如叼。重寫init方法冰木,在init方法中初始化成員變量,注意:重寫init方法必須按照蘋果規(guī)定的格式重寫笼恰,如果不按照規(guī)定會引發(fā)一些位置的錯誤踊沸。-(instancetype)init{_age = 10}
蘋果固定格式:1.不能先初始化父類,在初始化子類 2. 必須判斷父類是否初始化成功社证,只有父類初始化成功才能繼續(xù)初始化子類 3. 返回當前的地址
-(instancetype)init{
self = [super init];//初始化父類逼龟,只要父類初始化成功,就會返回對應的地址追葡,如果初始化失敗腺律,就會返回nil==0==假==初始化失敗
? ? ? ? ?if(self != nil){//判斷是否初始化成功
? ? ? ? ? ? ? ? //初始化子類, ? ? ? ?設置初始化的值
? ? ? ? ? ?_age = 10;
? ? ? }
? ? ? //返回地址
? ? return self;
}
43. instancetype和id的區(qū)別:他們都是萬能指針宜肉,指向一個對象匀钧,但是,instancetype在編譯的時候能判斷這個對象是什么類型谬返,id在編譯的時候不能判斷對象的真是類型之斯。另外一個區(qū)別:id可以用來定義變量,可以作為形參遣铝,可以作為返回值佑刷,而instancetype只能作為返回值。 ?自定義構造方法酿炸,盡量使用instancetype瘫絮,在編譯的時候就能檢查錯誤
44. 自定義構造方法:其實就是自定義一個init方法。 ? 一定是對象方法填硕,一定返回id或者instancetype 麦萤,一定以init開頭
-(instancetype)initWithAge:(int)age{if[self = [super init]] _age = age; return self;}(With的W必須要大寫)
一個類可以有0個或多個自定義構造方法。
自定義構造方法的繼承。 ?在子類中super 父類的init方法 ? 屬性名稱不要以new開頭频鉴,方法名也是栓辜。
45. 類工廠方法(也稱快速創(chuàng)建方法):類工廠方法是一種用于分配,初始化實例并返回一個它自己的實例的方法垛孔,類工廠方法很方便藕甩,因為他們允許您只使用一個步驟就能創(chuàng)建對象 ? 。 ? 例如:new
自定義類工廠方法:1周荐,一定是+號開頭 2狭莱,返回值一般是instancetype類型或id 3,方法名稱以類名開頭概作,首字母小寫腋妙。
+(instancetype)persionWithAge:(int)age
{
Persion *p = [[Person alloc]init];? p.age = age;? ? return p;//注意:在類工廠方法中一定不要使用類名來創(chuàng)建對象,要使用self來創(chuàng)建對象讯榕。self在方法中就代表類對象? Persion *p = [[self alloc]init];
}
類的本質:類其實也是一個對象骤素,這個對象會在這個類第一次被使用的時候創(chuàng)建,只要有了類對象愚屁,將來就可以通過類對象來創(chuàng)建實力對象济竹,實例對象中有一個isa指針,指向創(chuàng)建自己的類對象霎槐。 ?類對象中保存了當前所有的對象方法送浊,當給一個實力對象方法消息的時候,會根據(jù)實例對象中的isa指針去對應的類對象中查找丘跌。類對象代表類袭景,Class類型,對象方法屬于類對象 ? 如果詳細的接收者是類名闭树,則類名代表類對象耸棒,所有類的實例都由類對象生成。
獲取類對象:Class c = [對象/實例對象 class];//一個類在內存中只有一份類對象蔼啦。
類對象的使用場景:【c alloc】init]榆纽;[c text];
1. 用于創(chuàng)建實例對象,2捏肢,用于調用類方法。
46. 只要程序啟動就會將類的代碼加載到內存中饥侵,放到代碼區(qū)鸵赫。 ?load方法會在當前類被加載到內存的時候調用,有且僅會調用一次 ? ? 會自動被調用
47. +(void)initialize{} 當前類第一次被使用的時候就會調用(創(chuàng)建類對象的時候)只會被調用一次
48. SEL 類型作用躏升,配合對象類來檢查對象或類中有沒有實現(xiàn)某一個方法
SEL sel = @selector(text);
BOOL flag = [Person respondsToSelector:sel];//對用類方法
Person *p = [Person new]; ? BOOL flag = [p respondsToSelector:sel];//調用類方法
49. 內存管理:創(chuàng)建一個對象辩棒,定義一個變量,調用一個函數(shù)或方法,都會增加app的內存占用一睁。 ? 所謂內存管理就是分配內存(增加內存占用)和清除內存(減小內存占用)
內存管理的范圍:任何繼承了NSObject的對象钻弄,對其他非對象類型無效(char,float,double,struct,enum等)
只有oc對象才需要進行內存管理的本質原因:oc對象存儲于堆里面 ? 非oc對象一般放在棧里面(棧內存會被系統(tǒng)自動回收)
50. dealloc ?重寫dealloc,在這里釋放相關資源者吁, ?一旦重寫了dealloc就必須調用【super dealloc】窘俺,并且放在寫在代碼最后. ? ?
注意:不能直接調用dealloc方法,一旦對象被回收了复凳,它占用的內存就不在可用瘤泪,堅持使用會導致程序崩潰(出現(xiàn)野指針錯誤)
51. 在ARC模式下是編譯器幫你釋放內存的 java是系統(tǒng)幫你清理內存的 ?一個引用計數(shù)器占用4個字節(jié)
52. 野指針和空指針:
只要一個對象被釋放了,我們就稱為僵尸對象育八,稱這個指針為野指針对途,只要給一個野指針發(fā)送消息就會報錯。(用棧區(qū)中的指針去訪問堆區(qū)中的對象就會崩潰 ?髓棋, ?找不到可以使用的對象)一般情況下实檀,在對象被釋放后,會把指針設置為空指針按声,給空指針發(fā)送一個消息不會崩潰劲妙、(nil ?0) ? p = nil;
53. 分類是用于給原有類添加方法的,不能添加屬性 ?儒喊, ?分類中的@property ?只會生成setter镣奋、getter方法的聲明,不會生成實現(xiàn)以及私有的成員變量 ?怀愧, ?可以在分類中訪問原有類的.h中的屬性
54. 類擴展:類擴展是分類的一個特例侨颈, ?對比分類來說,就少了一個分類名稱芯义,因此也有人稱他為“匿名分類” ?extension
55. property修飾符:retain會自動幫我們生成set方法內存管理的代碼哈垢, assign:不會幫我們生成set方法內存管理的代碼,僅僅只會生成普通的getter/setter方法扛拨,默認什么都不會就是assgin. ? ?相同類型的修飾符不能再一起使用 ?比如retain和assign
atomic ?和 nonatomic 用于多線程中 ?耘分,atomic性能低,nonatomic性能高一般情況下不會用atomic绑警。 ? 在ios開發(fā)中求泰,只要寫property ?后面就跟上nonatomic ? 來提高性能。
56. @class ?和 @“import” ?的區(qū)別:
由于import是一個預編譯指令计盒,他會將“”中的文件拷貝到import所在的位置渴频,并且import有一個特點,只有“”中的文件發(fā)生了變化北启,那么import就會重新拷貝一次(做更新操作) ?@class僅僅是告訴編譯器卜朗,有一個這個類拔第,不會做任何的拷貝操作逛万。 ?注意:由于@class僅僅是告訴編譯器后面的名稱就是一個類泣港,所以編譯器并不知道這個類中有哪些屬性和方法坡氯,所以在.m中使用類的使用,需要import這個類才可以使用哦. ?相互使用類的時候涮毫,可以用@class(避免相互拷貝,產生報錯)
57. block ?用來保存一段代碼 ?block是一個變量恬叹, ?是變量結尾就要有;結束符號
block注意事項:1.block中可以訪問外面的變量疏魏。2只厘,block中可以定義和外界同名的變量忘蟹,并且如果在block中定義了和外界同名的變量褥芒,在block中訪問的是block中的變量少辣,3,默認情況下爱葵,不可以在block中修改外界變量的值赞哗,因為blcok中的變量那個和外界的變量并不是同一個變量雷则,如果block中訪問到了外界的變量藤乙,block會將外界的變量拷貝一份到堆內存中送丰。 因為block中使用的外界變量是copy的,所以在調用之前修改外界變量的值器躏,不會影響到block中copy的值遏佣。 ?如果想在block中修改外界變量的值,必須在外界變量前面加上__block ,加完之后揽浙,如果在block中修改變量的值状婶,會影響外界變量的值。內外部的兩個變量的地址是不一樣的馅巷,只是指針之間值得傳遞膛虫。
為什么不加__block就不能修改外界變量的值,為什么加了之后就可以修改外面的值:加上就是地址傳遞钓猬,所以可以在block中修改外界變量的值稍刀,不加的話是值傳遞;敞曹。
默認情況下block存儲在棧中账月,如果對block進行一個copy操作综膀,block會轉移到堆中,如果block在棧中捶障,block中訪問了外界的對象僧须,那么不會對對象進行retain操作纲刀, ?但是如果block在堆中项炼, ?block中訪問了外界的對象,那么會對外界的對象進行一次retain示绊。
58. Protocol ?協(xié)議:是用來創(chuàng)建方法的锭部,只有方法的聲明,沒有方法的實現(xiàn)面褐。
協(xié)議和繼承的區(qū)別:1.繼承之后默認就有實現(xiàn)拌禾,而protocol只有聲明沒有實現(xiàn)。 2.相同類型可以使用繼承展哭,但是不同而理性的類只能使用protocol湃窍。3.protocol可以用于存儲方法的聲明,可以將多個類中共同的方法抽取出來匪傍,以后讓這些類遵守協(xié)議方法即可您市。
父類遵守了某個協(xié)議,那么子類也會自動遵守這個協(xié)議役衡。 ? ? 在oc中一個類可以遵守一個或多個協(xié)議茵休,oc中只能繼承一個父類。?
OC中的協(xié)議有可以遵守其他協(xié)議手蝎,只要一個協(xié)議遵守了其他協(xié)議,那么這個協(xié)議中就會自動包含其他協(xié)議的聲明。
NSObject是一個基類肄渗,任何其他類最終都要繼承它 ?有一個NSObject的協(xié)議缓升,它是一個基協(xié)議,最根本最基礎的協(xié)議邮辽。
@required:被它修飾的協(xié)議方法必須實現(xiàn)唠雕,不實現(xiàn)編譯器會發(fā)出警告
@optional:被它修飾的不一定要實現(xiàn)。
59. 協(xié)議的應用場景逆巍,可以將協(xié)議寫在數(shù)據(jù)類型的右邊及塘,那么對象必須遵守某個協(xié)議。 ? ?例如:Person<Protecol> *p = [Person new];
聲明屬性的時候屬性右邊也可以使用锐极。
在運用協(xié)議的時候笙僚,注意事項:雖然在接受某一個對象的時候,對這個對象進行了類型限定灵再,限定它必須實現(xiàn)某個協(xié)議肋层,但是并不意味著這個對象就真正的實現(xiàn)了該方法亿笤,所以每次在調用對象的協(xié)議方法時應該進行一次驗證。例如:
if([self.wife respondsToSelector:@selector(cooking)]){
[self.wife cooking];//如果有這個方法栋猖,就執(zhí)行里面的操作
}
60. 設計模式:設計模式是一套被反復使用净薛,多數(shù)人知曉的,經過分類編目的蒲拉,代碼設計經驗的總結肃拜,使用設計模式是為了可重用代碼,讓代碼更容易被他人理解雌团,保證代碼的可靠性燃领。
代理設計模式:比如我們買一包紙,不需要去制造廠去買锦援,去超市去買猛蔽,超市就是一種代理模式。
代理模式的應用場合:例如對象A和B灵寺,當A對象想監(jiān)聽B對象的一些變化時曼库,可以使用代理設計模式,當B對象發(fā)生一些事情略板,想通知A對象的時候毁枯,可以使用代理設計模式。
協(xié)議的編寫規(guī)范:1.一般情況下蚯根,當前協(xié)議屬于誰后众,我們就將協(xié)議定義到誰的頭文件中 2,協(xié)議的名稱一般以他屬于的那個類的類名開頭颅拦,后面跟上protocol或者delegate 3蒂誉,協(xié)議中的方法名稱一般以協(xié)議的名稱Protocol之前的作為開頭 4,一般情況下距帅,協(xié)議中的方法右锨,會將出發(fā)該協(xié)議的對象傳遞出去 5、一般情況下碌秸,一個類中的代理屬于的名稱叫做 delegate 6绍移、當有一個類中要稱為另外一個類的代理的時候,一般情況下在.h中用@protocol協(xié)議名稱讥电,告訴當前類這是一個協(xié)議 ? 在.m中用#import導入一個協(xié)議的聲明
61. Fundation簡介
框架:眾多應用程序的結合蹂窖,框架是由許多類,方法恩敌,函數(shù)瞬测,文檔在按照一定的邏輯組織起來的集合,以便使研發(fā)程序變得更容易。在OSX下mac大概有80個框架為所有程序開發(fā)奠定基礎的框架稱為Fondation框架月趟。
Fundation框架中大約有125個可用的頭文件灯蝴。是其他框架開發(fā)的基礎,包含了許多常用的數(shù)據(jù)類型:結構體孝宗,枚舉穷躁,類。
Fundation框架中的類都是以NS為前綴(Next Step的縮寫 ?是85年喬布斯離開蘋果公司創(chuàng)立的NeXT公司)這個框架是以前在NeXT公司寫NeXT的框架因妇。
對電腦文件顯隱:defaults write com.apple.finder AppleShowAllFiles -bool True ? 在終端中進行顯示和隱藏的操作 问潭, ?操作后一定要重新啟動Finder
62. 字符串基本概念:
創(chuàng)建字符串的方法:1.通過字符串常亮創(chuàng)建 2,通過alloc init創(chuàng)建 3沙峻,通過類工廠方法創(chuàng)建/ stringWithFormart ? 不同的創(chuàng)建方法所存儲的位置不一樣 ? 第一種存儲在常量去 ?下面兩種存儲在堆區(qū)
但是如果是通過alloc initWithString方法除外睦授,因為這個方法是通過copy返回一個字符串對象給我們,而copy又分為深拷貝和淺拷貝摔寨,如果是深拷貝會創(chuàng)建一個新的對象,如果是淺拷貝不會創(chuàng)建一個新的對象怖辆,而是直接返回被拷貝的對象的地址給我們是复,二initWithString正好是淺拷貝,所以無論是在什么平臺竖螃,什么編譯器都是指向同一塊存儲空間淑廊。
63. 字符串的讀取和寫入:
1、NSString *str = [NSString stringWithContentOfFile:path encoding:NSUTF8StringEncoding error:&error];
2特咆、BOOL flag = [str writeToFile:path atomically:YES encoding:NSUTF8StringEncoding error:nil];
64. 分類是用于給所有類添加方法的季惩,他只能添加方法,不能添加屬性(成員變量)腻格,分類中的@property画拾,只會生成setter/getter方法的聲明,不會生成實現(xiàn)以及私有的成員變量菜职∏嗯祝可以在分類中原有類中.h中的屬性
65. 對url的讀寫,如果url中有中文酬核,需要用【NSURL fileURLWithPath:@"fsfsd"】;進行編碼讀寫
66. 字符串進行比較:str isEqualToString:str2 ? 或者 ?str == str2 ? 前者是比較內容是否相等蜜另,后者是比較地址手否相同。
第三種方法用switch進行判斷:
str compare: str2 ? 有三種結果嫡意,是一個枚舉值举瑰,NSOrderAscending ? NSOrderedSame ? NSOrderedDescending ? 升序 ? 相等 ?降序 ?另外一種方法是忽略大小寫就行比較的 ?caseInsensitveCompare ?和第三種方法 比較的方法是一樣的。
67. 字符串搜索:判斷以什么開頭蔬螟,判斷以什么結尾 ?hasPrefix ? hasSuffix ? . ? ?還有一個字符串包含:rangeOfString:返回值是NSRange ?這個包含字符串的起始位置和長度,如果沒有要查詢的結果此迅,返回的長度為0,字符串的其實位置為NSNotFound
68. 只要是OC提供的結構體一般都是NSMakeXXX ? ? ?{x,x } ?
int和NSInteger其實是差不多的,但更推薦使用NSInteger邮屁,因為使用NSInteger,這樣就不用考慮設備是32位還是64位了整袁。
NSUInteger是無符號的,即沒有負數(shù),NSInteger是有符號的佑吝,所以NSUInteger類型不能給它賦負值坐昙。比如for循環(huán)的時候,a=-1的時候,是能進入循環(huán)的芋忿。
69. 字符串截日汀:1.動態(tài)獲取截取的起始位置,2戈钢,動態(tài)獲取截取的長度 痹仙。 ?
str = @"<head>麥迪文</head>";
NSUInteger location = [str rangeOfString:@">"].location + 1;
NSUInteger length = [str rangeOfString:@"<" options:NSBackwardSearch].location - location;//從字符串后面往前找
NSRange range = NSmakeRange(location,length);
70. 字符串截取:【str stringByReplacingOccurrencesOfString:@"xx"】殉了;
替換首位:str = @"sfdsfdsfdsf";
NSCharacterSet *set = [NSCharacterSet whitespaceCharacterSet];?
newStr = [str stringByTrimmingChatactersInSet:set];
71. 字符串轉換:【str uppercaseString】轉換成大寫 ? 【str lowercaseString】轉換成小寫开仰;
將字符串首字母轉換為大寫 ? 【str capitalizedString】;
【str deleteCharactersInRange:range】薪铜;//刪除指定的字符串
72. NSMutableString: 繼承于NSString ??
對于不可變字符串众弓,每次改變內容的時候都是創(chuàng)建一個新的對象。地址會改變
可變字符串:每次修改都是添加到同一個地址位置隔箍。
73. NSArray ?
NSArray *arr = [NSArray arrayWithObject:@"2",@"2",nil];//nil ?是一個結束符
快速創(chuàng)建數(shù)組:NSArray *arr = @[@“1”谓娃,@“3”]; // 和上面的意義一樣
查找數(shù)組中是否包含了某一個元素 ?
【arr containsObject:@"33"】;//返回值布爾值
oc中經常使用的三種遍歷:1.for循環(huán)的基本遍歷 2.forin遍歷 (for循環(huán)的增強版)3. 利用oc數(shù)組的迭代器遍歷也就是block遍歷
[arr enumerateObjectsUseingBlock:........];//返回值有三個參數(shù):1蜒滩,元素(obj)滨达,2,索引(idx) 3俯艰,*stop (用于控制循環(huán)停止在某一個地方)
如果使用oc數(shù)組存儲對象捡遍,可以調用oc數(shù)組的方法讓數(shù)組中所有的元素都執(zhí)行指定的方法
【arr makeObjectPerformSelector:@selector(say)】;//say是一個對象或者類方法
makeObjectPerformSelector:@selector(say:) withObject:@"ss"】蟆炊;//需要傳遞給調用方法的參數(shù)
注意點:如果數(shù)組中保存的不是相同類型的數(shù)據(jù)稽莉,并且沒有相同的方法,那么會報錯.
對數(shù)組進行排序:[arr sortArrayUsingSelector:@selector(compare:)];
//注意:想使用compare方法對數(shù)組中的元素進行排序涩搓,那么數(shù)組中的元素必須是Fondation框架中的對象污秆,也就是說不能是自定義的對象。
如果想調用自定義對象:需要使用
【arr sortedArrayWithOptions:NSSortStable usingComparator:....】昧甘;
返回obj1和obj2對象 ?進行比較 ?return obj1>obj2 ?或者相反
&&&&&&&冒泡排序
NSMutableArray *array = [NSMutableArray arrayWithObjects:@"12",@"84", @"35", @"70", @"85", @"99", nil];
NSInteger count = [array count];
for (int i = 0; i < count; i++) {
for (int j = 0; j < count - i - 1; j++) {
// if ([[array objectAtIndex:j] intValue] > [[array objectAtIndex:(j + 1)] intValue]) {? //這里在用[array objectAtIndex:j]時候必須intValue
//? ? ? ? ? ? ? ? if([[array objectAtIndex:j] compare:[array objectAtIndex:j + 1]] == -1){? //這里整體必須有一個返回值良拼,-1,0充边,1庸推,因為compare的返回值NSComparisonResult是一個枚舉類型的值常侦,所以要返回一個值
if([[array objectAtIndex:j] compare:[array objectAtIndex:j + 1] options:NSNumericSearch] == 1){? //同上potions? NSNumericSearch = 64,
[array exchangeObjectAtIndex:j withObjectAtIndex:(j + 1)];? //這里可以用exchangeObjectAtIndex:方法來交換兩個位置的數(shù)組元素。
}
}
}
for (NSString *i in array) {
NSLog(@"%@", i);
}
74. NSArray和NSString轉換
將數(shù)組中的元素進行連接起來:【arr compontentsJoinedByString:@"-"】贬媒;
通過一個字符串生成一個數(shù)組:也叫作字符串切割
str = @"33*44*55*56";
[str componentSwparatedByString:@"*"];
75. NSArray文件讀寫:
arr = @[@"2",@"3"];
BOOL flag = [arr writeToFile:@"路徑.plist" atomically:YES];//將數(shù)組寫入到文件中聋亡,其實如果講一個數(shù)組寫入到文件中會后,本質是戲寫入了一個XML文件 ?际乘, ?在iOS開發(fā)中一般情況下我們會將XML文件的擴展名保存為plist
從文件中讀取一個數(shù)組:
arr = [NSArray arrayWithContentOfFile:@"路徑"];
注意:write方法只能寫入數(shù)組中保存的元素都是Fundation中的方法坡倔,不能寫入自定義的元素。
76. NSMutableArray:
其實可變的數(shù)組脖含,字符串罪塔,字典都是不可變數(shù)組,字符串养葵,字典的子類征堪。
注意:不能通過@【】來創(chuàng)建一個可變數(shù)組,因為用@【】創(chuàng)建出來的是一個不可變的數(shù)組关拒,如果把一個不可變數(shù)組當做一個可變數(shù)組開使用佃蚜,會引發(fā)一個運行時的錯誤。
77. NSDictionary:
對字典進行forIn遍歷 ?對打印出所有的key
最方便的遍歷使用block進行遍歷
字典保存的數(shù)據(jù)是無序的
78. NSMutableDictionary:
不能使用@{}來創(chuàng)建可變字典 ?如果是不可變數(shù)組夏醉,那么key不能相同
NSArray是通過下標來訪問元素爽锥,NSDictionary是通過key值來訪問元素(因為它是無序的)
79. 常用結構體:
NSPoint和CGPoint NSSize和CGSize NSRect和CGRect ?這三個結構體是OC中常用的。這是三個結構體畔柔,只是有三個別名。
在蘋果開發(fā)中臣樱,蘋果推薦我們使用CG開頭的結構體靶擦,也就是說NS開頭的結構體一般不用.
80. NSNumber:
數(shù)組和字典都只能存放對象類型的數(shù)據(jù),基本數(shù)據(jù)類型存放會報錯雇毫。如果想存儲基本數(shù)據(jù)類型玄捕,需要將基本數(shù)據(jù)轉換成對象類型:
例如: NSNumber *num = [NSNumber numberWithInt:age]; ? 或者使用快速轉換的方法:NSNumber *num = @(int); ?如果傳入的是常量則不需要使用圓括號。
81. NSValue:
NSValue是NSNumber的父類
如果想包裝基本數(shù)據(jù)類型以外的類型棚放,可以使用NSValue枚粘。 ? NSValue中有很多方法,比如可以轉換常用的基本結構體飘蚯,如果想轉換自定義結構體可以使用:
NSValue *value = [NSValue valueWithBytes:&p objCType:@encode(Person)];//Person是自定義的結構體 ? ?&p是傳入的指針 @encode是把自定義結構體對象轉化成指針馍迄。 ?如果想獲取自定義結構體中的變量:【value getValue:&p】;//Person *p;
82. NSDate:
NSDate *now = [NSDate date];//獲取當前的時間
NSTimeZone *zone = [NSTimeZone systemTimeZone]; ?//獲取當前所處的時區(qū)
NSInteger seconds = [NSInteger secondsFromGMTForDate:now];//獲取當前時區(qū)和指定時間的時間差
NSDate *newDate = [now dateByAddingInterval:seconds];//在now的基礎上增加了多少秒
newDate就是獲取的當前時區(qū)的正確時間局骤。
時間格式化:NSDateFormatter?
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
formatter.dataFormatter = @"yyyy年MM月dd日 HH時mm分ss秒 z";
formatter.dataFormatter = @"yyyy-MM-dd HH-mm-ss";
利用時間格式化對象對時間進行格式化:
NSString *str = [formatter stringFromDate:[NSdate date]];
//注意: 如果是從NSString格式化為NSDate攀圈,那么dateFormat的格式,必須和字符串中的時間格式一致峦甩,否則可能轉化失敗赘来。
NSString *str = @"2016-12-12 07:30:20";
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
formatter.dateFormat = @"yyyy-MM-dd HH:mm:ss";
NSDate *date = [foramtter dateFormString:str];
83. NSCalendar:
NSDate *now = [NSDate date];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSCalendarUnit type = NSCalendarUnitYear | NSCalendarMonth;
NSDateComponents cmps = [calendar components:type formDate:now];
nslog(@"%@%@",cmps,year,cmps.month);
比較兩個時間:
NSDateComponents *cmps = [calendar components:type fromDate:date toDate:now options:0];
84. NSFileManager:
NSFileManager *manager = [NSFileManager ?defauleManager];
BOOL flag = [manager fileExistsAtPath:@""];//判斷一個文件或者文件夾是否存在
BOOL dir = NO;//默認為NO
BOOL flag = [manager fileExistsAtPath:@"" isDirectory:$dir];//判斷一個文件是否存在,并且判斷它是否是一個文件夾, ?第一個參數(shù)是路徑犬辰,第二個參數(shù)返回的是判斷這個路徑是否是一個文件夾嗦篱。
獲取文件或文件夾的屬性:
[manager attributesOfItemAtPath:@"" error:nil];
獲取文件夾中所有的文件
【manager contentsOfDirectoryAtPath:@"" error:nil】;
也可以創(chuàng)建文件夾和文件方法幌缝,自己去找createFile.........
85. 集合中對象的內存管理
1.如果將一個對象添加到一個數(shù)組中灸促,那么數(shù)組會對對象進行一個retain ??
2. 當數(shù)組對象釋放之后,會給數(shù)組中所有的對象發(fā)送一條release消息
3. 當數(shù)組移除一個對象之后狮腿,會給這個對象發(fā)送一條release消息
86. copy 基本使用:
NSString *str = @"uio";
NSMutableString *copy = [str mutableCopy];
只要是拷貝出來的對象腿宰,拷貝出來的對象中的內容一致,一般情況下拷貝會生成一個新的對象缘厢,為什么會產生一個新的對象(因為拷貝要求修改原來的對象吃度,不能影響到拷貝出來的對象 ? 修改拷貝出來的對象也不能影響到原來的對象,所以需要生成一個新的對象 ?由于以前的對象是一個不可變的對象贴硫,而通過nutableCopy拷貝出來的對象必須是一個可變的對象椿每,所以必須生成一個新的對象)
如果通過不可變對象調用了copy方法,那么不會生成一個新的對象英遭,原因:(因為原來的對象是不能修改的间护,拷貝出來的對象也是不能修改的,既然兩個都不能修改挖诸,所以永遠不能影響到另一個對象汁尺,那么已經符合需求,所以OC為了對內存進行優(yōu)化多律,就不會生成一個新的對象)
正是因為調用copy方法:有時候會生成一個新的對象痴突,有時候不會生成一個新的對象,所以:如果沒有生成新的對象狼荞,我們稱之為淺拷貝辽装,本質就是指針拷貝。如果生成了新的對象相味,我們稱之為深拷貝拾积,本質就是會創(chuàng)建一個新的對象。
對于內存的管理: ?如果是淺拷貝:不會生成新的對象丰涉,但是系統(tǒng)就會對原來的對象進行retain拓巧,所以需要對原來的對象進行一次release。 ? 如果是深拷貝:會生成新的對象昔搂,系統(tǒng)不會對原來的對象進行retain玲销,但是因為生成了新的對象,所以我們需要對新的對象進行release
87. ?對于property中的修飾符摘符,如果修飾字符串的話贤斜,就用copy避免了修改原對象或新對象的值影響被拷貝對象中的內容策吠,如果用retain進行修飾的話,修改了一個對象就會對原對象或者新對象的內容產生影響瘩绒。
88. copy的用途:1.防止外界修改內部的數(shù)據(jù)猴抹。2. block默認存儲在棧中,棧中的block訪問到了外界的對象锁荔,不會對對象進行retain蟀给,block如果在堆中,如果在block中訪問了外界的對象阳堕,會對外界的對象進行一次retain跋理。 使用Block_copy(myBlock),就是將block轉移到堆中。 ? 3.如果使用copy保存block恬总,這樣可以保住block中使用的外界對象的命前普,避免以后調用block的時候,外界的對象已經釋放了壹堰。
89. copy block之后引發(fā)循環(huán)引用 ?如果對象中的block又用到了對象自己拭卿,那么為了避免內存泄漏,應該講對象修飾為__block
90. 自定義類實現(xiàn)Copy(讓自定義的對象能夠被copy)
1. 需要遵守NSCopying協(xié)議
2. 需要實現(xiàn)協(xié)議方法:-(id)copyWithZone:(NSZone *)zone{ ?};
91. 單例:
由于所有的創(chuàng)建方法都會調用allocWithZone:贱纠,所以只需要在該方法中控制當前對象值創(chuàng)建一次即可峻厚。
設置一個靜態(tài)的對象 ?。 ? 使用代理每次創(chuàng)建對象的時候都是同一個地址谆焊。相當于永遠之創(chuàng)建同一個對象惠桃。 ? 只有程序銷毀的時候,這塊對象才會被釋放辖试。
\ ?表示換行
單例的優(yōu)缺點:
單例模式的優(yōu)缺點
1刽射、時間和空間
比較上面兩種寫法:懶漢式是典型的時間換空間,也就是每次獲取實例都會進行判斷剃执,看是否需要創(chuàng)建實例,浪費判斷的時間懈息。當然肾档,如果一直沒有人使用的話,那就不會創(chuàng)建實例辫继,則節(jié)約內存空間怒见。
餓漢式是典型的空間換時間,當類裝載的時候就會創(chuàng)建類實例姑宽,不管你用不用遣耍,先創(chuàng)建出來,然后每次調用的時候炮车,就不需要再判斷了舵变,節(jié)省了運行時間酣溃。
2、線程安全
(1)從線程安全性上講纪隙,不加同步的懶漢式是線程不安全的赊豌,比如,有兩個線程绵咱,一個是線程A碘饼,一個是線程B,它們同時調用getInstance方法悲伶,那就可能導致并發(fā)問題艾恼。如下示例:
public static? Singleton getInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
程序繼續(xù)運行,兩個線程都向前走了一步麸锉,如下:
public static? Singleton getInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}