前言:面試筆試都是必考語法知識點。請認真復習和深入研究OC。
obje-c
1. 方法和選擇器有何不同?(Difference between method andselector?)
答:selector 只是一個方法的名字,method是一個組合體,包含了名字和實現(xiàn)。
2. Core Foundation的內(nèi)存管理
答: 1.凡是帶有Create、Copy、Retain等字眼的函數(shù),創(chuàng)建出來的對象,都需要在最后做一次release 2.比如CFRunLoopObserverCreate release函數(shù): CFRelease(對象);
【擴充]:
2.1 內(nèi)存管理 Autorelease、retain、copy、assign的set方法和含義?1).你初始化(alloc/init)的對象,你需要釋放(release)它。例如: NSMutableArray *aArray = [[NSArray alloc] init]; 后,需要 [aArray release]; 2).你retain或copy的,你需要釋放它。例如: [aArray retain] 后,需要 [aArray release]; 3).被傳遞(assign)的對象,你需要斟酌的retain和release。例如: obj2 = [[obj1 someMethod] autorelease]; 對象2接收對象1的一個自動釋放的值,或傳遞一個基本數(shù)據(jù)類型(NSInteger, NSString)時:你 或希望將對象2進行retain,以防止它在被使用之前就被自動 釋放掉。但是在retain后,一定要 在適當?shù)臅r候進行釋放。 <擴展> 關于索引計數(shù)(Reference Counting)的問題 retain值 = 索引計數(shù)(Reference Counting) NSArray對象會retain任何數(shù)組中的對象(索引計數(shù)值retain+1)。當NSArray被摧毀(dealloc)的時候, 所有數(shù)組中的對象會 被 執(zhí)行一次釋放(索引計數(shù)值retain值 -1)。 不僅僅是NSArray,任何收集類 (Collection Classes)都執(zhí)行類似操作。例如 NSDictionary, 甚至UINavigationController。Alloc/init建立的對象,索引計數(shù)為1。無需將其再次retain。 [NSArray array]和[NSDate date]等“方法”建立一個索引計數(shù)為1的對象,但是也是一個自動釋放對象。 所以是本地臨時對象,那么無所謂了。如果是打算在全Class中使用的變量(iVar), 則必須retain它。 缺省(系統(tǒng)默認的)的類方法返回值都被執(zhí)行了“自動釋放”方法。(*如上中的NSArray) 在類中“dealloc”方法中,release所有未被平衡(未被釋放)的NS對象。(所有未被autorelease, 而retain值為1的)
3. malloc和New的區(qū)別
答: 1.new是c++中的操作符,malloc是c中的一個函數(shù) 2.new 不止是分配內(nèi)存,而且會調(diào)用類的構造函數(shù),同理delete會調(diào)用類的析構函數(shù)。 而malloc則只分配內(nèi)存,不會進行初始化類成員的工作,同樣free也不會調(diào)用析構函數(shù)。 3.內(nèi)存泄露對于malloc或者new都可以檢查出來的,區(qū)別在于new可以指定哪個文件的哪一行,而malloc沒有這些消息。 4.new和malloc效率的比較高 5.new出來的指針是直接帶類型信息的。
參考文章: 細說new與malloc的10點區(qū)別
4. 你是否接觸過OC中的反射機制?簡單聊一下概念和使用
答: * class反射 1.通過類名的字符串形式實例化對象 Class class NSClassFromString@(@"student"); Student *stu = [[class alloc]init]; 2.將類名變?yōu)樽址? Class class = [Student class]; NSString *className = NSStringFromClass(class) * SEL的反射 1.通過方法的字符串形式實例化方法 SEL selector = NSSelectorFromString(@"setName") [stu performSelector:selector withObject:@"Mike"]; 2.將方法變成字符串 NSStringFromSelector(@selector*(setName:))
5. 什莫是SEL?如何聲明一個SEL?通過哪些方法能夠,調(diào)用SEL包裝起來的方法?
答: 1.SEL就是對方法的一種包裝。包裝的SEL類型數(shù)據(jù),它對應相應的方法地址,找到方法地址就可以調(diào)用方法。 在內(nèi)存中每個類的方法都存儲在類對象中,每個方法都有一個與之對應的SEL類型的數(shù)據(jù),根據(jù)一個SEL數(shù)據(jù) 就可以找到對應的方法地址,進而調(diào)用方法。 2.怎么包裝 SEL s1 = @selector(test1); //將test1方法包裝成SEL對象 SEL s2 = NSSelectorFromString(@"test1");// 將一個字符串方法轉換成SEL對象 3.調(diào)用方式 1)直接通過方法名來調(diào)用[person text]; 2) 間接的通過SEL數(shù)據(jù)來調(diào)用SEL aaa = @selector(text);[person performSelector:aaa];
6. 協(xié)議中<NSObject>是什莫意思?子類繼承了父類,那么子類會遵守父類的協(xié)議嗎?協(xié)議中能夠定義成員變量嗎?如何約束一個對象類型的變量要存儲的地址是遵守一個協(xié)議對象?
- 遵守NSObject協(xié)議 - 會 - 能,但是只在頭文件中聲明,編譯器是不會自動生成實例變量的。需要自己處理getter和setter。 - id <xxx>
7. NS/CF/CG/CA/UI這些前綴分別是什莫含義?
- NS-->函數(shù)歸屬屬于cocoa Fundation框架 - CF-->函數(shù)歸屬屬于core Fundation框架 - CG-->函數(shù)歸屬屬于Core Graphics.frameworks框架 - CA-->函數(shù)歸屬屬于CoreAnimation.frameworks框架 - UI-->函數(shù)歸屬屬于UIKit框架
8. 面向對象都有哪些特征以及你對這些特征的理解。
- 繼承:繼承是從已有類得到繼承信息創(chuàng)建新類的過程。提供繼承信息的類被稱為父類(超類、基類); 得到繼承信息的類被稱為子類(派生類)。繼承讓變化中的軟件有了一定的延續(xù)性,同時繼承 也是封裝程序中可變因素的重要手段。
- 封裝:*
封裝是把數(shù)據(jù)和操作的方法綁定起來,對數(shù)據(jù)的訪問只能通過已定義的接口。我們在類中編寫的 方法就是對實現(xiàn)細節(jié)的一種封裝;我們編寫一個類就是對數(shù)據(jù)和操作的封裝。可以說,封裝就是 隱藏一切可隱藏的東西,只向外界提供最簡單的編程接口。
- 多態(tài):
多態(tài)性是指允許不同的子類型的對象對同一消息做出不同的響應。簡單的說就是用同樣的對象引 用調(diào)用同樣的方法但是做了不同的事情。多態(tài)性分為編譯時的多態(tài)性和運行時的多態(tài)性。方法重載 (overload)實現(xiàn)的是編譯時的多態(tài)性(也稱為前綁定),而方法重寫(override)實現(xiàn)的是運行時的多 態(tài)性(也稱后綁定)。運行時的多態(tài)是面向對象最精髓的東西,要實現(xiàn)多態(tài)需要做兩件事情: 1.方法重寫(子類繼承父類并重寫父類中已有的或抽象的方法); 2.對象造型(用父類型引用子類型對象,這樣 同樣的引用調(diào)用同樣的方法就會根據(jù)子類對象的不同而表現(xiàn)出不同的行為)。
- 抽象:
抽象是將一類對象的共同特征總結出來構造類的過程。包括數(shù)據(jù)抽象和行為抽象兩方面。抽象只關注 對象有哪些屬性和行為,并不關注這些行為的細節(jié)是什莫。
9. 我們說的Objective-C是動態(tài)運行時語言是什莫意思?
- 主要是將數(shù)據(jù)類型的確定由編譯時,推遲到了運行時。這個問題其實淺涉及到兩個概念,運行時和多態(tài)。 - 簡單來說,運行時機制使我們直到運行時才去決定一個對象的類別,以及調(diào)用該類別對象指定的方法。 - 多態(tài):不同對象以自己的方式響應相同消息的能力叫多態(tài)。 - 意思就是假設生物類(life)都擁有一個相同的方法-eat;那人類屬于生物,豬也屬于生物,都繼承了life后, 實現(xiàn)各自的eat,但是調(diào)用是我們只需調(diào)用各自的eat方法。也就是不同的對戲那個以自己的方式響應了相同的 消息(響應了eat這個選擇器)。因此也可以這么說,運行時機制是多態(tài)的基礎。
10. readwrite, readonly, assign, retain, copy, nonatomic屬性的作用?
1) @property是一個屬性訪問聲明,擴號內(nèi)支持以下幾個屬性: 2) getter=getterName,setter=setterName,設置setter與 getter的方法名 3) readwrite,readonly,設置可供訪問級別 4).assign,setter方法直接賦值,不進行任何retain操作,為了解決原類型與環(huán)循引用問題。 用于非指針變量。用于基礎數(shù)據(jù)類型 (例如NSInteger)和C數(shù)據(jù)類型(int, float, double, char, 等), 另外還有id,其setter方法直接賦值,不進行任何retain操作. 5).retain,setter方法對參數(shù)進行release舊值再retain新值,所有實現(xiàn)都是這個順序(CC上有 相關資料) 6).copy,setter方法進行Copy操作,與retain處理流程一樣,先舊值release,再 Copy出新的 對象,retainCount為1。這是為了減少對上下文的依賴而引入的機制。 7).nonatomic,決定編譯器生成的setter getter是非原子操作,非原子性訪問,不加同步,多 線程并發(fā)訪問會??高性能。注意,如果不加此屬性,則默認是兩個訪問方法都為原子型事務訪 問。鎖被加到所屬對象實例級。 8).weak 用于指針變量,比assign多了一個功能,當對象消失后自動把指針變成nil,由于消息發(fā) 送給空對象表示無操作,這樣有效的避免了崩潰(野指針),為了解決原類型與循環(huán)引用問題 9).strong 用于指針變量,setter方法對參數(shù)進行release舊值再retain新值 - readwrite 是可讀可寫特性,需要生成getter方法和setter方法; - readonly 是只讀特性 只會生成getter方法 不會生成setter方法,不希望屬性在類外改變; - assign 是賦值特性,setter方法將傳入?yún)?shù)賦值給實例變量;僅設置變量;assign用于簡單數(shù)據(jù)類型,如NSInter,double,bool; - retain 表示持有特性,setter方法將傳入?yún)?shù)先保留,在賦值,傳入?yún)?shù)的引用計數(shù)器retaincount+1; - copy 表示賦值特性,setter方法將對象賦值一份;需要完全一份新的變量時; - nonatomic 非原子操作,決定編譯器生成的setter getter 是否是原子操作; - atomic 表示多線程安全,一般使用notatomic
11. 簡述NotificationCenter、KVC、KVO、Delegate?并說明它們之間區(qū)別(重點)
- KVO (Key-Value-Observing):
一對多,觀察者模式,鍵值觀察機制,它提供了觀察某一屬性變化,極大簡化了代碼。
- KVC(Key-Value-Coding):
鍵值編碼,一個對象在調(diào)用setValue的時候, ① 檢查是否存在相應key的set方法,存在就調(diào)用set方法。 ② set方法不存在,就查找_key的成員變量是否存在,存在就直接賦值。 ③ 如果_key沒找到,就查找相同名稱的key,存在就賦值。 ④ 如果沒有就調(diào)用valueForUndefinedkey和setValue: forUndefinedKey。
- Delegate:
通常發(fā)送者和接受者的關系是直接的一對一的關系。 ① 代理的目的是改變或者傳遞控制鏈。允許一個類在某些特定時刻通知到其他類,而不需要獲取到那些類的指針。 ② 可以減少框架復雜度。消息的發(fā)送者(sender)告知接受者(receive)某個事件將要發(fā)生,delegate后,發(fā)送者響應事件, delegate機制使得接收者可以改變發(fā)送者行為。
- Notification:
觀察者模式,通常發(fā)送者和接受者的關系是間接的多對多關系。 消息的發(fā)送者告知接收者事件已經(jīng)發(fā)生或者將要發(fā)送,僅此而已,接受者并不能反過來想想發(fā)送者的行為。
-區(qū)別:
① 就效率來說,delegate比NSNotification高。 ② delegate方法比notification更加直接,需要關注返回值,所以delegate方法往往包含should這個傳奇的詞。 相反的,notification最大的特色就是不關心結果。所以notification往往用did這個詞匯。 ③ 兩個模塊之間聯(lián)系不是很緊密,就用notification傳值,例如多線程之間傳值用notification。 ④ delegate只是一種較為簡單的回調(diào),且主要用在一個模塊中,例如底層功能完成了, 需要把一些值傳到上層去,就事先把上層的函數(shù)通過delegate傳到底層, 然后在底層call這個delegate,它們都在一個模塊中,完成一個功能, 例如說NavgationController從B界面到A點返回按鈕(調(diào)用popViewController方法) 可以用delegate比較好。
12. 懶加載 (What is lazy loading ?)
- 就是懶加載,只是在用到的時候才去初始化。也可以理解為延遲加載。 我覺得最好也是最簡單的一個例子,就是tableView中圖片的加載顯示, 一個延時加載,避免內(nèi)存過高,一個異步加載,避免線程堵塞提高用戶體驗。
13. OC有多繼承嗎?沒有的話可以用什莫方法替代
- 多繼承即一個子類可以有多個父類,它繼承了多個父類特性。 - Object-c的類沒有多繼承,只支持單繼承,如果要實現(xiàn)多繼承的話,可以通過類別和協(xié)議來實現(xiàn)。 - protocol (協(xié)議) 可以實現(xiàn)多個接口,通過實現(xiàn)多個接口可以完成多繼承。 - Category (類別) 一般使用分類,用Category去重寫類的方法,僅對本Category有效。不會影響到其他類與原有類的關系。
14. 分別描述類別(categories)和延展(extensions)是什莫?以及兩者的區(qū)別?繼承和類別在實現(xiàn)中有何區(qū)別?為什么category只能為對象添加方法,卻不能添加成員變量?
- 類別:在沒有原類 .m 文件的基礎上,給該類添加方法; - 延展:一種特殊形式的類別,主要在一個類的.m文件里聲明和實現(xiàn)延展的作用,就是給某類添加私有方法或是私有變量。 - 兩個的區(qū)別: ① 延展可以添加屬性并且它的方法都是不需實現(xiàn)的。延展可以認為是一個私有的類目。 ② 類別可以在不知道,不改變原有代碼的情況下往里面添加新的方法,只能添加,不能刪除修改。 ③ 并且如果類別和原來類中的方法產(chǎn)生名稱沖突,則類別將覆蓋原來的方法,因為類別具有更高的優(yōu)先級。 ④ 繼承可以增加,修改刪除方法,添加屬性。 - Category只能為對象添加方法,卻不能添加成員變量。原因:如果可以添加成員變量,添加的成員變量沒有辦法初始化。
15. Objective-C有私有方法嗎?私有變量呢?如沒有的話,有沒有什莫代替的方法?
- Objective-c類里面的方法只有兩種,靜態(tài)方法和實例方法。但是可以通過把方法的聲明和定義 都放在.m文件中來實現(xiàn)一個表面上的私有方法。有私有變量,可以通過@private來修飾, 或者把聲明放到.m文件中。在Objective-c中,所有實例變量默認都是都是私有的, 所有實例方法默認都是公有的。
16. include與#import的區(qū)別?#import與@class的區(qū)別
- import 是 Objective-C 導入頭文件的關鍵字,#include 是 C/C++導入頭文件的關鍵字 - 使用import 頭文件會自動只導入一次,不會重復導入,相當于#include 和#pragma once;(條件編譯) - import指令就是Object-C針對#include的改進版本,#import確保引用的頭文件只會被引用一次,這樣你就不會陷入遞歸包含的問題中。 - @class 告訴編譯器某個類的聲明,當執(zhí)行時,才去查看類的實現(xiàn)文件,循環(huán)引用頭文件;#import<> 用來包含系統(tǒng)的頭文件,#import””用來包含用戶頭文 - import與@class二者的區(qū)別在于: ① import會鏈入該頭文件的全部消息,包括實例變量和方法等。而@class只是告訴編譯器,其后面聲明的名稱是類的名稱,至于這些類是如何定義的,暫時不用考慮。 ② 在頭文件中一般使用@class來聲明這個名稱是類的名稱,不需要知道其內(nèi)部的實體變量和方法。 ③ 而在實現(xiàn)類里面,因為會用到這個引用類的內(nèi)部的實體變量和方法,所以需要使用#import來包含這個被引用類的頭文件。 ④ 在編譯效率方面,如果你有100個頭文件都#import了同一個頭文件, 或者這些頭文件是依次引用的,如A->B,B->C,C->D這樣的引用關系。 當最開始的頭文件有變化的話,后面所有引用它的類都需要重新編譯, 如果你有的類很多的話,這將耗費大量的時間。而是用@class則不會。 ⑤ 如果有循環(huán)依賴關系,如:A->B,B->A這樣的相互依賴關系,如果使用 #import來相互包含,那么就會出現(xiàn)編譯錯誤,如果使用@class在兩個類的頭 文件中相互聲明,則不會有編譯錯誤出現(xiàn)。
17. 淺復制(拷貝)和深復制的區(qū)別?
- 淺復制(copy):只復制指向對象的指針,而不復制引用對象本身。 - 深復制(mutableCopy): 復制引用對象本身。深復制就好理解了,內(nèi)存中存在了兩份獨立對象本身,當修改A時,A_copy不變。
18. 類變量的@protected,@private,@public,@package聲明各有什莫含義?
變量的作用域不同。 - @protected 該類和子類中訪問,是默認的; - @private 只能在本類中訪問; - @public 任何地方都能訪問; - @package 本包內(nèi)使用,跨包不可以;
19. Objective-C和C、C++之間的聯(lián)系和區(qū)別?
- Objective-C和C++都是C的面向對象的超集。 - Objective與C++的區(qū)別主要點: Objective-C是完全動態(tài)的,支持在運行時 動態(tài)類型決議(dynamic typing),動態(tài)綁定(dynamic binding)以及動態(tài)裝載 (dynamic loading);而C++,是部分動態(tài)的,編譯時靜態(tài)綁定,通過嵌入 類(多重繼承)和虛函數(shù)(虛表)來模擬實現(xiàn)。 - Objective-C在語言層次上支持動態(tài)消息轉發(fā),其消息發(fā)送語法為[object function]; 而且C++為object->function()。兩者的語義也不同,在Objective-C里是說發(fā)送 消息到一個對象上,至于在這個對象能不能響應消息以及是響應還是轉發(fā)消息都不會 crash;而在C++里是說對象進行了某個操作,如果對象沒有這個操作的話,要么編 譯會報錯(靜態(tài)綁定),要么程序會crash掉的(動態(tài)綁定)。
20. 目標-動作機制
- 目標是動作消息的接收者。一個控件,或者更為常見的是它的單元,以插座變量的形式保其動作消息的目標。 - 動作是控件發(fā)送給目標的消息,或者從目標的角度看,它的目標為了響應動作而實現(xiàn)的方法。程序需要某些機制來進行事件和指令的翻譯。 這個機制就是目標-動作機制。
- 21. Objective-C優(yōu)點和缺點
- 優(yōu)點:
① Cateogies
② Posing
③ 動態(tài)識別
④ 指標計算
⑤ 彈性訊息傳遞
⑥ 不是一個過度復雜的C衍生語言
⑦ Objective-C與C++可混合編程
- 缺點
① 不支持命名空間
② 不支持運算符重載
③ 不支持多重繼承
④ 使用動態(tài)運行時類型,所有的方法都是函數(shù)調(diào)用,所以很多編譯時優(yōu)化方法都用不到。(如內(nèi)聯(lián)函數(shù)等),性能低劣。
- 22. C語言的函數(shù)調(diào)用和oc的消息機制有什莫區(qū)別?
- 對于C語言,函數(shù)的調(diào)用在編譯的時候會決定調(diào)用哪個函數(shù)。編譯完成之后直接順序執(zhí)行。
- OC的函數(shù)調(diào)用成為消息發(fā)送。屬于動態(tài)調(diào)用過程。在編譯的時候并不能決定真正調(diào)用哪個函數(shù)
(事實證明,在編譯階段,OC可以調(diào)用任何函數(shù),即使這個函數(shù)并未實現(xiàn),只要申明過就不會報錯。而C語言在編譯階段就會報錯)。這有在真正運行的時候才會根據(jù)函數(shù)的名稱找到對應的函數(shù)來調(diào)用。
23. 什么是謂詞?
謂詞就是通過NSPredicate給定的邏輯條件作為約束條件,完成對數(shù)據(jù)的篩選。// 定義謂詞對象,謂詞對象中包含了過濾條件 NSPredicate *predicate = [NSPredicate predicateWithFormat:@''age<%d'',30]; // 使用謂詞條件過濾數(shù)組中的元素,過濾之后返回查詢的結果 NSArray *array = [persons filteredArrayUsingPredicate:predicate]; // 可以使用&&進行多條件過濾 predicate = [NSPredicate predicateWithFormat:@''name='1' && age>40'']; array = [persons filteredArrayUsingPredicate:predicate]; // 包含語句的使用 predicate = [NSPredicate predicateWithFormat:@''self.name IN{'1','2','4'} || self.age IN{30,40}'']; // 指定字符開頭和指定字符串結尾,是否包含指定字符 // name以a開頭的 predicate = [NSPredicate predicateWithFormat:@''name BEGINSWITH 'a''']; // name以ba結尾的 predicate = [NSPredicate predicateWithFormat:@''name ENDSWITH'ba''']; // name中包含字符a的 predicate = [NSPredicate predicateWithFormat:@''name CONTAINS 'a''']; // like進行匹配多個字符 // name中只要有s字符就滿足條件 predicate = [NSPredicate predicateEithFormat:@''name like 's''']; //?代表一個字符,下面的查詢條件是: name中第二個字符是s的 predicate = [NSPredicate predicateWithFormat:@''name like '?s'''];
- 24. C與OC混用
處理.m可以識別c和oc,.mm可以識別c c++ oc 但是cpp只能用c/c++
- 25. atomic和nonatomic的區(qū)別
- atomic提供多線程安全,防止讀寫未完成的時候被另外一個線程的讀寫,造成數(shù)據(jù)錯誤。
- nonatomic在自己管理內(nèi)存環(huán)境中,解析的訪問器保留并自動釋放返回值,若指定了nonatomic,那么訪問器只是簡單的返回這個值。
- 26. 常見的oc數(shù)據(jù)類型哪些,和c的基本類型有啥區(qū)別
- 常見的: NSInteger、 CGFloat、 NSString、 NSNumber、 NSMutableArray、 NSArray、 NSDate
- NSInteger 根據(jù)32或者64位系統(tǒng)決定本身是int還是long
- CGFloat 根據(jù)32或者64位系統(tǒng)決定本身是float還是double
- NSString NSNumber NSArray NSDate是指針類型的對象,在堆中分配內(nèi)存,C語言中的char int 等都是在棧中分配控件
- 27. id和nil代表什么
- id類型的指針可以指向任何OC對象
- nil代表空值(空指針的值,0)
- 28. nil和NULL的區(qū)別
- 從oc的官方語法上看,nil表示對象的指針 即對象的引用為空
- null表示指向基礎數(shù)據(jù)類型變量 即c語言變量的指針為空
- 在非arc中 兩個空可以互換,但是arc中普通指針和對象引用被嚴格限制,不能互換
29. nil、Nil、NULL和NSNull區(qū)別
- nil和C語言的NULL相同,在objc/objc.h中定義。nil表示Objective-C對象的值為空。 在C語言中,指針的控制用NULL表示。在Objective-C中,nil對象調(diào)用任何方法表示什莫 也不執(zhí)行,也不會崩潰。 - Nil: 那么對于我們Objective-C開發(fā)來說,Nil也就代表((void *)0)。但是它是用于代表空類的.比如:Class myClass = Nil; - NULL:在C語言中,NULL是無類型的,只是一個宏,它代表空。這就是在C/C++中的空指針。對于我們Objective-C開發(fā)來說,NULL就表示((void*)0) - NSNull:NSNull是繼承于NSObject的類型。它是很特殊的類,它表示是空,什么也不存儲, 但是它卻是對象,只是一個占位對象。使用場景就不一樣了,比如服務器中的接口中讓我們在值為空時,傳空。 NSDictionry *parameters = @{@''arg1'':@''value1'',@''arg2'':arg2.isEmpty?[NSNull null]:arg2};
對于NULL、nil、Nil這三者對于Objective-C中值是一樣的,都是(void )0,那么為什么要區(qū)分呢?又與NSNull之間有什么區(qū)別:((void *)0)
- NULL是宏,是對于C語言指針而使用的,表示空指針 - nil是宏,是對于Objective-C中對象而使用的,表示對象為空 - Nil是宏,是對于Objective-C中的類而使用的,表示類指針為空 - NSNull是類類型,是用于表示空的占位對象,與JS或者服務器端的null類似的含意。
- 30. 向一個nil對象發(fā)送消息會發(fā)生什么?
向nil發(fā)送消息是完全有效的-- 只是在運行時不會有任何作用。
如果一個方法返回值是一個對象,那么發(fā)送給nil的消息將返回0(nil)
如果方法返回值為指針類型
其指針大小為小于或者等于sizeof(void*),float,double,long double 或者long long 的整型標量,發(fā)送給nil的消息將返回0. 如果方法返回值為結構體,正如在《Mac OS X ABI 函數(shù)調(diào)用指南》, 發(fā)送給nil的消息將返回0.結構體中各個字段的值將都是0.其他的結構 體數(shù)據(jù)類型將不是用0填充。** 如果方法的返回值不是上述提到的幾種情況,那么發(fā)送給nil的消息的返回值將是未定義的。
self.和self->的區(qū)別
- self.是調(diào)用get或者set方法 - self是當前本身,是一個指向當前對象的指針 - self->直接訪問成員變量
31. 類方法和實例方法的本質(zhì)區(qū)別和聯(lián)系
類方法屬于類對象 只能類對象調(diào)用 self是類對象 類方法可以調(diào)用其他類方法 類方法不能訪問成員變量 類方法不能直接調(diào)用對象方法
實例方法
屬于實例方法 實例對象調(diào)用 self是實例對象 實例方法可以調(diào)用實例方法 實例方法可以訪問成員變量 實例方法可以調(diào)用類方法
32. __block/weak修飾符區(qū)別
- __block在arc和mrc環(huán)境下都能用,可以修飾對象,也能修飾基本數(shù)據(jù)類型 - __weak只能在arc環(huán)境下使用,只能修飾對象(NSString),不能修飾基本數(shù)據(jù)類型(int) - __block對象可以在block中重新賦值,__weak不行。
33. 寫一個NSString類的實現(xiàn)
NSString *str = [NSString alloc]initWithCString:null TerminatedCString encoding:encoding];
34. 為什么標準頭文件都有類似一下的結構?
ifndef __INCvxWorksh
define __INCvxWorksh
ifdef __cplusplus
extern ''C'' {
endif
ifdef __cplusplus
}
endif
endif**顯然,頭文件中的編譯宏"indef INCvxWorksh、#define INCvxWorksh.#endif"的作用是防止該頭文件被重復引用**
- 35. init和initwithobject區(qū)別(語法)
后者給屬性賦值
36.@property 的本質(zhì)是什么?ivar/getter/setter是如何生成并添加到這個類中的
@property的本質(zhì):@property = ivar(實例變量) + getter(取方法) + setter(存方法)
-『屬性』(property)有兩大概念:ivar(實例變量)、存取方法(access method = getter +setter)
ivar/getter/setter如何生成并添加到類中:
這是編譯器自動合成的,通過@synthesize關鍵字指定,若不指定,默認為@synthesize propertyName = _propertyName; 若手動實現(xiàn)了getter、setter方法,則不會自動合成。 - 現(xiàn)在編譯器已經(jīng)默認為我們添加@sythesize propertyName = _propertyName; 因此不再需要手動添加了,除非你真的要改成員 變量。 - 生成getter方法時,會判斷當前屬性名是否有_,比如聲明屬性為@property(nonatomic,copy) NSString *_name; 那么所生成的成員變量就會變成_ _name,不過,命名都要有規(guī)范,是不允許聲明屬性是使用_開頭的,不規(guī)范的命名, 在使用runtime時,會帶來很多的不方便。
*37. 這個寫法會出現(xiàn)什么問題:@property(copy) NSMutableArray array
- 沒有指名為nonatomic,因此就是atomic原子操作,會影響性能。 - 該屬性使用了同步鎖,會在創(chuàng)建時生成一些額外的代碼用于幫助編寫編寫多線程程序,這會帶來性能問題。 - 通過聲明nonatomic可以節(jié)省這些雖然很小,但是不必要額外開銷。 - 在我們的應用程序中,幾乎都是使用nonatomic來聲明的, - 因此使用atomic并不能保證絕對的線程安全,對于要絕對保證線程安全的操作, - 還需要使用更高級的方式來處理,比如NSSpinLock/@syncronized等。 - 因此使用的是copy,所得到的實際是NSArray,它是不可變的,若使用中使用了增、刪、改操作,則會crash。
38. @protocol和category中如何使用@property
在protocol中使用@property只會生成setter和getter方法聲明,
我們使用的目的是希望遵守我協(xié)議的對象能實現(xiàn)該屬性。category使用@property也是只會生成setter和getter的聲明,
如果,我們真的需要caregory增加屬性的實現(xiàn),需要借助于運行時的兩個函數(shù):
objc_setAssociatedObject
objc_getAssociatedObject
39. @property中有哪些屬性關鍵字
① 原子性(atomic,nonatomic) ② 讀寫(readwrite, readonly) ③ 內(nèi)存管理(assign, strong, weak, unsafe_unretained,copy) ④ getter、setter
40.isa指針問題
- isa: 是一個Class類型的指針.每個實例對象有個isa的指針, 它指向對象的類,而class里也有個isa指針,指向meteClass(元類)。 元類保存了類方法的列表。當類方法被調(diào)用時,先會從本身查找類方法的實現(xiàn), 如果沒有,元類會向他父類查找該方法。同時注意的是:元類>(meteClass) 也是對象。元類也有isa指針,它的isa指針最終指向的是 一個根元類 (root meteClass).根元類的is指針指向本身 ,這樣形成了一個封閉的內(nèi)循環(huán)。
41.如何訪問并修改一個類的私有屬性?
- 一種是通過KVC獲取 - 通過runtime訪問并修改私有屬性
42.如何為Class定義一個對外只讀對內(nèi)可讀寫的屬性?
在頭文件中將屬性定義為readonly,在.m文件中將屬性重新定義為readwrite
43.Objective-C中,meta-class指的是什莫?
meta-class是Class對象的類,為這個Class類存儲類方法,當一個類發(fā)送消息時, 就去這個類對應的meta-class中查找那個消息,每個Class都有不同的meta-class, 所有的meta-class,所有的meta-class都使用基類的meta-class(假如類繼承 NSObject,那么他所對應的meta-class也是NSObject)作為他們的類。
44.Objective-C的class是如何實現(xiàn)的?Selector是如何被轉化為c語言的函數(shù)調(diào)用的?
當一個類被正確的編譯過后,在這個編譯成功的類里面,存在一個變量用于保存這個類的信息。 我們可以通過[NSClassFromString]或[obj class]。這樣的機制允許我們在程序執(zhí)行的過程中, 可以Class來得到對象的類,也可以在程序執(zhí)行的階段動態(tài)的生成一個在編譯階段無法確定的 一個對象。(isa指針)
- @selector()基本可以等同C語言的中函數(shù)指針,只不過C語言中,
可以把函數(shù)名直接賦給一個函數(shù)指針,而Object-C的類不能直接
應用函數(shù)指針,這樣只能做一個@selector語法來取。@interface foo - (int)add:int val @end SEL class_func; // 定義一個類方法指針 class_func = @selector(add:int); @selector是查找當前類的方法,而[object@selector(方法名:方法參數(shù)..)]; 是取object對應類的相應方法。 查找類方法時,除了方法名,方法參數(shù)查詢條件之一。 可以用字符串來找方法SEL 變量名 = NSSelectorFromString(方法名字的字符串) 可以運行中用SEL變量反向查出方法名字字符串。NSString *變量名 = NSStringFromSelector(SEL參數(shù)); 取到selector的值以后,執(zhí)行seletor.SEL變量的執(zhí)行。用performSelecor方法來執(zhí)行。 [對象 performSelector:SEL變量 withObject:參數(shù)1 withObject:參數(shù)2];
45. 對于語句NSString obj = [NSData alloc]init];,編譯時和運行時obj是什莫類型?
- 編譯時是NSString類型,運行時是NSData類型
46. @synthesize和@dynamic分別有什么作用?
- @property有兩個對應的詞,一個是 @synthesize,一個是@dynamic. 如果@synthesize和@dynamic都沒寫,那么默認的就是@synthesize var = _var; - @synthesize 的語義是如果你沒有手動實現(xiàn) setter 方法和getter,那么編譯器會自動為你加上這兩個方法。 - @dynamic 告訴編譯器:屬性的setter 與getter方法由用戶自己實現(xiàn),不自動生成。(當然對于 readonly 的屬性只需要提供getter即可)。 假如一個屬性被聲明為@dynamic var,然后你沒有提供@setter方法和@setter方法, 編譯的時候沒問題,但是當程序運行到 instance.var = someVar,由 于缺setter方法會導致程序崩潰;或者當運行到someVar = Var時,由于缺 getter方法同樣會導致崩潰。編譯時沒有問題,運行時才執(zhí)行相應的方法, 這就是所謂的動態(tài)綁定。 有些存取是在運行時動態(tài)創(chuàng)建的,如在 CoreData 的 NSManagedObject 類使用的某些。 如果你想 這些情況下,聲明和使用屬性,但要避免缺少方法在編譯時的警告, 你可以使用@dynamic 動態(tài) 指令,而不是@synthesize 合成指令。
47. NSString 的時候用copy和strong的區(qū)別?
oc中NSString為不可變字符串的時候,用copy和strong都只分配一次內(nèi)存, 但是如果用copy的時候,需要先判斷字符串是否是不可變字符串,如果是不可 變字符串,就不在分配空間,如果是可變字符串才分配空間。如果程序中用到 NSString的地方特別多,每一次都要先進行判斷就會耗費性能,影響用戶體驗, 用strong就不會再進行判斷,所以不可變字符串可以直接用strong.
- 48.NSArray、NSSet、NSDictionary、NSMutableArray、NSMutableSet、NSMutableDictionary的特性和作用(遇到copy修飾產(chǎn)生的變化)
特性:
**NSArray** 表示不可變數(shù)組,是有序元素集,只能存儲對象類型,可通過>索引直接訪問元素, 而且元素類型可以不一樣,但是不能進行增、刪、改操作;>NSMutableArray是可 變數(shù)組,能進行增、刪、改操作。通過索引查詢值很快,但是插入、刪除等效率很低。 **NSSet** 表示不可變集合,具有確定性、互異性、無序性的特點,只能>訪問而不能修改集合; NSMutableSet表示可變集合,可以對集合進行增、刪、改操作。集合通過值查詢很快, 插入、刪除操作極快。 **NSDictionary** 表示不可變字典,具有無序性的特點,每個key對應的值是唯一的,可通過 key直接獲取值;NSMutableDictionary表示可變字典,能對字典進行增、刪、改操作。 通過key查詢值、插入、刪除值都很快。
作用:
- 數(shù)組用于處理一組有序的數(shù)據(jù)集,比如通常用的列表的dataSource要有序,可通過索引直接訪問,效率高。 - 集合要求具有確定性、互異性、無序性,在iOS開發(fā)中是比較少使用到的。筆者也不清楚如何說明其作用 - 字典是鍵值對數(shù)據(jù)集,操作字典效率極高,時間復雜度為常量,但是值是無序的。在iOS中,常見的 JSON轉字典,字典轉模型就是其中一種應用。
49. 請把字符串2015-04-10格式化日期轉為NSDate
NSString *timeStr = @"2015-04-10"; NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; formatter.dateFormat = @"yyyy-MM-dd"; formatter.timeZone = [NSTimezone defaultTimeZone]; NSDate *date = [formatter dateFromString:timeStr]; // 2015-04-09 16:00:00 +0000 NSLog(@"%@",date);
50. 在一個對象的方法里:self.name = @object;和name = @object有什么不同
- 這是老生常談的話題了,實質(zhì)上就是問setter方法賦值與成員變量賦值有什么不同。 通過點語法self.name實質(zhì)上就是[self setName:@object];。而name這里是成員變量,直接賦值。 - 一般來說,在對象的方法里成員變量和方法都是可以訪問的, 我們通常會重寫Setter方法來執(zhí)行某些額外的工作。比如說, 外部傳一個模型過來,那么我會直接重寫Setter方法,當模型 傳過來時,也就是意味著數(shù)據(jù)發(fā)生了變化,那么視圖也需要更新 顯示,則在賦值新模型的同時也去刷新UI。這樣也不用在額外提供方法了。
51. 怎樣使用performSelector傳入3個以上參數(shù),其中一個為結構體
- (id)performSelector:(SEL)aSelector; - (id)performSelector:(SEL)aSelector withObject:(id)object; - (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;
因為系統(tǒng)提供的performSelector的api中,并沒有提供三個參數(shù)。因此,我們只能傳數(shù)組或者字典,但是數(shù)組或者字典只有存入對象類型,而結構體并不是對象類型,那么怎么辦呢?沒有辦法,我們只能通過對象放入結構作為屬性來傳過去了:
typedef struct HYBStruct{ int a; int b; } *my_struct @interface HYBObject: NSObject @property (nonatomic,assign) my_struct arg3; @property (nonatomic,copy) NSString *arg1; @property (nonatomic,copy) NSString *arg2; @end @implementation HYBObject // 在堆上分配的內(nèi)存,我們要手動釋放掉 - (void)dealloc { free(self.arg3); } @end
測試:
my_struct str = (my_struct)(malloc(sizeof(my_struct))) str->a = 1; str->b = 2; HYBObject *obj = [[HYBObject alloc] init]; obj.arg1 = @"arg1"; obj.arg2 = @"arg2"; obj.arg3 = str; [self performSelector:@selector(call:) withObject:obj]; // 在回調(diào)時得到正確的數(shù)據(jù)的 - (void)call:(HYBObject *)obj { NSLog(@"%d %d",obj.arg3->a,obj.arg->b); }
52. objc中向一個對象發(fā)送消息[obj foo]和objc_msgSend()函數(shù)之間有什么關系?
實際上,編譯器在編譯時會轉換成objc_msgSend,大概會像這樣: ((void (*)(id,SEL)) (void)objc_msgSend) ((id)obj,sel_registerName("foo")); 也就是說,[obj foo];在objc動態(tài)編譯時,會被轉換為:
objc_msgSend(obj,@selector(foo));
這樣的形式,但是需要根據(jù)具體的參數(shù)類型及返回值類型進行相應的類型轉換。
53. 下面的代碼輸出什么?
@implementation Son: Father
- (id)init {
self = [super init];
if(self){
NSLog(@"%@",NSStringFromClass([self class]));
NSLog(@"%@",NSStringFromClass([self class]));
}
return self;
}
@end// 輸出 NSStringFromClass([self class]) = Son; NSStringFromClass([self class]) = Son;
這個題目主要是考察關于Object-c中對self和super的理解。我們都知道self是類的隱藏參數(shù),指向當前調(diào)用方法的這個類的實例。那super呢?
很多人會想當然的認為super和self類似,應該是指向父類的指針吧!
這是很普遍的一個誤區(qū)。其實super是一個Magic Keyword,它本質(zhì)是一個編譯器標志符,和self是指向的同一個消息接受者!他們兩個的不同點在于:super會告訴編譯器,調(diào)用class這個方法時,要去父類的方法,而不是本類里的。上面的例子不管調(diào)用[self class]還是[super class],接受當前的對象都是Son *xxx這個對象。
當使用self調(diào)用方法時,會從當前類的方法列表中開始查找,如果沒有就從父類中再找。
而當使用super時,則從當前類的方法列表中開始找。然后調(diào)用父類這個方法。
54. 若一個類有實例變量NSString _foo,調(diào)用setValue:forKey時,可以以foo還是_foo作為key?
答:兩者都可以
55. 什莫時候使用NSMutableArray,什莫時候使用NSArray?
答:- 當數(shù)組在程序運行時,需要不斷變化的,使用NSMutableArray. - 當數(shù)組在初始化后,便不在改變時,使用NSArray.
需要指出
- 使用NSArray只表明該數(shù)組在運行時,不發(fā)生改變,即:不能往NSArray的數(shù)組中新增和刪除元素,但不表明其數(shù)組內(nèi)的內(nèi)容不發(fā)生改變。 - NSArray是線程是安全的,NSMutableArray線程是不安全的,多線程使用> NSMutableArray需要注意。
56. 類NSObject的哪些方法經(jīng)常被使用?
- NSObject是Object-C的基類,其由NSObject類及一系列協(xié)議組成 - 類方法 alloc /class/description - 對象方法 init/dealloc/-performSelector:withObject:afterDelay:等經(jīng)常使用
57.什莫是簡便構造方法
答:
簡便構造方法一般由CocoaTouch框架提供,如NSNumber的
+numberWithBool: +numberWithChar: +numberWithDouble: +numberWithFloat; +numberWithWithInt
Foundation下大部分類均有簡便構造方法,我們可以通過簡便構造方法,獲得系統(tǒng)給我們創(chuàng)建好的對象,并且不需要手動釋放。
58.什莫是構造方法,使用構造方法需要什莫注意點?
- 什莫是構造方法:構造方法是對象初始化并一個實例方法。
- 構造方法有什莫用:一般在構造方法里,對類進行一些初始化操作
注意點:方法開頭必須以init開頭,接下來名稱要大寫 例如 initWithName,initLayout
59.創(chuàng)建一個對像需要經(jīng)過三個步驟?
- 開辟內(nèi)存空間
- 初始化參數(shù)
- 返回內(nèi)存地址值
60.Get方法的作用是什莫?
Get方法的作用:為調(diào)用者返回對象內(nèi)部成員變量
61.Set方法的作用是什莫?Set方法的好處是什莫?
- Set 方法的作用: 為外界提供一個設置成員變量值的方法。
- Set 方法的好處:
- 不讓對象暴露在外,保證了數(shù)據(jù)的安全性
- 對設置的數(shù)據(jù)進行過濾
62.結構體中能定義oc對象嗎?
不能,因為結構體中只能是類型的聲明,不能進行分配空間
63.點語法的本質(zhì)是什莫?寫一個點語法的例子,并寫上注釋
- 點語法的本質(zhì),就是方法的調(diào)用,而不是訪問成員變量。當使用點語法是,編譯器會自動展開響應的方法。
注意:切記,點語法的本事是轉換成相應的set 和get 方法,如果沒有set和get方法,則不能使用點語法。
** 例如**
# 例如有一個Person類 通過@property定義了name和age屬性,在提供一個run方法。 Person *person = [Person new]; person.name = @"Tom"; // 調(diào)用了person的setName方法 int age = person.age; // 調(diào)用了person的age方法(get) person.run // 調(diào)用了person的run方法
64.id類型是什莫,instancetype就是什莫,有什莫區(qū)別?
- id類型:萬能指針,能作為參數(shù),方法的返回類型。
- instancetype: 只能作為方法的范圍類型,并且返回的類型是當前定義類的類類型。(特定類)
65.成員變量的命名以下劃線開頭的好處?
- 與get方法的方法名區(qū)分開來;
- 可以和一些其他的局部變量分開來,下劃線開頭的變量,通常都是類的成員變量。
66.下面這段代碼有什莫問題嗎?
@implementation Person
- (void)setAge:(int)newAge{
self.age = newAge;
}
@end
- 會造成死循環(huán),會重復調(diào)用自己!self,age改為_age即可;
- 并且書寫不規(guī)范:setter方法中的newAge應該為age
67.截取字符串『20 | http:ww.baidu.com』中『|』字符串前面和后面的數(shù)據(jù),分別輸出它們。
- NSString *str = @"20 | http:ww.baidu.com"; NSArray *array = [str componentsSeparatedByString:@" | "]; 輸出截取后的字符串 for (int i = 0;i<[array count];i++){ NSLog(@"%d = %@",i,[array objectAtIndex:i]); }
68.寫一個完整的代理,包括聲明和實現(xiàn)
- 創(chuàng)建 @protocol MyDelagate @required - (void)eat :(NSString * )foodName; @optional - (void)run; @end - 聲明 @interface person :NSObject<MyDelagate> - 實現(xiàn) @implementation person - (void)eat:(NSString * )foofName { NSLog(@"吃:%@!",foodName); } - (void)run { NSLog(@"run"); } @end
69. isKindOfClass、isMemberOfClass、selector作用分別是什莫?
① isKindOfClass,作用是,某個對象屬于某個類型或者繼承自某個類型
② isMemberOfClass某個對象確切屬于某個類型
③ selector:通過方法名,獲取內(nèi)存中函數(shù)的入口地址
70. 請分別寫出SEL、Id、@的意思?
- SEL 是selector的一個 類型,表示一個方法的名字----就是一個方法的入口地址。
- id是一個指向任何一個繼承了Object(或者NSObject) 類的對象。需要注意的是id是一個指針,所以在使用id的時候不需要加*
- @: 是OC中的指令符
70. unsigned int 和int有什莫區(qū)別。 假設int長度為65535,請寫出unsigned int 和int的取值范圍
int:基本整數(shù),當字節(jié)數(shù)為2時 取值范圍為-32768~32767,當字節(jié)數(shù)為4時 取>值范圍是 負的2的31次方 到2的31減1
unsigned int:無符號基本整數(shù),當字節(jié)數(shù)為2時 取值范圍為 0~65535,當字>節(jié)書為4時 取值范圍為0到2的32次
71. Foundation對象,Core Foundation對象有什么區(qū)別
Foundation對象是OC的,Core Foundation對象是C對象
數(shù)據(jù)類型之間的轉換
- ARC:bridge_retained(持有對象所有權,F(xiàn)->CF)、bridge_transfer(釋放對象所有權CF->F)
- 非ARC:__bridege
72. 編寫一個函數(shù),實現(xiàn)遞歸刪除指定路徑下的所有文件。
+ (void)deleteFiles:(NSString *)path{ // 1.判斷文件還是目錄 NSFileManager *fileManger = [NSFileManager defaultManager]; BOOL isDir = NO; BOOL isExist = [fileManger fileExistsAtPath:path isDirectory:&isDir]; if(isExist){ // 2.判斷是不是目錄 if(isDir) { NSArray *dirArray = [fileManger contentOfDirectoryAtPath:path error: nil]; NSString *subPath = nil; for ( NSString *str in dirArray){ subPath = [path stringByAppendingPathComponent:str]; BOOL issubDir = NO; [fileManger fileExistsAtExistsAtPath:subPath isDirectory:&issubDir]; [self deleteFiles: subPath]; }else{ NSLog(@"%@",path) [manager removeItenAtPath:filePath error:nil]; } }else{ NSLog(@"你打印的是目錄或者不存在"); } } }
73.UITableview創(chuàng)建方式
(1)自定義高度
1>新建一個繼承自UITableViewCell的類
2>重寫initWithStyle:reuseIdentifier:方法
3>添加所有需要顯示的子控件(不需要設置子控件的數(shù)據(jù)和frame, 子控件要添加到 contentView中)
4>進行子控件一次性的屬性設置(有些屬性只需要設置一次, 比如字體\固定的圖片)
5>提供2個模型- 數(shù)據(jù)模型: 存放文字數(shù)據(jù)\圖片數(shù)據(jù) - frame模型: 存放數(shù)據(jù)模型\所有子控件的frame\cell的高度
6>cell擁有一個frame模型(不要直接擁有數(shù)據(jù)模型)
7>重寫frame模型屬性的setter方法: 在這個方法中設置子控件的顯示數(shù)據(jù)和frame(2)自定義高度原理
A 手動計算
1> 由于heightForRow比cellForRow方法先調(diào)用,創(chuàng)建frame模型包含微博模型,重寫微博模型 賦值set方法,提前計算cell子控件的frame并保存,heightForRow方法中取出frame模型中保存 的高度,實現(xiàn)自定義高度cell。
2> 設置最大尺寸、文本屬性,根據(jù)文本內(nèi)容計算正文內(nèi)容展示尺寸
3> cellForRow中創(chuàng)建自定義cell包含frame屬性,重寫frame屬性set方法創(chuàng)建cell子控件并賦 值frame模型保存的子控件尺寸
B. 自動計算
1> 首先設置行高使用autolayout自動計算并預估高度
2> 在stroboard中對cell內(nèi)容進行自動布局,注意設置圖片距離底部約束,cellForRow中創(chuàng)建 storyboard中對應標記的自定義cell
3> 由于正文內(nèi)容的不確定性,設置label多行,拖線圖片高度約束,根據(jù)圖片有無,設置代碼 設置高度約束
74.Swift和OC的區(qū)別
蘋果宣稱 Swift 的特點是:
(1)快速、現(xiàn)代、安全、互動,而且明顯優(yōu)于 Objective-C 語言 (2)可以使用現(xiàn)有的 Cocoa 和 Cocoa Touch 框架 (3)Swift 取消了 Objective C 的指針/地址等不安全訪問的使用 (4)??供了類似 Java 的名字空間(namespace)、泛型(generic)var、運算對象重載(operator overloading (5)Swift 被簡單的形容為 “沒有 C 的 Objective-C”(Objective-C without the C) (6) 為蘋果開發(fā)工具帶來了Xcode Playgrounds功能,該功能??供強大的互動效果,能讓Swift源代碼在撰寫過程中實時顯示出其運行結果; (7) 基于C和Objective-C,而卻沒有C的一些兼容約束; (8) 采用了安全的編程模式; (9)界面基于Cocoa和Cocoa Touch框架; (10) 舍棄 Objective C 早期應用 Smalltalk 的語法,保留了Smalltalk的動態(tài)特性,全面 改為句點表示法 (11) 類型嚴謹 對比oc的動態(tài)綁定
75.在項目開發(fā)中常用 的開發(fā)工具有哪些
Instrument beyondCompare git corn stone application loadder idea(編寫 h5 和 RN):
76.UITableView&UICollection
UICollectionView 是 iOS6 新引進的 API,用于展示集合視圖,布局更加靈活,其用法類似 于 UITableView。而 UICollectionView、UICollectionViewCell 與 UITableView、 UITableViewCell 在用法上有相似 的也有不同的,下面是一些基本的使用方法:
對于 UITableView,僅需要 UITableViewDataSource,UITableViewDelegate 這兩個協(xié)議,使用 UICollectionView 需要實現(xiàn) UICollectionViewDataSource,UICollectionViewDelegate, UICollectionViewDelegateFlowLayout 這三個協(xié)議,這是因為 UICollectionViewDelegateFlowLayout 實際上是 UICollectionViewDelegate 的一個子協(xié)議, 它繼承 了 UICollectionViewDelegate,它的作用是??供一些定義 UICollectionView 布局模式 的函數(shù)
77.NSProxy&NSObject
NSObjetct:
NSObject協(xié)議組對所有的Object-C下的objects都生效。如果objects遵從該協(xié)議, 就 會被看作是 first-class object(s 一級類)。另外,遵從該協(xié)議的 objects 的 retain,release, autorelease 等方法也服從 objects 的管理和在 Foundation 中 定義的釋放方法。
一些容器中的 對象也可以管理這些 objects,比如 說 NSArray 和 NSDictionary 定義的對象。 Cocoa 的根類 也遵循該協(xié)議,所以所有繼承 NSObjects 的 objects 都有遵循該協(xié)議的特性。
NSProXY:
NSProxy 是一個虛基類,它為一些表現(xiàn)的像是其它對象替身或者并不存在的對象 定義一套 API。一般的,發(fā)送給代理的消息被轉發(fā)給一個真實的對象或者代理本 身 load(或者將本身轉換 成)一個真實的對象。
NSProxy 的基類可以被用來透明的轉發(fā)消息或者耗費巨大的對象的 lazy 初始化。
78.傳值通知&推送通知(本地&遠程)
傳值通知: 類似通知,代理,Block 實現(xiàn)值得傳遞
.
推送通知: 推送到用戶手機對應的 App 上(主要是不再前臺的情況),用戶獲得資源的一種 手段。普通情況下,都是客戶端主動的 pull。推送則是服務器端主動 push。
.
本地通知: local notification,用于基于時間行為的通知,比如有關日歷或者 todo 列表的 小應用。 另外,應用 如果在后臺執(zhí)行,iOS 允許它在受限的時間內(nèi)運行,它也會發(fā)現(xiàn)本地通 知有用。 比如,一個應用,在后臺運行,向應用的服務器端獲取消息,當消息到達時,比如下 載更新版本的提示消息,通過本地通知機制通知用戶。
本地通知是 UILocalNotification 的實例,主要有三類屬性:
scheduled time:時間周期,用來指定 iOS 系統(tǒng)發(fā)送通知的日期和時間; notification type:通知類型,包括警告信息、動作按鈕的標題、應用圖標上的 badge(數(shù) 字標記)和播放的聲音; 自定義數(shù)據(jù):本地通知可以包含一個 dictionary 類型的本地數(shù)據(jù)。
對本地通知的數(shù)量限制,iOS 最多允許最近本地通知數(shù)量是 64 個,超過限制的本地通知將被 iOS 忽略。
遠程通知(需要服務器)。流程大概是這樣的
1> 生成 CertificateSigningRequest.certSigningRequest 文件 2> 將 CertificateSigningRequest.certSigningRequest 上傳進 developer,導出.cer 文 件 3> 利用 CSR 導出 P12 文件 4> 需要準備下設備 token 值(無空格) 5> 使用 OpenSSL 合成服務器所使用的推送證書
一般使用極光/友盟推送,步驟是一樣的,只是我們使用的服務器是極光的,不需要自己大服務 器!
79.第三方庫&第三方平臺
第三方庫:一般是指大牛封裝好的一個框架(庫),或者第三方給我們??供的一個庫,這里 比較籠統(tǒng) * 第三方平臺:指第三方提供的一些服務,其實很多方面跟第三方庫是一樣的,但是還是存 在一些區(qū)別。 庫:AFN,ASI,Alomofire,MJRefresh,MJExtension,MBProgressHUD 平臺:極光,百度,友盟,Mob,環(huán)信
80.imageName 和 ImageWithContextOfFile 的區(qū)別?哪個性能高
用 imageNamed 的方式加載時,圖片使用完畢后緩存到內(nèi)存中,內(nèi)存消耗多,加載速度快。 即使生成的對象被 autoReleasePool 釋放了,這份緩存也不釋放,如果圖像比較大,或者圖像 比較多,用這種方式會消耗很大的內(nèi)存。
imageNamed 采用了緩存機制,如果緩存中已加載了圖片,直接從緩存讀就行了,每次就不 用再去讀文件了,效率會更高 。
ImageWithContextOfFile 加載,圖片是不會緩存的,加載速度慢。
大量使用 imageNamed 方式會在不需要緩存的地方額外增加開銷 CPU 的時間.當應用程序需要 加載一張比較大的圖片并且使用一次性,那么其實是沒有必要去緩存這個圖片的,用 imageWithContentsOfFile 是最為經(jīng)濟的方式,這樣不會因為 UIImage 元素較多情況下,CPU 會 被逐個分散在不必要緩存上浪費過多時間.
81.NSCache&NSDcitionary
NSCache 與可變集合有幾點不同:
NSCache 類結合了各種自動刪除策略,以確保不會占用過多的系統(tǒng)內(nèi)存。如果其它應用需 要內(nèi)存時,系統(tǒng)自動執(zhí)行這些策略。當調(diào)用這些策略時,會從緩存中刪除一些對象,以最大限 度減少內(nèi)存的占用。
NSCache 是線程安全的,我們可以在不同的線程中添加、刪除和查詢緩存中的對象,而不 需要鎖定緩存區(qū)域。
不像 NSMutableDictionary 對象,一個緩存對象不會拷貝 key 對象。NSCache 和 NSDictionary 類似,不同的是系統(tǒng)回收內(nèi)存的時候它會自動刪掉它的內(nèi)容。
(1)可以存儲(當然是使用內(nèi)存) (2)保持強應用, 無視垃圾回收. =>這一點同 NSMutableDictionary (3)有固定客戶.
位運算
NSCache 特點:a> 線程安全的 b> 當內(nèi)存不足的時候,自動釋放 c> 緩存數(shù)量和緩存成本 區(qū)別NSMutableDictionary
區(qū)別NSMutableDictionary
1> 不能也不應該遍歷 2> NSCache對key強引用,NSMutableDictionary對key進行copy
82.UIView 的 setNeedsDisplay 和 setNeedsLayout 方法
(1) 在 Mac OS 中 NSWindow 的父類是 NSResponder,而在 iOS 中 UIWindow 的父類是 UIVIew。 程序一般只有一個窗口但是會又很多視圖。 (2) UIView 的作用:描畫和動畫,視圖負責對其所屬的矩形區(qū)域描畫、 布局和子視圖管理、 事件處理、可以接收觸摸事件、事件信息的載體、等等。 (3) UIViewController 負責創(chuàng)建其管理的視圖及在低內(nèi)存的時候將他們從內(nèi)存中移除。 還為標準的系統(tǒng)行為進行響應。 (4) layOutSubViews 可以在自己定制的視圖中重載這個方法,用來調(diào)整子視圖的尺寸和位置。 (5) UIView 的 setNeedsDisplay(需要重新顯示,繪制)和 setNeedsLayout(需要重新布局)方 法。 首先兩個方法都是異步執(zhí)行的。而 setNeedsDisplay 會調(diào)用自動調(diào)用 drawRect 方法,這 樣 可以拿到 UIGraphicsGetCurrentContext,就可以畫畫 了。而 setNeedsLayout 會默認調(diào)用 layoutSubViews,就可以處理子視圖中的一些數(shù)據(jù)。 綜上所述:setNeedsDisplay 方便繪圖,而 layoutSubViews 方便出來數(shù)據(jù)。setNeedDisplay 告 知視圖它發(fā)生了改變,需要重新繪制自身,就相當于刷新界面.
83.UILayer&UIView
UIView 是 iOS 系統(tǒng)中界面元素的基礎,所有的界面元素都繼承自它。1)它本身完全是由 CoreAnimation 來實現(xiàn)的(Mac 下似乎不是這 樣)。 2)它真正的繪圖部分,是由一個叫 CALayer(Core Animation Layer)的類來管理。 3)UIView 本身,更像是一個 CALayer 的管理器,訪問它的跟繪 圖和跟坐標有關的屬性, 例如 frame,bounds 等等, 實際上內(nèi)部都是在訪問它所包含的 CALayer 的相關屬性。 4)UIView 有個重要屬性 layer,可以返回它的主 CALayer 實例。
UIView 的 CALayer 類似 UIView 的子 View 樹形結構,也可以向它的 layer 上添加子 layer, 來完成某些特殊的表示。即 CALayer 層是可以嵌套的。
UIView 的 layer 樹形在系統(tǒng)內(nèi)部,被維護著三份 copy。 分別 shi 邏輯樹:這里是代碼可以操縱的; 動畫樹:是一個中間層,系統(tǒng)就在這一層上更改屬性,進行各種渲染操作; 顯示樹:其 內(nèi)容就是當前正被顯示在屏幕上得內(nèi)容。 動畫的運作:對 UIView 的 subLayer(非主 Layer)屬性進行更改, 系統(tǒng)將自動進行動畫生 成,動畫持續(xù)時間的缺省值似乎是 0.5 秒。 坐標系統(tǒng):CALayer 的坐標系統(tǒng)比 UIView 多了一個 anchorPoint 屬性, 使用 CGPoint 結構 表示,值域是 0~1,是個比例值。 渲染:當更新層,改變不能立即顯示在屏幕上。當所有的層都準備好時, 可以調(diào)用 setNeedsDisplay 方法來重繪顯示。 變換:要在一個層中添加一個 3D 或仿射變換,可以分別設置層的 transform 或 affineTransform 屬性。 變形:Quartz Core 的渲染能力,使二維圖像可以被自由操縱, 就好像是三維的。圖像可以在一個三維坐標系中以任意角度被旋轉, 縮放和傾斜。CATransform3D 的一套方法??供了一 些魔術般的變換效果。
84.layoutSubViews&drawRects
layoutSubviews 在以下情況下會被調(diào)用(視圖位置變化是觸發(fā)):
1、init 初始化不會觸發(fā) layoutSubviews。 2、addSubview 會觸發(fā) layoutSubviews。 3、設置 view 的 Frame 會觸發(fā) layoutSubviews,當然前??是 frame 的值設置前后發(fā)生了變 化。 4、滾動一個 UIScrollView 會觸發(fā) layoutSubviews。 5、旋轉 Screen 會觸發(fā)父 UIView 上的 layoutSubviews 事件。 6、改變一個 UIView 大小的時候也會觸發(fā)父 UIView 上的 layoutSubviews 事件。 7、直接調(diào)用 setLayoutSubviews。
drawRect 在以下情況下會被調(diào)用:
1、如果在 UIView 初始化時沒有設置 rect 大小,將直接導致 drawRect 不被自動調(diào)用。 drawRect 掉用是在 Controller->loadView, Controller->viewDidLoad 兩方法之后調(diào)用的。 所 以不用擔心在 控制器中,這些View的drawRect就開始畫了.這樣可以在控制器中設置一些值給 View(如果這些 View draw 的時候需要用到某些變量 值). 2、該方法在調(diào)用 sizeToFit 后被調(diào)用,所以可以先調(diào)用 sizeToFit 計算出 size。 然后系 統(tǒng)自動調(diào)用 drawRect:方法。 3、通過設置 contentMode 屬性值為 UIViewContentModeRedraw。 那么將在每次設置或更改 frame 的時候自動調(diào)用 drawRect:。 4、直接調(diào)用 setNeedsDisplay,或者 setNeedsDisplayInRect:觸發(fā) drawRect:, 但是有個 前提條件是 rect 不能為 0。
drawRect 方法使用注意點:
1、 若使用 UIView 繪圖,只能在 drawRect:方法中獲取相應的 contextRef 并繪圖。 如果 在其他方法中獲取將獲取到一個 invalidate 的 ref 并且不能用于畫圖。 drawRect:方法不能 手動顯示調(diào)用,必須通過調(diào)用 setNeedsDisplay 或 者 setNeedsDisplayInRect, 讓系統(tǒng)自動 調(diào)該方法。 2、若使用 calayer 繪圖,只能在 drawInContext: 中(類似魚 drawRect)繪制, 或者在 delegate 中的相應方法繪制。同樣也是調(diào)用 setNeedDisplay 等間接 調(diào)用以上方法 3、若要實 時畫圖,不能使用 gestureRecognizer,只能使用 >touchbegan 等方法來掉用 setNeedsDisplay 實時刷新屏幕