iOS基礎(chǔ)
-
分類(Category)和類擴展(Class Extension)
分類(Category)
Category,是表示一個指向分類的結(jié)構(gòu)體的指針,其定義如下: typedef struct objc_category *Category; struct objc_category { char *category_name OBJC2_UNAVAILABLE; // 分類名 char *class_name OBJC2_UNAVAILABLE; // 分類所屬的類名 struct objc_method_list *instance_methods OBJC2_UNAVAILABLE; // 實例方法列表 struct objc_method_list *class_methods OBJC2_UNAVAILABLE; // 類方法列表 struct objc_protocol_list *protocols OBJC2_UNAVAILABLE; // 分類所實現(xiàn)的協(xié)議列表 } 分類的結(jié)構(gòu)體成員:分類名、分類所屬的類名、實例方法列表、類方法列表、分類所實現(xiàn)的協(xié)議列表。 發(fā)現(xiàn),該結(jié)構(gòu)體包含了分類定義的實例方法與類方法,但結(jié)構(gòu)體里沒有屬性列表。 注:(Category局限性上) 1.Category,原則上只能添加方法,不能添加屬性,實際上可以通過其他方式添加屬性; 2.分類中可以寫 @property,但不會聲明及實現(xiàn)setter/getter; 3.分類的優(yōu)先級最高,如果方法名與原有類同名,則會優(yōu)先調(diào)用分類中的方法,優(yōu)先級順序 分類>本類>父類; 延伸問題: 為什么在分類中聲明屬性時運行不會報錯? or 為什么分類中使用@property仍然可以編譯通過? 答:一個類中使用@property聲明屬性,編譯器會自動生成 _成員變量和setter/getter。 但分類結(jié)構(gòu)體中沒有屬性列表,所以不會自動生成 _成員變量 和 setter/getter。 因此使用@property編譯和運行都不會報錯,一旦使用 _成員變量 或 setter/getter,就會報錯。 可不可以手動實現(xiàn)setter/getter方法來避免崩潰? 答:可以的,OC是動態(tài)語言,可以通過runtime添加 setter/getter方法。 objc_setAssociatedObject(),動態(tài)實現(xiàn)setter方法,objc_getAssociatedObject(),動態(tài)實現(xiàn)getter方法。
類擴展(Class Extension)
Extension 是 Category 的一個特例。格式: @interface XXX () //私有屬性 //私有方法(如果不實現(xiàn),編譯時會報警,Method definition for 'XXX' not found) @end
分類和類擴展的區(qū)別
1.Category原則上只能增加方法(可通過runtime解決增加屬性的問題); 2.Extention可增加方法和屬性,只是該屬性是@private類型,作用范圍是自身; 3.Category是運行時添加到類中,Extension是編譯時添加到類中。
-
atomic 和 nonatomic
使用@property聲明屬性時,會使用atomic/nonatomic關(guān)鍵字 atomic 和 nonatomic 區(qū)別在于系統(tǒng)自動生成setter/getter方法不一樣 atomic 系統(tǒng)自動生成的setter/getter方法會進行加鎖操作; nonatomic 系統(tǒng)自動生成的setter/getter方法不會進行加鎖操作。
atomic
系統(tǒng)生成的setter/getter方法進行加鎖操作,但這個鎖,僅僅保證了setter/getter存取方法的線程安全。 因加鎖的緣故,其他線程要讀取這個屬性時,會先執(zhí)行完當前操作。 延伸問題: atmoic是線程安全嗎? 答:atomic只是對屬性的setter/getter方法進行加鎖操作,僅僅是set/get的讀取安全,并非真正的線程安全,線程安全還有讀取之外的其 他操作。 (比如:當一個線程正在setter/getter時,有另一個線程 同時進行release操作,這時可能導致crash)
nonatomic
系統(tǒng)生成的setter/getter方法沒有進行加鎖操作,讀取時不安全,但速度更快,當多個線程同時訪問同一屬性時,會出現(xiàn)無法預(yù)料的結(jié)果。
atomic和nonatomic的使用選擇
atomic能夠保證setter/getter操作的安全性,但是相對nonatomic更耗費資源,且速度更慢,因此如果沒有多線程之間通信操作的情況下,使用nonatomic更好。
-
Objective-C是一門動態(tài)語言
動態(tài),不需要再編譯時確定所有的東西,在運行時可以動態(tài)添加變量、屬性、方法、類。Objective-C可以通過runtime,在運行時動態(tài)的添加變量、屬性、方法、類,所以說Objective-C是一門動態(tài)語言。 動態(tài)性體現(xiàn): 1.動態(tài)類型。如id類型。靜態(tài)類型因固定性和可預(yù)知性而使用廣泛。靜態(tài)類型是強類型,而動態(tài)類型是弱類型,運行時決定接收者; 2.動態(tài)綁定。讓代碼在運行時判斷需要調(diào)用的方法,而不是在編譯時。與其他面向?qū)ο笳Z言一樣,方法調(diào)用和代碼并不是在編譯時連接在一起,而是在消息發(fā)送時連接,運行時決定調(diào)用哪個方法; 3.動態(tài)載入。程序在運行時添加代碼模塊及資源。用戶可根據(jù)需要加載可執(zhí)行代碼和資源,而不是啟動時家在所有組件。可執(zhí)行代碼中可以含有和程序運行時整合的新類。
-
weak、strong、assign
由ARC引入 weak相當于OC中的assign,但是weak只能修飾OC對象,而assign可用于非OC對象,但是它們都不會造成引用計數(shù)+1; strong相當于OC中都retain,會造成引用計數(shù)+1。 ARC,引用計數(shù)機制,OC的內(nèi)存管理機制。其原理:還要還有一個變量指向?qū)ο螅瑢ο缶蜁3衷趦?nèi)存中。 當指針指向新值,或者指針不存在時,相關(guān)聯(lián)的對象就會自動釋放。
strong
strong指針是強引用,能夠保持對象的生命,一個對象只要有strong指針指向它就不會被釋放; 相反,如果沒有一個strong指針指向它,那么它將自動釋放。 默認所有實例變量和局部變量都是strong指針。
weak
weak指針是弱指針,同樣可以指向一個對象,但是不是該對象的擁有者。即當對象銷毀時,weak指針自動指向nil(空指針)。 這樣避免了指針繼續(xù)指向已釋放對象,進而避免了野指針的出現(xiàn)。 延伸問題: IBOutlet連出來的視圖屬性為什么用weak修飾?那些控件對象不會自動釋放嗎? 如:@property (nonatomic, weak) IBOutlet UIButton *button; 答:xib創(chuàng)建或放置控件時,存在該引用關(guān)系: UIViewController->UIView->subviews->UIButton UIView持有了subviews(強引用),所以這里可以使用weak來修飾。 為什么代理要用weak修飾? 答:防止循環(huán)引用。 如:控制器的view強引用這UITableView,而tableview的delegate又是控制器。 如果不用weak,Controller->View->delegate-> Controller,就造成了循環(huán)引用。
assign
assign主要用于修飾基本數(shù)據(jù)類型,如NSInteger,CGFloat等,存儲在棧中,內(nèi)存不用程序員管理。
待更...