ios--小知識(shí)點(diǎn)(二)

37.cocoa內(nèi)存管理規(guī)則

1)當(dāng)你使用new,alloc或copy方法創(chuàng)建一個(gè)對(duì)象時(shí),該對(duì)象的保留計(jì)數(shù)器值為1。當(dāng)不再使用該對(duì)象時(shí),你要負(fù)責(zé)向該對(duì)象發(fā)送一條release或autorelease消息。這樣,該對(duì)象將在其使用壽命結(jié)束時(shí)被銷(xiāo)毀。

2)當(dāng)你通過(guò)任何其他方法獲得一個(gè)對(duì)象時(shí),則假設(shè)該對(duì)象的保留計(jì)數(shù)器值為1,而且已經(jīng)被設(shè)置為自動(dòng)釋放,你不需要執(zhí)行任何操作來(lái)確保該對(duì)象被清理。如果你打算在一段時(shí)間內(nèi)擁有該對(duì)象,則需要保留它并確保在操作完成時(shí)釋放它。

3)如果你保留了某個(gè)對(duì)象,你需要(最終)釋放或自動(dòng)釋放該對(duì)象。必須保持retain方法和release方法的使用次數(shù)相同。

38.清理自動(dòng)釋放池
由于自動(dòng)釋放池的銷(xiāo)毀時(shí)間是完全確立的,所以它在循環(huán)執(zhí)行過(guò)程中不會(huì)被銷(xiāo)毀。在迭代中或者循環(huán)中,需要建立自己的自動(dòng)釋放池。

39.垃圾回收gc
自動(dòng)內(nèi)存管理機(jī)制。objective-c的垃圾回收器是一種繼承性的垃圾回收器。與那些已經(jīng)存在了一段時(shí)間的對(duì)象相比,新創(chuàng)建的對(duì)象更可能被當(dāng)成 垃圾。 垃圾回收器定期檢查變量和對(duì)象以及他們之間的指針,當(dāng)發(fā)現(xiàn)沒(méi)有任何變量指向某個(gè)對(duì)象時(shí),就將該對(duì)象視為應(yīng)該被丟棄的垃圾。如果你再一個(gè)實(shí)例變量中指向某個(gè) 對(duì)象,一定要在某個(gè)時(shí)候使該實(shí)例變量賦值為nil,以取消對(duì)該對(duì)象的引用并使垃圾回收器知道該對(duì)象可以被清理了。

與自動(dòng)釋放池一樣,垃圾回收器也是在時(shí)間循環(huán)結(jié)束時(shí)才觸發(fā)。

ARC是什么?
ARC是iOS 5推出的新功能,全稱叫 ARC(Automatic Reference Counting)。簡(jiǎn)單地說(shuō),就是代碼中自動(dòng)加入了retain/release,原先需要手動(dòng)添加的用來(lái)處理內(nèi)存管理的引用計(jì)數(shù)的代碼可以自動(dòng)地由編譯器完成了。

該機(jī)能在 iOS 5/ Mac OS X 10.7 開(kāi)始導(dǎo)入,利用 Xcode4.2 可以使用該機(jī)能。簡(jiǎn)單地理解ARC,就是通過(guò)指定的語(yǔ) 法,讓編 譯器(LLVM 3.0)在編譯代碼時(shí),自動(dòng)生成實(shí)例的引用計(jì)數(shù)管理部分代碼。有一點(diǎn),ARC并不是GC,它只是一種代碼靜態(tài)分析 (Static Analyzer)工具。

40.分配
是一個(gè)新對(duì)象誕生的過(guò)程。是從操作系統(tǒng)獲得一塊內(nèi)存并將其指定為存放對(duì)象的實(shí)例變量的位置。

40.初始化
與分配對(duì)應(yīng)的操作是初始化。初始化從操作系統(tǒng)取得一塊內(nèi)存。準(zhǔn)備用于存儲(chǔ)對(duì)象。

嵌套調(diào)用技術(shù)非常重要,因?yàn)槌跏蓟椒ǚ祷氐膶?duì)象可能與分配的對(duì)象不同。

1)初始化時(shí)做什么?
給實(shí)例變量賦值并創(chuàng)建你得對(duì)象完成任務(wù)所需要的其他對(duì)象。

2)便利初始化函數(shù)
許多類(lèi)包含便利初始化函數(shù)。用來(lái)完成某些額外的工作的初始化方法,可以減少你自己完成這些工作的麻煩。

例如:NSString類(lèi)中-(id)initWithFormat:(NSString *)format,...;

3)指定初始化函數(shù)
類(lèi)中的某個(gè)初始化方法被指派為指定初始化函數(shù)。該類(lèi)所有初始化方法使用指定初始化函數(shù)執(zhí)行初始化操作。子類(lèi)使用其超類(lèi)的指定初始化函數(shù)實(shí)現(xiàn)超類(lèi)的初始化。

例如:其他初始化函數(shù)通過(guò)指定初始化函數(shù)實(shí)現(xiàn)。

41.初始化函數(shù)規(guī)則
不需要為你自己的類(lèi)創(chuàng)建初始化函數(shù)方法。如果不需要設(shè)置任何狀態(tài),或者只需要alloc方法將內(nèi)存清零的默認(rèn)行為,則不需要擔(dān)心init。

如果構(gòu)造了一個(gè)初始化函數(shù),則一定要在你自己的指定初始化函數(shù)中調(diào)用超類(lèi)的指定初始化函數(shù)。一定要將超類(lèi)的初始化函數(shù)的值賦給self對(duì)象,并返回你自己的初始化方法的值。因?yàn)槌?lèi)可能決定返回一個(gè)完全不同的對(duì)象。

如果初始化函數(shù)不止一個(gè),則要選擇一個(gè)座位指定初始化函數(shù)。被選定的方法應(yīng)該調(diào)用超類(lèi)指定初始化函數(shù)。要按照指定初始化函數(shù)的形式實(shí)現(xiàn)所有其他初始化函數(shù),就像我們?cè)谇懊娴膶?shí)現(xiàn)一樣。

42.特性@property
objective-c2.0的特性只適用于mac os x 10.5或更高版本。特性主要應(yīng)用于cocoa的新組件(尤其是華麗奪目的core Animation效果)。

1)簡(jiǎn)化接口
@property預(yù)編譯指令的作用是自動(dòng)生命屬性的setter和getter方法。

2)@synthesize也是一種新的編譯器功能,表示“創(chuàng)建該屬性的訪問(wèn)器”。

3)點(diǎn)表達(dá)式
如果點(diǎn)表達(dá)式出現(xiàn)在=左邊,該屬性名稱的setter方法(set方法)將被調(diào)用。如果點(diǎn)表達(dá)式出現(xiàn)在對(duì)象變量右邊,則該屬性名稱的getter方法(get方法)將被調(diào)用。

4)特性擴(kuò)展
@property()括號(hào)里面的東西,是對(duì)應(yīng)在set方法中要添加的語(yǔ)句。比如我在括號(hào)里寫(xiě)retain,就相當(dāng)于在它的set方法里添加了一句 [xx retain]。

@property屬性
屬性分為3類(lèi):
1.讀寫(xiě)屬性(Writability)包含:readwrite / readonly

2.setter語(yǔ)義(Setter Semantics)包含:assign / retain / copy

3.原子性(Atomicity)包含:nonatomic

下面具體說(shuō)明各個(gè)屬性的含義
readwrite / readonly:
決定是否生成set訪問(wèn)器,readwrite是默認(rèn)屬性,生成getter和setter方法;readonly只生成getter方法,不生成setter方法。

readonly關(guān)鍵字代表setter不會(huì)被生成, 所以它不可以和 copy/retain/assign組合使用。

assign / retain / copy:
這些屬性用于指定set訪問(wèn)器的語(yǔ)義,也就是說(shuō),這些屬性決定了以何種方式對(duì)數(shù)據(jù)成員賦予新值。

assign:直接賦值,索引計(jì)數(shù)不改變,適用于簡(jiǎn)單數(shù)據(jù)類(lèi)型,例如:NSIngeter、CGFloat、int、char等。

retain:指針的拷貝,使用的是原來(lái)的內(nèi)存空間。對(duì)象的索引計(jì)數(shù)加1。

此屬性只能用于Objective-C對(duì)象類(lèi)型,而不能用于Core Foundation對(duì)象。(原因很明顯,retain會(huì)增加對(duì)象的引用計(jì)數(shù),而基本數(shù)據(jù)類(lèi)型或者Core Foundation對(duì)象都沒(méi)有引用計(jì)數(shù))。

copy:對(duì)象的拷貝,新申請(qǐng)一塊內(nèi)存空間,并把原始內(nèi)容復(fù)制到那片空間。新對(duì)象的索引計(jì)數(shù)為1。
此屬性只對(duì)那些實(shí)行了NSCopying協(xié)議的對(duì)象類(lèi)型有效。

很多Objective-C中的object最好使用用retain,一些特別的object(例如:string)使用copy。

nonatomic:
非原子性訪問(wèn),不加同步,多線程并發(fā)訪問(wèn)會(huì)提高性能。如果不加此屬性,則默認(rèn)是兩個(gè)訪問(wèn)方法都為原子型事務(wù)訪問(wèn)。默認(rèn)值是atomic,為原子操作。

(atomic是Objc使用的一種線程保護(hù)技術(shù),基本上來(lái)講,是防止在寫(xiě)未完成的時(shí)候被另外一個(gè)線程讀取,造成數(shù)據(jù)錯(cuò)誤。而這種機(jī)制是耗費(fèi)系統(tǒng)資源的, 所以在iPhone這種小型設(shè)備上,如果沒(méi)有使用多線程間的通訊編程,那么nonatomic是一個(gè)非常好的選擇。)

5)保留周期retain cycle 引用計(jì)數(shù)器在該周期中歸零。

6)什么是屬性訪問(wèn)器
屬性訪問(wèn)器(Property Accessor),包括 get 訪問(wèn)器和 set 訪問(wèn)器分別用于字段的讀寫(xiě)操作

其設(shè)計(jì)目的主要是為了實(shí)現(xiàn)面向?qū)ο螅∣O)中的封裝思想。根據(jù)該思想,字段最好設(shè)為private,一個(gè)精巧的類(lèi)最好不要直接把字段設(shè)為公有提供給客戶調(diào)用端直接訪問(wèn)

另外要注意屬性本身并不一定和字段相聯(lián)系

7)self.a與a的區(qū)別
self.a使編譯器知道我們期望使用訪問(wèn)器訪問(wèn)a。如果只使用裸名a,編譯器將假設(shè)我們直接修改了實(shí)例變量。

8)self.a = nil
這行代碼表示使用nil參數(shù)調(diào)用setName:方法。生成的訪問(wèn)器方法將自動(dòng)釋放以前的name對(duì)象,并使用nil替代a。該方法完成了釋放 name對(duì) 象所占用內(nèi)存的操作。當(dāng)然,也可以只釋放name對(duì)象以清理其占用的內(nèi)存。如果你再dealloc方法以外的地方清除特性,那么使用"將nil賦值給對(duì) 象"的方法可以將特性設(shè)置為nil,同時(shí)可以使我們避免對(duì)已釋放內(nèi)存的懸空引用問(wèn)題。

9)特性不是萬(wàn)能的
有些方法不適合特性所能涵蓋的方法的相當(dāng)狹小的范圍。特性不支持那些需要接受額外參數(shù)的方法。

43.類(lèi)別@category
1)聲明類(lèi)別
@interface NSString (NumberConvenience)
-(NSNumber *)lengthAsNumber;

@end

該聲明具有2個(gè)特點(diǎn)。首先,現(xiàn)有類(lèi)位于@interface關(guān)鍵字之后,其后是位于圓括號(hào)中的一個(gè)新名稱。該聲明表示,類(lèi)別的名稱是 NumberConvenience,而且該類(lèi)別將向NSString類(lèi)中添加方法。只要保證類(lèi)別名稱的唯一性,你可以向一個(gè)類(lèi)中添加任意多得類(lèi)別。

其次,你可以指定希望向其添加類(lèi)別的類(lèi)以及類(lèi)別的名稱,而且你還可以列出添加的方法,最后以@end結(jié)束。由于不能添加新實(shí)現(xiàn)變量,因此與類(lèi)聲明不同的是,類(lèi)別的聲明中沒(méi)有實(shí)例變量部分。

2)實(shí)現(xiàn)類(lèi)別

3)類(lèi)別的局限性

第一,無(wú)法向類(lèi)中添加新的實(shí)例變量。類(lèi)別沒(méi)有位置容納實(shí)例變量。

第二,名稱沖突,即類(lèi)別中得方法與現(xiàn)有的方法重名。當(dāng)發(fā)生名稱沖突時(shí),類(lèi)別具有更高的優(yōu)先級(jí)。你得類(lèi)別方法將完全取代初始方法,從而無(wú)法再使用初始方法。有些編程人員在自己的類(lèi)別方法中增加一個(gè)前綴,以確保不發(fā)生名稱沖突。

有一些技術(shù)可以克服類(lèi)別無(wú)法增加新實(shí)例變量的局限。例如,可以使用全局字典存儲(chǔ)對(duì)象與你想要關(guān)聯(lián)的額外變量之間的映射。但此時(shí)你可能需要認(rèn)真考慮一下,類(lèi)別是否是完成當(dāng)前任務(wù)的最佳選擇。

4)類(lèi)別的作用

cocoa中得類(lèi)別主要用于3個(gè)目的:第一,將類(lèi)的實(shí)現(xiàn)分散到不同文件或者不同框架中。第二,創(chuàng)建對(duì)私有方法的前向引用。第三,向?qū)ο筇砑臃钦絽f(xié)議。

44.run循環(huán)是一種cocoa構(gòu)造,它一直處于阻塞狀態(tài)(即不執(zhí)行任何處理),知道某些事件發(fā)生為止。

45.響應(yīng)選擇器

一個(gè)類(lèi)別如何知道其委托對(duì)象是否能夠處理那些發(fā)送給它的消息?

類(lèi)別首先檢查對(duì)象,詢問(wèn)其能否響應(yīng)該選擇器。如果該對(duì)象能夠響應(yīng)該選擇器,

1)選擇器@selector()

選擇器只是一個(gè)方法名稱,但它以objective-c運(yùn)行時(shí)使用的特殊方式編碼,以快速執(zhí)行查詢。你可以使用@selector()預(yù)編譯指令選擇器,其中方法名位于圓括號(hào)中。

46.委托 非正式協(xié)議

47.正式協(xié)議

與非正式協(xié)議一樣,正式協(xié)議是一個(gè)命名的方法列表。但與非正式協(xié)議不同的是,正式協(xié)議要求顯式的采用協(xié)議。采用協(xié)議的辦法是在類(lèi)的@interface聲明中列出協(xié)議名稱。采用協(xié)議意味著你承諾實(shí)現(xiàn)該協(xié)議的所有方法。

1)聲明協(xié)議
@protocol NSCopying
-(id)copyWithZone:(NSZone *)zone;
@end

2)采用協(xié)議
@interface Car: NSObject
{
}
@end

3)協(xié)議和數(shù)據(jù)類(lèi)型
如果一個(gè)用尖括號(hào)括起來(lái)的協(xié)議名稱跟隨在id之后,則編譯器將知道你期望任意類(lèi)型的對(duì)象,只要其遵守該協(xié)議。

4)objective-c2.0的新特性@optional @required

@optional可選擇實(shí)現(xiàn)的方法

@required必須實(shí)現(xiàn)的方法

因此cocoa中得非正式協(xié)議正被帶有@optional的正式協(xié)議所取代。

48.Application Kit

1)IBOutlet與IBAction

他們實(shí)際上只是APPKit提供的#defines。IBOutlet的定義沒(méi)有任何作用,因此將不會(huì)對(duì)它進(jìn)行編譯。IBAction定義為 void,這 意味著在AppController中聲明的方法的返回類(lèi)型將使void。IBOutlet和IBAction不執(zhí)行任何操作,他們并不是用于編譯的,實(shí) 際上他們是為Interface Builder以及閱讀代碼的人提供的標(biāo)記。通過(guò)查找IBOutlet和 IBAction,Interface Builder知道AppController對(duì)象具有兩個(gè)能夠連接的實(shí)例變量。

2)IBOutlet是如何工作的

當(dāng)加載nib文件時(shí)(MainMenu.nib會(huì)在應(yīng)用程序啟動(dòng)時(shí)自動(dòng)加載,可以創(chuàng)建你自己的nib文件并自行加載),存儲(chǔ)在nib文件中得任何對(duì) 象都會(huì) 被重新創(chuàng)建。這意味著會(huì)再后臺(tái)執(zhí)行alloc和init方法。所以,當(dāng)應(yīng)用程序啟動(dòng)時(shí),會(huì)分配并初始化一個(gè)AppController實(shí)例。在執(zhí)行 init方法期間,所有IBOutlet實(shí)例變量都為nil。只有創(chuàng)建了nib文件中得所有對(duì)象(這包括窗口和文本域和按鈕),所有連接才算完成。

一旦建立了所有連接(也就是將NSTextField對(duì)象的地址添加到AppController的實(shí)例變量中),會(huì)向創(chuàng)建的每個(gè)對(duì)象發(fā)送消息 awakeFromNib。一個(gè)非常常見(jiàn)的錯(cuò)誤是試圖在init方法中使用IBOutlet執(zhí)行一些操作。由于所有實(shí)例變量都為nil,發(fā)送給他們的所有 消息不執(zhí)行任何操作,所以在init中得任何嘗試都會(huì)發(fā)生無(wú)提示失敗。(這是Cocoa導(dǎo)致效率低和占用大量調(diào)試時(shí)間的一個(gè)方面)。如果你想知道為什么這 些操作不起作用,可以使用NSLog輸出實(shí)例變量的值,并查看他們是否都為nil。對(duì)于創(chuàng)建的對(duì)象和發(fā)送的awakeFromNib消息,都不存在預(yù)定義 順序。

文件加載與保存

49.屬性列表

1)自動(dòng)釋放對(duì)象

NSDate

NSData NSData對(duì)象是不可改變的。他們被創(chuàng)建后就不能改變。可以使用他們,但不能改變其中的內(nèi)容。

2)編碼對(duì)象 編碼和解碼

cocoa具備一種機(jī)制來(lái)將對(duì)象自身轉(zhuǎn)換為某種格式并保存到磁盤(pán)中。對(duì)象可以將他們的實(shí)例變量和其他數(shù)據(jù)塊編碼為數(shù)據(jù)塊,然后保存到磁盤(pán)中。以后將這些數(shù)據(jù)塊讀回到內(nèi)存中,并且還能基于保存的數(shù)據(jù)創(chuàng)建新對(duì)象。這個(gè)過(guò)程稱為編碼和解碼?;蚍Q為序列化和反序列化。

50.鍵/值編碼 KVC

是一種間接改變對(duì)象狀態(tài)的方式,其實(shí)現(xiàn)方法是使用字符串描述要更改的對(duì)象狀態(tài)部分。

1)valueForKey與setValue:forKey:

這兩種方法的工作方式相同。他們首先查找名稱的setter(getter)方法,如果不存在setter(getter)方法,他們將在類(lèi)中查找名為名稱或_名稱的實(shí)例變量。然后給它賦值(取值)。無(wú)需通過(guò)對(duì)象指針直接訪問(wèn)實(shí)例變量。

2)路徑

鍵路徑的深度是任意的,具體取決于對(duì)象圖。

鍵路徑不僅能引用對(duì)象值,還可以引用一些運(yùn)算符來(lái)進(jìn)行一些運(yùn)算,例如獲取一組值的平均值或返回這組值中得最小值和最大值。

例如:NSNumber *count;

count = [garage valueForKeyPath:@"cars.@count"];

NSLog(@"We have %@ cars", count);

我們將路徑“cars.@count”拆開(kāi),cars用于獲取cars屬性,它是來(lái)自garage的NSArray類(lèi)型的值。接下來(lái)的部分是@count ,其中@符號(hào)意味著后面將進(jìn)行一些運(yùn)算。

和 cars@sun.mileage

最大值 cars@min.mileage

最小值 cars@max.mileage

3)整體操作

KVC非常棒的一點(diǎn)是,如果向NSArray請(qǐng)求一個(gè)鍵值,它實(shí)際上會(huì)查詢數(shù)組中得每個(gè)對(duì)象來(lái)查找這個(gè)鍵值,然后將查詢結(jié)果打包到另一個(gè)數(shù)組中并返回給你。這種方法也適用于通過(guò)鍵路徑訪問(wèn)的對(duì)象內(nèi)部的數(shù)組。

4)批處理

KVC包含兩個(gè)調(diào)用,可以使用他們對(duì)對(duì)象進(jìn)行批量更改。第一個(gè)調(diào)用是dictionaryWith-ValuesForKeys:。它接受一個(gè)字符串?dāng)?shù)組。該調(diào)用獲取一些鍵,對(duì)每個(gè)鍵使用valueForKey:,然后為鍵字符串和剛才獲取的值構(gòu)建一個(gè)字典。

1、Object-C有多繼承嗎?沒(méi)有的話用什么代替?cocoa 中所有的類(lèi)都是NSObject 的子類(lèi)

多繼承在這里是用protocol 委托代理 來(lái)實(shí)現(xiàn)的

你不用去考慮繁瑣的多繼承 ,虛基類(lèi)的概念.

ood的多態(tài)特性 在 obj-c 中通過(guò)委托來(lái)實(shí)現(xiàn).

2、Object-C有私有方法嗎?私有變量呢?

objective-c – 類(lèi)里面的方法只有兩種, 靜態(tài)方法和實(shí)例方法. 這似乎就不是完整的面向?qū)ο罅?按照OO的原則就是一個(gè)對(duì)象只暴露有用的東西. 如果沒(méi)有了私有方法的話, 對(duì)于一些小范圍的代碼重用就不那么順手了. 在類(lèi)里面聲名一個(gè)私有方法

@interface Controller : NSObject { NSString *something; }

  • (void)thisIsAStaticMethod;

– (void)thisIsAnInstanceMethod;

@end

@interface Controller (private) -
(void)thisIsAPrivateMethod;
@end

@private可以用來(lái)修飾私有變量

在Objective‐C中,所有實(shí)例變量默認(rèn)都是私有的,所有實(shí)例方法默認(rèn)都是公有的

3、關(guān)鍵字const什么含義?
const意味著”只讀”,下面的聲明都是什么意思?
const int a;
int const a;
const int *a;
int * const a;
int const * a const;
前兩個(gè)的作用是一樣,a是一個(gè)常整型數(shù)。第三個(gè)意味著a是一個(gè)指向常整型數(shù)的指針(也就是,整型數(shù)是不可修改的,但指針可以)。第四個(gè)意思a是一個(gè)指向整 型數(shù)的常指針(也就是說(shuō),指針指向的整型數(shù)是可以修改的,但指針是不可修改的)。最后一個(gè)意味著a是一個(gè)指向常整型數(shù)的常指針(也就是說(shuō),指針指向的整型 數(shù)是不可修改的,同時(shí)指針也是不可修改的)。
結(jié)論:
?; 關(guān)鍵字const的作用是為給讀你代碼的人傳達(dá)非常有用的信息,實(shí)際上,聲明一個(gè)參數(shù)為常量是為了告訴了用戶這個(gè)參數(shù)的應(yīng)用目的。如果你曾花很多時(shí)間清理其它人留下的垃圾,你就會(huì)很快學(xué)會(huì)感謝這點(diǎn)多余的信息。(當(dāng)然,懂得用const的程序員很少會(huì)留下的垃圾讓別人來(lái)清理的。)

?; 通過(guò)給優(yōu)化器一些附加的信息,使用關(guān)鍵字const也許能產(chǎn)生更緊湊的代碼。

?; 合理地使用關(guān)鍵字const可以使編譯器很自然地保護(hù)那些不希望被改變的參數(shù),防止其被無(wú)意的代碼修改。簡(jiǎn)而言之,這樣可以減少bug的出現(xiàn)。

欲阻止一個(gè)變量被改變,可以使用 const 關(guān)鍵字。在定義該 const 變量時(shí),通常需要對(duì)它進(jìn)行初

始化,因?yàn)橐院缶蜎](méi)有機(jī)會(huì)再去改變它了;

(2)對(duì)指針來(lái)說(shuō),可以指定指針本身為 const,也可以指定指針?biāo)傅臄?shù)據(jù)為 const,或二者同時(shí)指定為 const;

(3)在一個(gè)函數(shù)聲明中,const 可以修飾形參,表明它是一個(gè)輸入?yún)?shù),在函數(shù)內(nèi)部不能改變其值;

(4)對(duì)于類(lèi)的成員函數(shù),若指定其為 const 類(lèi)型,則表明其是一個(gè)常函數(shù),不能修改類(lèi)的成員變量;

(5)對(duì)于類(lèi)的成員函數(shù),有時(shí)候必須指定其返回值為 const 類(lèi)型,以使得其返回值不為“左值”。

4、關(guān)鍵字volatile有什么含義?并給出三個(gè)不同例子?

一個(gè)定義為volatile的變量是說(shuō)這變量可能會(huì)被意想不到地改變,這樣,編譯器就不會(huì)去假設(shè)這個(gè)變量的值了。精確地說(shuō)就是,優(yōu)化器在用到

這個(gè)變量時(shí)必須每次都小心地重新讀取這個(gè)變量的值,而不是使用保存在寄存器里的備份。下面是volatile變量的幾個(gè)例子:

并行設(shè)備的硬件寄存器(如:狀態(tài)寄存器)

一個(gè)中斷服務(wù)子程序中會(huì)訪問(wèn)到的非自動(dòng)變量(Non-automatic variables)

多線程應(yīng)用中被幾個(gè)任務(wù)共享的變量

一個(gè)參數(shù)既可以是const還可以是volatile嗎?解釋為什么。

一個(gè)指針可以是volatile 嗎?解釋為什么。

下面是答案:

是的。一個(gè)例子是只讀的狀態(tài)寄存器。它是volatile因?yàn)樗赡鼙灰庀氩坏降馗淖儭K莄onst因?yàn)槌绦虿粦?yīng)該試圖去修改它。

是的。盡管這并不很常見(jiàn)。一個(gè)例子是當(dāng)一個(gè)中服務(wù)子程序修該一個(gè)指向一個(gè)buffer的指針時(shí)。

static作用?

函數(shù)體內(nèi) static 變量的作用范圍為該函數(shù)體,不同于 auto 變量,該變量的內(nèi)存只被分配一次,

因此其值在下次調(diào)用時(shí)仍維持上次的值;

(2)在模塊內(nèi)的 static 全局變量可以被模塊內(nèi)所用函數(shù)訪問(wèn),但不能被模塊外其它函數(shù)訪問(wèn);

(3)在模塊內(nèi)的 static 函數(shù)只可被這一模塊內(nèi)的其它函數(shù)調(diào)用,這個(gè)函數(shù)的使用范圍被限制在聲明

它的模塊內(nèi);

(4)在類(lèi)中的 static 成員變量屬于整個(gè)類(lèi)所擁有,對(duì)類(lèi)的所有對(duì)象只有一份拷貝;

(5)在類(lèi)中的 static 成員函數(shù)屬于整個(gè)類(lèi)所擁有,這個(gè)函數(shù)不接收 this 指針,因而只能訪問(wèn)類(lèi)的static 成員變量。

6、#import和#include的區(qū)別,@class代表什么?

@class一般用于頭文件中需要聲明該類(lèi)的某個(gè)實(shí)例變量的時(shí)候用到,在m文件中還是需要使用#import

而#import比起#include的好處就是不會(huì)引起重復(fù)包含

7、線程和進(jìn)程的區(qū)別?

進(jìn)程和線程都是由操作系統(tǒng)所體會(huì)的程序運(yùn)行的基本單元,系統(tǒng)利用該基本單元實(shí)現(xiàn)系統(tǒng)對(duì)應(yīng)用的并發(fā)性。

進(jìn)程和線程的主要差別在于它們是不同的操作系統(tǒng)資源管理方式。進(jìn)程有獨(dú)立的地址空間,一個(gè)進(jìn)程崩潰后,在保護(hù)模式下不會(huì)對(duì)其它進(jìn)程產(chǎn)生影響,而線程只是一 個(gè)進(jìn)程中的不同執(zhí)行路徑。線程有自己的堆棧和局部變量,但線程之間沒(méi)有單獨(dú)的地址空間,一個(gè)線程死掉就等于整個(gè)進(jìn)程死掉,所以多進(jìn)程的程序要比多線程的程 序健壯,但在進(jìn)程切換時(shí),耗費(fèi)資源較大,效率要差一些。但對(duì)于一些要求同時(shí)進(jìn)行并且又要共享某些變量的并發(fā)操作,只能用線程,不能用進(jìn)程。

8、堆和棧的區(qū)別?

管理方式:對(duì)于棧來(lái)講,是由編譯器自動(dòng)管理,無(wú)需我們手工控制;對(duì)于堆來(lái)說(shuō),釋放工作由程序員控制,容易產(chǎn)生memory leak。

申請(qǐng)大?。?/p>

棧:在Windows下,棧是向低地址擴(kuò)展的數(shù)據(jù)結(jié)構(gòu),是一塊連續(xù)的內(nèi)存的區(qū)域。這句話的意思是棧頂?shù)牡刂泛蜅5淖畲笕萘渴窍到y(tǒng)預(yù)先規(guī)定好的,在 WINDOWS下,棧的大小是2M(也有的說(shuō)是1M,總之是一個(gè)編譯時(shí)就確定的常數(shù)),如果申請(qǐng)的空間超過(guò)棧的剩余空間時(shí),將提示overflow。因 此,能從棧獲得的空間較小。

堆:堆是向高地址擴(kuò)展的數(shù)據(jù)結(jié)構(gòu),是不連續(xù)的內(nèi)存區(qū)域。這是由于系統(tǒng)是用鏈表來(lái)存儲(chǔ)的空閑內(nèi)存地址的,自然是不連續(xù)的,而鏈表的遍歷方向是由低地址向高地址。堆的大小受限于計(jì)算機(jī)系統(tǒng)中有效的虛擬內(nèi)存。由此可見(jiàn),堆獲得的空間比較靈活,也比較大。

碎片問(wèn)題:對(duì)于堆來(lái)講,頻繁的new/delete勢(shì)必會(huì)造成內(nèi)存空間的不連續(xù),從而造成大量的碎片,使程序效率降低。對(duì)于棧來(lái)講,則不會(huì)存在這個(gè)問(wèn)題,因?yàn)闂J窍冗M(jìn)后出的隊(duì)列,他們是如此的一一對(duì)應(yīng),以至于永遠(yuǎn)都不可能有一個(gè)內(nèi)存塊從棧中間彈出

分配方式:堆都是動(dòng)態(tài)分配的,沒(méi)有靜態(tài)分配的堆。棧有2種分配方式:靜態(tài)分配和動(dòng)態(tài)分配。靜態(tài)分配是編譯器完成的,比如局部變量的分配。動(dòng)態(tài)分配由alloca函數(shù)進(jìn)行分配,但是棧的動(dòng)態(tài)分配和堆是不同的,他的動(dòng)態(tài)分配是由編譯器進(jìn)行釋放,無(wú)需我們手工實(shí)現(xiàn)。

分配效率:棧是機(jī)器系統(tǒng)提供的數(shù)據(jù)結(jié)構(gòu),計(jì)算機(jī)會(huì)在底層對(duì)棧提供支持:分配專(zhuān)門(mén)的寄存器存放棧的地址,壓棧出棧都有專(zhuān)門(mén)的指令執(zhí)行,這就決定了棧的效率比較高。堆則是C/C++函數(shù)庫(kù)提供的,它的機(jī)制是很復(fù)雜的。

9、Object-C的內(nèi)存管理?

1.當(dāng)你使用new,alloc和copy方法創(chuàng)建一個(gè)對(duì)象時(shí),該對(duì)象的保留計(jì)數(shù)器值為1.當(dāng)你不再使用該對(duì)象時(shí),你要負(fù)責(zé)向該對(duì)象發(fā)送一條release或autorelease消息.這樣,該對(duì)象將在使用壽命結(jié)束時(shí)被銷(xiāo)毀.

2.當(dāng)你通過(guò)任何其他方法獲得一個(gè)對(duì)象時(shí),則假設(shè)該對(duì)象的保留計(jì)數(shù)器值為1,而且已經(jīng)被設(shè)置為自動(dòng)釋放,你不需要執(zhí)行任何操作來(lái)確保該對(duì)象被清理.如果你打算在一段時(shí)間內(nèi)擁有該對(duì)象,則需要保留它并確保在操作完成時(shí)釋放它.

3.如果你保留了某個(gè)對(duì)象,你需要(最終)釋放或自動(dòng)釋放該對(duì)象.必須保持retain方法和release方法的使用次數(shù)相等.

10、為什么很多內(nèi)置的類(lèi),如TableViewController的delegate的屬性是assign不是retain?

循環(huán)引用

所有的引用計(jì)數(shù)系統(tǒng),都存在循環(huán)應(yīng)用的問(wèn)題。例如下面的引用關(guān)系:

對(duì)象a創(chuàng)建并引用到了對(duì)象b.

對(duì)象b創(chuàng)建并引用到了對(duì)象c.

對(duì)象c創(chuàng)建并引用到了對(duì)象b.

這時(shí)候b和c的引用計(jì)數(shù)分別是2和1。當(dāng)a不再使用b,調(diào)用release釋放對(duì)b的所有權(quán),因?yàn)閏還引用了b,所以b的引用計(jì)數(shù)為1,b不會(huì)被釋放。b不釋放,c的引用計(jì)數(shù)就是1,c也不會(huì)被釋放。從此,b和c永遠(yuǎn)留在內(nèi)存中。

這種情況,必須打斷循環(huán)引用,通過(guò)其他規(guī)則來(lái)維護(hù)引用關(guān)系。比如,我們常見(jiàn)的delegate往往是assign方式的屬性而不是retain方式的屬 性,賦值不會(huì)增加引用計(jì)數(shù),就是為了防止delegation兩端產(chǎn)生不必要的循環(huán)引用。如果一個(gè)UITableViewController 對(duì)象a通 過(guò)retain獲取了UITableView對(duì)象b的所有權(quán),這個(gè)UITableView對(duì)象b的delegate又是a,如果這個(gè)delegate是 retain方式的,那基本上就沒(méi)有機(jī)會(huì)釋放這兩個(gè)對(duì)象了。自己在設(shè)計(jì)使用delegate模式時(shí),也要注意這點(diǎn)。

11、定義屬性時(shí),什么情況使用copy、assign、retain?

assign用于簡(jiǎn)單數(shù)據(jù)類(lèi)型,如NSInteger,double,bool,

retain和copy用于對(duì)象,

copy用于當(dāng)a指向一個(gè)對(duì)象,b也想指向同樣的對(duì)象的時(shí)候,如果用assign,a如果釋放,再調(diào)用b會(huì)crash,如果用copy 的方式,a和b各自有自己的內(nèi)存,就可以解決這個(gè)問(wèn)題。

retain 會(huì)使計(jì)數(shù)器加一,也可以解決assign的問(wèn)題。

另外:atomic和nonatomic用來(lái)決定編譯器生成的getter和setter是否為原子操作。在多線程環(huán)境下,原子操作是必要的,否則有可能引起錯(cuò)誤的結(jié)果。

加了atomic,setter函數(shù)會(huì)變成下面這樣:

if (property != newValue) {

[property release];

property = [newValue retain];

}

12、對(duì)象是什么時(shí)候被release的?

引用計(jì)數(shù)為0時(shí)。

autorelease實(shí)際上只是把對(duì)release的調(diào)用延遲了,對(duì)于每一個(gè)Autorelease,系統(tǒng)只是把該Object放入了當(dāng)前的 Autorelease pool中,當(dāng)該pool被釋放時(shí),該pool中的所有Object會(huì)被調(diào)用Release。對(duì)于每一個(gè)Runloop,系統(tǒng)會(huì) 隱式創(chuàng)建一個(gè)Autorelease pool,這樣所有的release pool會(huì)構(gòu)成一個(gè)象CallStack一樣的一個(gè)棧式結(jié)構(gòu),在每一個(gè) Runloop結(jié)束時(shí),當(dāng)前棧頂?shù)腁utorelease pool會(huì)被銷(xiāo)毀,這樣這個(gè)pool里的每個(gè)Object(就是autorelease的對(duì) 象)會(huì)被release。那什么是一個(gè)Runloop呢?一個(gè)UI事件,Timer call, delegate call, 都會(huì)是一個(gè)新的 Runloop

13、iOS有沒(méi)有垃圾回收?

Objective-C 2.0也是有垃圾回收機(jī)制的,但是只能在Mac OS X Leopard 10.5 以上的版本使用。

14、tableView的重用機(jī)制?

查看UITableView頭文件,會(huì)找到NSMutableArray* visiableCells,和 NSMutableDictnery* reusableTableCells兩個(gè)結(jié)構(gòu)。visiableCells內(nèi)保存當(dāng)前顯示的 cells,reusableTableCells保存可重用的cells。

TableView顯示之初,reusableTableCells為空,那么 tableView dequeueReusableCellWithIdentifier:CellIdentifier返回nil。開(kāi)始的cell都 是通過(guò) [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] 來(lái)創(chuàng)建,而且cellForRowAtIndexPath只是調(diào)用最大顯示cell數(shù)的次數(shù)。

比如:有100條數(shù)據(jù),iPhone一屏最多顯示10個(gè)cell。程序最開(kāi)始顯示TableView的情況是:

1.用 [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] 創(chuàng)建10次cell,并給cell指定同樣的重用標(biāo)識(shí)(當(dāng)然,可以為不同顯示類(lèi)型的cell指定不同的標(biāo)識(shí))。并且10個(gè)cell全部都加入到 visiableCells數(shù)組,reusableTableCells為空。

2.向下拖動(dòng)tableView,當(dāng)cell1完全移出屏幕,并且cell11(它也是alloc出來(lái)的,原因同上)完全顯示出來(lái)的時(shí)候。 cell11加入到visiableCells,cell1移出visiableCells,cell1加入到reusableTableCells。

3.接著向下拖動(dòng)tableView,因?yàn)閞eusableTableCells中已經(jīng)有值,所以,當(dāng)需要顯示新的 cell,cellForRowAtIndexPath再次被調(diào)用的時(shí) 候,tableView dequeueReusableCellWithIdentifier:CellIdentifier,返回cell1。 cell1加入到visiableCells,cell1移出reusableTableCells;cell2移出 visiableCells,cell2加入到reusableTableCells。之后再需要顯示的Cell就可以正常重用了。

15、ViewController 的loadView、viewDidLoad、viewDidUnload分別是什么時(shí)候調(diào)用的,在自定義ViewCointroller時(shí)在這幾個(gè)函數(shù)中應(yīng)該做什么工作?

由init、loadView、viewDidLoad、viewDidUnload、dealloc的關(guān)系說(shuō)起

init方法

在init方法中實(shí)例化必要的對(duì)象(遵從LazyLoad思想)

init方法中初始化ViewController本身

loadView方法

當(dāng)view需要被展示而它卻是nil時(shí),viewController會(huì)調(diào)用該方法。不要直接調(diào)用該方法。

如果手工維護(hù)views,必須重載重寫(xiě)該方法

如果使用IB維護(hù)views,必須不能重載重寫(xiě)該方法

loadView和IB構(gòu)建view

你在控制器中實(shí)現(xiàn)了loadView方法,那么你可能會(huì)在應(yīng)用運(yùn)行的某個(gè)時(shí)候被內(nèi)存管理控制調(diào)用。 如果設(shè)備內(nèi)存不足的時(shí)候, view 控制器會(huì)收到 didReceiveMemoryWarning的消息。 默認(rèn)的實(shí)現(xiàn)是檢查當(dāng)前控制器的view是否在使用。如果它的view不在當(dāng)前正在使用的 view hierarchy里面,且你的控制器實(shí)現(xiàn)了loadView方法,那么這個(gè)view將被release, loadView方法將被再次調(diào)用 來(lái)創(chuàng)建一個(gè)新的view。

viewDidLoad方法

viewDidLoad 此方法只有當(dāng)view從nib文件初始化的時(shí)候才被調(diào)用。

重載重寫(xiě)該方法以進(jìn)一步定制view

在iPhone OS 3.0及之后的版本中,還應(yīng)該重載重寫(xiě)viewDidUnload來(lái)釋放對(duì)view的任何索引

viewDidLoad后調(diào)用數(shù)據(jù)Model

viewDidUnload方法

當(dāng)系統(tǒng)內(nèi)存吃緊的時(shí)候會(huì)調(diào)用該方法(注:viewController沒(méi)有被dealloc)

內(nèi)存吃緊時(shí),在iPhone OS 3.0之前didReceiveMemoryWarning是釋放無(wú)用內(nèi)存的唯一方式,但是OS 3.0及以后viewDidUnload方法是更好的方式

在該方法中將所有IBOutlet(無(wú)論是property還是實(shí)例變量)置為nil(系統(tǒng)release view時(shí)已經(jīng)將其release掉了)

在該方法中釋放其他與view有關(guān)的對(duì)象、其他在運(yùn)行時(shí)創(chuàng)建(但非系統(tǒng)必須)的對(duì)象、在viewDidLoad中被創(chuàng)建的對(duì)象、緩存數(shù)據(jù) 等 release對(duì)象后,將對(duì)象置為nil(IBOutlet只需要將其置為nil,系統(tǒng)release view時(shí)已經(jīng)將其release掉了)

一般認(rèn)為viewDidUnload是viewDidLoad的鏡像,因?yàn)楫?dāng)view被重新請(qǐng)求時(shí),viewDidLoad還會(huì)重新被執(zhí)行

viewDidUnload中被release的對(duì)象必須是很容易被重新創(chuàng)建的對(duì)象(比如在viewDidLoad或其他方法中創(chuàng)建的對(duì)象),不要release用戶數(shù)據(jù)或其他很難被重新創(chuàng)建的對(duì)象

dealloc方法

viewDidUnload和dealloc方法沒(méi)有關(guān)聯(lián),dealloc還是繼續(xù)做它該做的事情

16、ViewController的didReceiveMemoryWarning是在什么時(shí)候調(diào)用的?默認(rèn)的操作是什么?

當(dāng)程序接到內(nèi)存警告時(shí)View Controller將會(huì)收到這個(gè)消息:didReceiveMemoryWarning

從iOS3.0開(kāi)始,不需要重載這個(gè)函數(shù),把釋放內(nèi)存的代碼放到viewDidUnload中去。

這個(gè)函數(shù)的默認(rèn)實(shí)現(xiàn)是:檢查controller是否可以安全地釋放它的view(這里加粗的view指的是controller的view屬性),比如view本身沒(méi)有superview并且可以被很容易地重建(從nib或者loadView函數(shù))。

如果view可以被釋放,那么這個(gè)函數(shù)釋放view并調(diào)用viewDidUnload。

你可以重載這個(gè)函數(shù)來(lái)釋放controller中使用的其他內(nèi)存。但要記得調(diào)用這個(gè)函數(shù)的super實(shí)現(xiàn)來(lái)允許父類(lèi)(一般是UIVIewController)釋放view。

如果你的ViewController保存著view的子view的引用,那么,在早期的iOS版本中,你應(yīng)該在這個(gè)函數(shù)中來(lái)釋放這些引用。而在iOS3.0或更高版本中,你應(yīng)該在viewDidUnload中釋放這些引用。

17、列舉Cocoa中常見(jiàn)的集中多線程的實(shí)現(xiàn),并談?wù)劧嗑€程安全的幾種解決辦法,一般什么地方會(huì)用到多線程?

NSThread,GCD等。盡量用上層分裝好的方法去實(shí)現(xiàn)多線程而不是手動(dòng)調(diào)用NSThread。

18、怎么理解MVC,在Cocoa中MVC是怎么實(shí)現(xiàn)的?

Model: 代表你的應(yīng)用程序是什么(不是怎么展現(xiàn))

Controller: 控制你的Model怎么展現(xiàn)給用戶(UI邏輯)

View: Controller的奴隸。。。

1 Model,Controller,View相互通訊的規(guī)則:

Controller可以直接和Model通信

Controller也可以直接和View通信

Model和View永遠(yuǎn)不能直接通信

iOS中View和Controller的通信是透明和固定的,主要通過(guò)outlet和action實(shí)現(xiàn)

View使用Delegate接口和Controller同步信息

View不直接和數(shù)據(jù)通信,使用dataSource接口從Controller處獲取數(shù)據(jù)

View的delegate和dataSource一般就是Controller

Controller負(fù)責(zé)為View翻譯和格式化Model的數(shù)據(jù)

Model使用Notification & KVO的方式分發(fā)數(shù)據(jù)更新信息,Controller可以有選擇的監(jiān)聽(tīng)自己感興趣的信息。

View也可以監(jiān)聽(tīng)廣播信息,但一般不是Model發(fā)出的信息

一個(gè)完整的App就是很多MVC的集合

19、delegate和notification區(qū)別,分別在什么情況下使用?

Delegate:

消息的發(fā)送者(sender)告知接收者(receiver)某個(gè)事件將要發(fā)生,delegate同意然然后發(fā)送者響應(yīng)事件,delegate機(jī)制使得接收者可以改變發(fā)送者的行為。通常發(fā)送者和接收者的關(guān)系是直接的一對(duì)多的關(guān)系。

Notification:

消息的發(fā)送者告知接收者事件已經(jīng)發(fā)生或者將要發(fā)送,僅此而已,接收者并不能反過(guò)來(lái)影響發(fā)送者的行為。通常發(fā)送者和接收者的關(guān)系是間接的多對(duì)多關(guān)系。

  1. 效率肯定是delegate比nsnotification高。
  1. delegate方法比notification更加直接,最典型的特征是,delegate方法往往需要關(guān)注返回值,也就是delegate方法 的結(jié)果。比如-windowShouldClose:,需要關(guān)心返回的是yes還是no。所以delegate方法往往包含should這個(gè)很傳神的詞。 也就是好比你做我的delegate,我會(huì)問(wèn)你我想關(guān)閉窗口你愿意嗎?你需要給我一個(gè)答案,我根據(jù)你的答案來(lái)決定如何做下一步。相反 的,notification最大的特色就是不關(guān)心接受者的態(tài)度,我只管把通告放出來(lái),你接受不接受就是你的事情,同時(shí)我也不關(guān)心結(jié)果。所以 notification往往用did這個(gè)詞匯,比如NSWindowDidResizeNotification,那么nswindow對(duì)象放出這個(gè) notification后就什么都不管了也不會(huì)等待接受者的反應(yīng)。

1)兩個(gè)模塊之間聯(lián)系不是很緊密,就用notification傳值,例如多線程之間傳值用notificaiton。

2)delegate只是一種較為簡(jiǎn)單的回調(diào),且主要用在一個(gè)模塊中,例如底層功能完成了,需要把一些值傳到上層去,就事先把上層的函數(shù)通過(guò) delegate傳到底層,然后在底層call這個(gè)delegate,它們都在一個(gè)模塊中,完成一個(gè)功能,例如 說(shuō) NavgationController 從 B 界面到A 點(diǎn)返回按鈕 (調(diào)用popViewController方法) 可以用delegate 比較好
20、self.跟self什么區(qū)別?

21、id、nil代表什么?

id和void *并非完全一樣。在上面的代碼中,id是指向struct objc_object的一個(gè)指針,這個(gè)意思基本上是說(shuō),id是一個(gè)指向任何 一個(gè)繼承了Object(或者NSObject)類(lèi)的對(duì)象。需要注意的是id是一個(gè)指針,所以你在使用id的時(shí)候不需要加星號(hào)。比如id foo=nil 定義了一個(gè)nil指針,這個(gè)指針指向NSObject的一個(gè)任意子類(lèi)。而id *foo=nil則定義了一個(gè)指針,這個(gè)指針指向另一個(gè)指針,被指向的這個(gè) 指針指向NSObject的一個(gè)子類(lèi)。

nil和C語(yǔ)言的NULL相同,在objc/objc.h中定義。nil表示一個(gè)Objctive-C對(duì)象,這個(gè)對(duì)象的指針指向空(沒(méi)有東西就是空)。

首字母大寫(xiě)的Nil和nil有一點(diǎn)不一樣,Nil定義一個(gè)指向空的類(lèi)(是Class,而不是對(duì)象)。

SEL是“selector”的一個(gè)類(lèi)型,表示一個(gè)方法的名字

Method(我們常說(shuō)的方法)表示一種類(lèi)型,這種類(lèi)型與selector和實(shí)現(xiàn)(implementation)相關(guān)

IMP定義為 id (*IMP) (id, SEL, …)。這樣說(shuō)來(lái), IMP是一個(gè)指向函數(shù)的指針,這個(gè)被指向的函數(shù)包括id(“self”指針),調(diào)用的SEL(方法名),再加上一些其他參數(shù).說(shuō)白了IMP就是實(shí)現(xiàn)方法。

22、內(nèi)存管理 Autorelease、retain、copy、assign的set方法和含義?

1,你初始化(alloc/init)的對(duì)象,你需要釋放(release)它。例如:

NSMutableArray aArray = [[NSArray alloc] init]; 后,需要 [aArray release];

2,你retain或copy的,你需要釋放它。例如:

[aArray retain] 后,需要 [aArray release];

3,被傳遞(assign)的對(duì)象,你需要斟酌的retain和release。例如:

obj2 = [[obj1 someMethod] autorelease];

對(duì)象2接收對(duì)象1的一個(gè)自動(dòng)釋放的值,或傳遞一個(gè)基本數(shù)據(jù)類(lèi)型(NSInteger,NSString)時(shí):你或希望將對(duì)象2進(jìn)行retain,以防止它在被使用之前就被自動(dòng)釋放掉。但是在retain后,一定要在適當(dāng)?shù)臅r(shí)候進(jìn)行釋放。

關(guān)于索引計(jì)數(shù)(Reference Counting)的問(wèn)題

retain值 = 索引計(jì)數(shù)(Reference Counting)

NSArray對(duì)象會(huì)retain(retain值加一)任何數(shù)組中的對(duì)象。當(dāng)NSArray被卸載(dealloc)的時(shí)候,所有數(shù)組中的對(duì)象會(huì)被 執(zhí)行一次釋放(retain值減一)。不僅僅是NSArray,任何收集類(lèi)(Collection Classes)都執(zhí)行類(lèi)似操作。例如 NSDictionary,甚至UINavigationController。

Alloc/init建立的對(duì)象,索引計(jì)數(shù)為1。無(wú)需將其再次retain。

[NSArray array]和[NSDate date]等“方法”建立一個(gè)索引計(jì)數(shù)為1的對(duì)象,但是也是一個(gè)自動(dòng)釋放對(duì)象。所以是本地臨時(shí)對(duì)象,那么無(wú)所謂了。如果是打算在全Class中使用的變量(iVar),則必須retain它。

缺省的類(lèi)方法返回值都被執(zhí)行了“自動(dòng)釋放”方法。(*如上中的NSArray)

在類(lèi)中的卸載方法“dealloc”中,release所有未被平衡的NS對(duì)象。(*所有未被autorelease,而retain值為1的)

23、類(lèi)別的作用?

有時(shí)我們需要在一個(gè)已經(jīng)定義好的類(lèi)中增加一些方法,而不想去重寫(xiě)該類(lèi)。比如,當(dāng)工程已經(jīng)很大,代碼量比較多,或者類(lèi)中已經(jīng)包住很多方法,已經(jīng)有其他代碼調(diào)用了該類(lèi)創(chuàng)建對(duì)象并使用該類(lèi)的方法時(shí),可以使用類(lèi)別對(duì)該類(lèi)擴(kuò)充新的方法。

注意:類(lèi)別只能擴(kuò)充方法,而不能擴(kuò)充成員變量。

24、委托(舉例)

委托代理(degegate),顧名思義,把某個(gè)對(duì)象要做的事情委托給別的對(duì)象去做。那么別的對(duì)象就是這個(gè)對(duì)象的代理,代替它來(lái)打理要做的事。反映到程序中,首先要明確一個(gè)對(duì)象的委托方是哪個(gè)對(duì)象,委托所做的內(nèi)容是什么。

委托機(jī)制是一種設(shè)計(jì)模式,在很多語(yǔ)言中都用到的,這只是個(gè)通用的思想,網(wǎng)上會(huì)有很多關(guān)于這方面的介紹。

那么在蘋(píng)果開(kāi)發(fā)過(guò)程中,用到委托的程序?qū)崿F(xiàn)思想如下,我主要拿如何在視圖之間傳輸信息做個(gè)例子。

譬如:在兩個(gè)頁(yè)面(UIIview視圖對(duì)象)實(shí)現(xiàn)傳值,用委托(delegate)可以很好做到!

方法:

類(lèi)A

@interface A:UIView

id transparendValueDelegate;

@property(nomatic, retain) id transparendValueDelegate;

@end

@implemtion A

@synthesize transparendValueDelegate

-(void)Function

{

NSString* value = @"hello";

//讓代理對(duì)象執(zhí)行transparendValue動(dòng)作

[transparendValueDelegate transparendValue: value];

}

@end

類(lèi)B

@interface B:UIView

NSString* value;

@end

@implemtion B

-(void)transparendValue:(NSString*)fromValue

{

value = fromValue;

NSLog(@"the value is %@ ",value);

}

@end

//下面的設(shè)置A代理委托對(duì)象為B

//在定義A和B類(lèi)對(duì)象處:

A* a = [[A alloc] init];

B* b = [[B alloc] init];

a. transparendValueDelegate = b;//設(shè)置對(duì)象a代理為對(duì)象b

這樣在視圖A和B之間可以通過(guò)委托來(lái)傳值!

25、retainCount?

26..屬性readwrite,readonly,assign,retain,copy,nonatomic 各是什么作用,在那種情況下用

assign:指定setter方法用簡(jiǎn)單的賦值,這是默認(rèn)操作。你可以對(duì)標(biāo)量類(lèi)型(如int)使用這個(gè)屬性。你可以想象一個(gè)float,它不是一個(gè)對(duì)象,所以它不能retain、copy。

retain:指定retain應(yīng)該在后面的對(duì)象上調(diào)用,前一個(gè)值發(fā)送一條release消息。你可以想象一個(gè)NSString實(shí)例,它是一個(gè)對(duì)象,而且你可能想要retain它。

copy:指定應(yīng)該使用對(duì)象的副本(深度復(fù)制),前一個(gè)值發(fā)送一條release消息。基本上像retain,但是沒(méi)有增加引用計(jì)數(shù),是分配一塊新的內(nèi)存來(lái)放置它。

readonly:將只生成getter方法而不生成setter方法(getter方法沒(méi)有g(shù)et前綴)。

readwrite:默認(rèn)屬性,將生成不帶額外參數(shù)的getter和setter方法(setter方法只有一個(gè)參數(shù))。

atomic:對(duì)于對(duì)象的默認(rèn)屬性,就是setter/getter生成的方法是一個(gè)原子操作。如果有多個(gè)線程同時(shí)調(diào)用setter的話,不會(huì)出現(xiàn)某一個(gè)線程執(zhí)行setter全部語(yǔ)句之前,另一個(gè)線程開(kāi)始執(zhí)行setter的情況,相關(guān)于方法頭尾加了鎖一樣。

nonatomic:不保證setter/getter的原子性,多線程情況下數(shù)據(jù)可能會(huì)有問(wèn)題。

27.類(lèi)變量的@protected ,@private ,@public ,@package聲明各有什么含義

Objective-C 對(duì)存取權(quán)限的設(shè)定。也是變量的作用域。

protected 該類(lèi)和所有的子類(lèi)中的方法可以直接訪問(wèn)這樣的變量,這是默認(rèn)的。

private — 該類(lèi)中的方法可以訪問(wèn)這樣的變量,子類(lèi)不可以。 public — 除了自己和子類(lèi)中的方法外,也可以被其他類(lèi)或者其他模塊中的方法所訪問(wèn)。開(kāi)放性最大。 package — 對(duì)于64位圖像,這樣的成員變量可以在實(shí)現(xiàn)這個(gè)類(lèi)的圖像中隨意訪問(wèn)。

28.淺拷貝和深拷貝區(qū)別是什么

簡(jiǎn)單的來(lái)說(shuō)就是,在有指針的情況下,淺拷貝只是增加了一個(gè)指針指向已經(jīng)存在的內(nèi)存,而深拷貝就是增加一個(gè)指針并且申請(qǐng)一個(gè)新的內(nèi)存,使這個(gè)增加的指針指向這個(gè)新的內(nèi)存,采用深拷貝的情況下,釋放內(nèi)存的時(shí)候就不會(huì)出現(xiàn)在淺拷貝時(shí)重復(fù)釋放同一內(nèi)存的錯(cuò)誤

29.Cocoa中與虛基類(lèi)的概念么?怎么簡(jiǎn)潔的實(shí)現(xiàn)

30.NSString 和 NSMutableString 有什么區(qū)別

NSString相當(dāng)于一個(gè)const char* 不可以改變。

而 NSMutableString相當(dāng)于 char* 可以改變內(nèi)部的內(nèi)容。

31.自動(dòng)釋放池跟GC有什么區(qū)別?iPhone上有GC么?[pool release] 和[pool drain]有什么區(qū)別

”Autorelease Pools”(自動(dòng)釋放池)在應(yīng)用中的使用技巧。

1,Autorelease Pools概要

一個(gè)”Autorelease Pool”實(shí)例中“包含”其它各種調(diào)用了”autorelease”方法的對(duì)象。當(dāng)它釋放時(shí),其中所有被管理對(duì)象都會(huì)收 到”relrease”的消信。注意,同一個(gè)對(duì)象可以被多次調(diào)用”autorelease”方法,并可以放到同一個(gè)”Autorelease Pool” 中。引入這個(gè)自動(dòng)釋放池機(jī)制,對(duì)象的”autorelease”方法代替”relrease”方法可以延長(zhǎng)它的生命周期,直接到當(dāng) 前”Autorelrease Pool”釋放。如果想讓此對(duì)象的生命周期超過(guò)”Autorelease Pool”,還可以再次”retain”,呵 呵,有意思吧?且讓我慢慢道來(lái)。

Cocoa總是認(rèn)為當(dāng)前至少有一個(gè)”Autorelease Pool”對(duì)象是可用的。若此對(duì)象并不存在,你調(diào)用的”autorelease”的所有對(duì)象都不會(huì)被自動(dòng)釋放掉,可想而知,造成內(nèi)存泄露。Cocoa把這個(gè)錯(cuò)誤信息寫(xiě)入日志??僅僅是為了以后分析。

你可以用”alloc”與”init”方法創(chuàng)建一個(gè)”NSAutoreleasePool”對(duì)象,并且可以調(diào)用”release”或”drain” (”release”與”drain”的區(qū)別是”drain”在有GC的環(huán)境中會(huì)引起GC回收操作,”release”反之。但在非GC環(huán)境中,兩者相 同。官方的說(shuō)法是為了程序的兼容性,應(yīng)該考慮用”drain”代替”release”,)方法來(lái)回收它(調(diào)用它的”autorelease” 或”retain”方法會(huì)引起異常)。在一個(gè)完整的上下文最后”Autorelease Pool”對(duì)象應(yīng)該被”release”掉(在方法內(nèi)或一段循環(huán) 體內(nèi)創(chuàng)建的”Autorelease Pool”對(duì)象)。

“Autorelease Pools”的所有實(shí)例在棧中管理(我們暫時(shí)叫他“自動(dòng)釋放池?!保?,并且它們是可以被嵌套的(父生子,子生孫。。。子子孫 孫 _)。例如,當(dāng)我們創(chuàng)建一個(gè)”Autorelease Pool”對(duì)象后,它就被自動(dòng)放到“自動(dòng)釋放池棧”的棧頂。當(dāng)本池對(duì)象回收時(shí),它就隨之從 這個(gè)棧中POP掉。那么也就是說(shuō),當(dāng)任何一個(gè)對(duì)象調(diào)用”autorelease”方法后,它會(huì)被放入當(dāng)前線程中當(dāng)前棧頂?shù)淖詣?dòng)釋放池中。

接下來(lái)我們聊聊”Autorelease Pools”的嵌套問(wèn)題。在你的應(yīng)用中,你可以任意多的創(chuàng)建”Autorelease Pool”對(duì)象,而這些 對(duì)象被當(dāng)前線程的“自動(dòng)釋放池?!彼芾怼D敲闯艘粋€(gè)接一個(gè)的順序創(chuàng)建并銷(xiāo)毀它的情況外,還有一種使用方式,就是嵌套式的創(chuàng)建與使用。例如:在你的主函 數(shù)創(chuàng)建了一個(gè)”autorelease pool”,然后又調(diào)用了創(chuàng)建了”autorelease pool”實(shí)例的其它方法;或是在外循環(huán)中創(chuàng)建 了”Autorelease Pool”的實(shí)例,而內(nèi)循環(huán)中也做了相同的事情。有意思吧,呵呵,嵌套的機(jī)制使父Pool實(shí)例釋放后,它的所有子Pool也 將釋放。但這里還存在一些副作用,后續(xù)文章會(huì)詳細(xì)討論。

“Application kit”在一個(gè)事件循環(huán)里會(huì)自動(dòng)創(chuàng)建一個(gè)”autorelease pool”。像鼠標(biāo)鍵的按下與釋放,所以你編寫(xiě)的代碼通常不需要考慮太多這方面的事情。當(dāng)然,有以下三種情況你會(huì)創(chuàng)建與銷(xiāo)毀自己的Pool實(shí)例:

1,應(yīng)用不是基于”Application Kit”,像”Command-line tool”,因?yàn)樗](méi)有內(nèi)置的”autorelease pools”的支持。

2,創(chuàng)建線程,你必需在線程開(kāi)始時(shí)創(chuàng)建一個(gè)”Autorelease Pool”實(shí)例。反之,會(huì)造成內(nèi)存池露(會(huì)在以后的文章詳細(xì)說(shuō)明線程與池的技巧)。

3,一個(gè)循環(huán)內(nèi)創(chuàng)建了太多的臨時(shí)對(duì)象,你應(yīng)該為他們創(chuàng)建一個(gè)”Autorelease Pool”對(duì)象,并在下次循還前銷(xiāo)毀它們。

2,自動(dòng)釋放池中的”Non-AppKit”應(yīng)用

在”Non-AppKit”應(yīng)用中使用自動(dòng)釋放池的機(jī)制其實(shí)是相當(dāng)簡(jiǎn)單的事情。你僅僅需要在main()起始處創(chuàng)建”Autorelease Pool” 對(duì)象,并在結(jié)尾處釋放掉它。就像在Xcode的Foundation Tool的創(chuàng)建模版里寫(xiě)的一樣。這個(gè)確保你在應(yīng)用生命周期內(nèi)至少有一 個(gè)”Autorelease Pool”是可用的。但是,這也使所有在此期間的所有”autorelease”的對(duì)象都必需在應(yīng)用結(jié)束后才被釋放。這也許 會(huì)引起在應(yīng)用的使用中不斷的增長(zhǎng),所以,你仍然考慮在不同的作用域創(chuàng)建新的”Autorelease Pool”。

大多應(yīng)用中都存在各種級(jí)別的循環(huán)機(jī)制。在這些應(yīng)用中,你可以在每個(gè)循環(huán)內(nèi)的開(kāi)頭創(chuàng)建一個(gè)”Autorelease Pool”對(duì)象,并在結(jié)尾處釋放掉它。

例如:

void main()

{

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

NSArray *args = [[NSProcessInfo processInfo] arguments];

unsigned count, limit = [args count];

for (count = 0; count < limit; count++)

{

NSAutoreleasePool *loopPool = [[NSAutoreleasePool alloc] init];

NSString *fileContents;

NSString *fileName;

fileName = [args objectAtIndex:count];

fileContents = [[[NSString alloc] initWithContentsOfFile:fileName] autorelease];

// this is equivalent to using stringWithContentsOfFile:

[loopPool release];

}

[pool drain];

exit (EXIT_SUCCESS);

}

在命令行中處理所有以參數(shù)傳來(lái)的文件。一次循環(huán)處理一個(gè)文件。在循環(huán)的開(kāi)頭創(chuàng)建一個(gè)”NSAutoreleasePool”對(duì)象,并在循環(huán)結(jié)束時(shí)釋放掉。 因此,任何在其中創(chuàng)建并調(diào)用“autorelease”的對(duì)象都將添加到這個(gè)Pool實(shí)例中,當(dāng)本池被釋放后,這些對(duì)象也將被回收。注意,任何在作用域內(nèi) 創(chuàng)建的”autoreleased”對(duì)象(像”fileName”),雖然并沒(méi)有顯示的調(diào)用”autorelease”方法,但都將被當(dāng)前池所管理并釋 放。

32.C和obj-c 如何混用

1)obj-c的編譯器處理后綴為m的文件時(shí),可以識(shí)別obj-c和c的代碼,處理mm文件可以識(shí)別obj-c,c,c++代碼,但cpp文件必須只能用c/c++代碼,而且cpp文件include的頭文件中,也不能出現(xiàn)obj-c的代碼,因?yàn)閏pp只是cpp

2)在mm文件中混用cpp直接使用即可,所以obj-c混cpp不是問(wèn)題

3)在cpp中混用obj-c其實(shí)就是使用obj-c編寫(xiě)的模塊是我們想要的。

如果模塊以類(lèi)實(shí)現(xiàn),那么要按照cpp class的標(biāo)準(zhǔn)寫(xiě)類(lèi)的定義,頭文件中不能出現(xiàn)obj-c的東西,包括#import cocoa的。實(shí)現(xiàn)文件中,即類(lèi)的實(shí)現(xiàn)代碼中可以使用obj-c的東西,可以import,只是后綴是mm。

如果模塊以函數(shù)實(shí)現(xiàn),那么頭文件要按c的格式聲明函數(shù),實(shí)現(xiàn)文件中,c++函數(shù)內(nèi)部可以用obj-c,但后綴還是mm或m。

總結(jié):只要cpp文件和cpp include的文件中不包含obj-c的東西就可以用了,cpp混用obj-c的關(guān)鍵是使用接口,而不能直接使用實(shí)現(xiàn)代 碼,實(shí)際上cpp混用的是obj-c編譯后的o文件,這個(gè)東西其實(shí)是無(wú)差別的,所以可以用。obj-c的編譯器支持cpp

33.響應(yīng)者鏈?zhǔn)鞘裁?/p>

響應(yīng)者鏈?zhǔn)茿pplication Kit事件處理架構(gòu)的中心機(jī)制。它由一系列鏈接在一起的響應(yīng)者對(duì)象組成,事件或者動(dòng)作消息可以沿著這些對(duì)象進(jìn)行傳 遞。如圖6-20顯示的那樣,如果一個(gè)響應(yīng)者對(duì)象不能處理某個(gè)事件或動(dòng)作-也就是說(shuō),它不響應(yīng)那個(gè)消息,或者不認(rèn)識(shí)那個(gè)事件,則將該消息重新發(fā)送給鏈中的 下一個(gè)響應(yīng)者。消息沿著響應(yīng)者鏈向上、向更高級(jí)別的對(duì)象傳遞,直到最終被處理(如果最終還是沒(méi)有被處理,就會(huì)被拋棄)。

當(dāng)Application Kit在應(yīng)用程序中構(gòu)造對(duì)象時(shí),會(huì)為每個(gè)窗口建立響應(yīng)者鏈。響應(yīng)者鏈中的基本對(duì)象是NSWindow對(duì)象及其視圖層次。在視圖層次中級(jí)別較低的視圖將比級(jí)別更高的視圖優(yōu)先獲得處理事件或動(dòng)作消息的機(jī)會(huì)。NSWindow中保有一個(gè)第一響應(yīng)者的引用,它通常是當(dāng)前窗口中處于選擇狀態(tài)的視圖,窗口通常把響應(yīng)消息的機(jī)會(huì)首先給它。對(duì)于事件消息,響應(yīng)者鏈通常以發(fā)生事件的窗口對(duì)應(yīng)的NSWindow對(duì)象作為結(jié)束,雖然其它對(duì)象也可以作為下一個(gè)響應(yīng)者被加入到NSWindow對(duì)象的后面。

34..UIscrollVew用到了什么設(shè)計(jì)模式?還能再foundation庫(kù)中找到類(lèi)似的嗎?

組合模式composition,所有的container view都用了這個(gè)模式

觀察者模式observer,所有的UIResponder都用了這個(gè)模式。

模板(Template)模式,所有datasource和delegate接口都是模板模式的典型應(yīng)用

  1. .timer的間隔周期準(zhǔn)嗎?為什么?怎樣實(shí)現(xiàn)一個(gè)精準(zhǔn)的timer?

NSTimer可以精確到50-100毫秒.

NSTimer不是絕對(duì)準(zhǔn)確的,而且中間耗時(shí)或阻塞錯(cuò)過(guò)下一個(gè)點(diǎn),那么下一個(gè)點(diǎn)就pass過(guò)去了

此份面試題包含40個(gè)題目,是現(xiàn)在網(wǎng)上能搜索到的一個(gè)比較熱的一份,但是答案并不是很詳細(xì)和完整,基本答案來(lái)著cocoaChina,和一些自己的補(bǔ)充。

34.Difference between shallow copy and deep copy?

淺復(fù)制和深復(fù)制的區(qū)別?

答案:淺層復(fù)制:只復(fù)制指向?qū)ο蟮闹羔?,而不?fù)制引用對(duì)象本身。

深層復(fù)制:復(fù)制引用對(duì)象本身。

意思就是說(shuō)我有個(gè)A對(duì)象,復(fù)制一份后得到A_copy對(duì)象后,對(duì)于淺復(fù)制來(lái)說(shuō),A和A_copy指向的是同一個(gè)內(nèi)存資源,復(fù)制的只不過(guò)是是一個(gè)指針,對(duì)象本身資源

還是只有一份,那如果我們對(duì)A_copy執(zhí)行了修改操作,那么發(fā)現(xiàn)A引用的對(duì)象同樣被修改,這其實(shí)違背了我們復(fù)制拷貝的一個(gè)思想。深復(fù)制就好理解了,內(nèi)存中存在了

兩份獨(dú)立對(duì)象本身。

用網(wǎng)上一哥們通俗的話將就是:

淺復(fù)制好比你和你的影子,你完蛋,你的影子也完蛋

深復(fù)制好比你和你的克隆人,你完蛋,你的克隆人還活著。
35.What is advantage of categories? What is difference between implementing a category and inheritance?

類(lèi)別的作用?繼承和類(lèi)別在實(shí)現(xiàn)中有何區(qū)別?

答案:category 可以在不獲悉,不改變?cè)瓉?lái)代碼的情況下往里面添加新的方法,只能添加,不能刪除修改。

并且如果類(lèi)別和原來(lái)類(lèi)中的方法產(chǎn)生名稱沖突,則類(lèi)別將覆蓋原來(lái)的方法,因?yàn)轭?lèi)別具有更高的優(yōu)先級(jí)。

類(lèi)別主要有3個(gè)作用:

(1)將類(lèi)的實(shí)現(xiàn)分散到多個(gè)不同文件或多個(gè)不同框架中。

(2)創(chuàng)建對(duì)私有方法的前向引用。

(3)向?qū)ο筇砑臃钦絽f(xié)議。

繼承可以增加,修改或者刪除方法,并且可以增加屬性。

36.Difference between categories and extensions?

類(lèi)別和類(lèi)擴(kuò)展的區(qū)別。

答案:category和extensions的不同在于后者可以添加屬性。另外后者添加的方法是必須要實(shí)現(xiàn)的。

extensions可以認(rèn)為是一個(gè)私有的Category。

37.Difference between protocol in objective c and interfaces in java?

oc中的協(xié)議和java中的接口概念有何不同?

答案:OC中的代理有2層含義,官方定義為 formal和informal protocol。前者和Java接口一樣。

informal protocol中的方法屬于設(shè)計(jì)模式考慮范疇,不是必須實(shí)現(xiàn)的,但是如果有實(shí)現(xiàn),就會(huì)改變類(lèi)的屬性。

其實(shí)關(guān)于正式協(xié)議,類(lèi)別和非正式協(xié)議我很早前學(xué)習(xí)的時(shí)候大致看過(guò),也寫(xiě)在了學(xué)習(xí)教程里

“非正式協(xié)議概念其實(shí)就是類(lèi)別的另一種表達(dá)方式“這里有一些你可能希望實(shí)現(xiàn)的方法,你可以使用他們更好的完成工作”。

這個(gè)意思是,這些是可選的。比如我門(mén)要一個(gè)更好的方法,我們就會(huì)申明一個(gè)這樣的類(lèi)別去實(shí)現(xiàn)。然后你在后期可以直接使用這些更好的方法。

這么看,總覺(jué)得類(lèi)別這玩意兒有點(diǎn)像協(xié)議的可選協(xié)議。"

現(xiàn)在來(lái)看,其實(shí)protocal已經(jīng)開(kāi)始對(duì)兩者都統(tǒng)一和規(guī)范起來(lái)操作,因?yàn)橘Y料中說(shuō)“非正式協(xié)議使用interface修飾“,

現(xiàn)在我們看到協(xié)議中兩個(gè)修飾詞:“必須實(shí)現(xiàn)(@requied)”和“可選實(shí)現(xiàn)(@optional)”。

38.What are KVO and KVC?

答案:kvc:鍵 - 值編碼是一種間接訪問(wèn)對(duì)象的屬性使用字符串來(lái)標(biāo)識(shí)屬性,而不是通過(guò)調(diào)用存取方法,直接或通過(guò)實(shí)例變量訪問(wèn)的機(jī)制。

很多情況下可以簡(jiǎn)化程序代碼。apple文檔其實(shí)給了一個(gè)很好的例子。

kvo:鍵值觀察機(jī)制,他提供了觀察某一屬性變化的方法,極大的簡(jiǎn)化了代碼。

具體用看到嗯哼用到過(guò)的一個(gè)地方是對(duì)于按鈕點(diǎn)擊變化狀態(tài)的的監(jiān)控。

比如我自定義的一個(gè)button

[cpp]

[self addObserver:self forKeyPath:@"highlighted" options:0 context:nil];

pragma mark KVO

  • (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context

{

([keyPath isEqualToString:@"highlighted"] ) {

[self setNeedsDisplay];

}

}

對(duì)于系統(tǒng)是根據(jù)keypath去取的到相應(yīng)的值發(fā)生改變,理論上來(lái)說(shuō)是和kvc機(jī)制的道理是一樣的。

對(duì)于kvc機(jī)制如何通過(guò)key尋找到value:

“當(dāng)通過(guò)KVC調(diào)用對(duì)象時(shí),比如:[self valueForKey:@”someKey”]時(shí),程序會(huì)自動(dòng)試圖通過(guò)幾種不同的方式解析這個(gè)調(diào)用。首先 查找對(duì)象是否帶有 someKey 這個(gè)方法,如果沒(méi)找到,會(huì)繼續(xù)查找對(duì)象是否帶有someKey這個(gè)實(shí)例變量(iVar),如果還沒(méi)有找到,程序會(huì)繼續(xù) 試圖調(diào)用 -(id) valueForUndefinedKey:這個(gè)方法。如果這個(gè)方法還是沒(méi)有被實(shí)現(xiàn)的話,程序會(huì)拋出一個(gè) NSUndefinedKeyException異常錯(cuò)誤。

(cocoachina.com注:Key-Value Coding查找方法的時(shí)候,不僅僅會(huì)查找someKey這個(gè)方法,還會(huì)查找 getsomeKey這個(gè)方法,前面加一個(gè)get,或者_(dá)someKey以及_getsomeKey這幾種形式。同時(shí),查找實(shí)例變量的時(shí)候也會(huì)不僅僅查找 someKey這個(gè)變量,也會(huì)查找_someKey這個(gè)變量是否存在。)

設(shè)計(jì)valueForUndefinedKey:方法的主要目的是當(dāng)你使用-(id)valueForKey方法從對(duì)象中請(qǐng)求值時(shí),對(duì)象能夠在錯(cuò)誤發(fā)生前,有最后的機(jī)會(huì)響應(yīng)這個(gè)請(qǐng)求。這樣做有很多好處,下面的兩個(gè)例子說(shuō)明了這樣做的好處。“

來(lái)至cocoa,這個(gè)說(shuō)法應(yīng)該挺有道理。

因?yàn)槲覀冎纀utton卻是存在一個(gè)highlighted實(shí)例變量.因此為何上面我們只是add一個(gè)相關(guān)的keypath就行了,

可以按照kvc查找的邏輯理解,就說(shuō)的過(guò)去了。

39.What is purpose of delegates?

代理的作用?

答案:代理的目的是改變或傳遞控制鏈。允許一個(gè)類(lèi)在某些特定時(shí)刻通知到其他類(lèi),而不需要獲取到那些類(lèi)的指針。可以減少框架復(fù)雜度。

另外一點(diǎn),代理可以理解為java中的回調(diào)監(jiān)聽(tīng)機(jī)制的一種類(lèi)似。

40.What are mutable and immutable types in Objective C?

oc中可修改和不可以修改類(lèi)型。

答案:可修改不可修改的集合類(lèi)。這個(gè)我個(gè)人簡(jiǎn)單理解就是可動(dòng)態(tài)添加修改和不可動(dòng)態(tài)添加修改一樣。

比如NSArray和NSMutableArray。前者在初始化后的內(nèi)存控件就是固定不可變的,后者可以添加等,可以動(dòng)態(tài)申請(qǐng)新的內(nèi)存空間。

41.When we call objective c is runtime language what does it mean?

我們說(shuō)的oc是動(dòng)態(tài)運(yùn)行時(shí)語(yǔ)言是什么意思?

答案:多態(tài)。 主要是將數(shù)據(jù)類(lèi)型的確定由編譯時(shí),推遲到了運(yùn)行時(shí)。

這個(gè)問(wèn)題其實(shí)淺涉及到兩個(gè)概念,運(yùn)行時(shí)和多態(tài)。

簡(jiǎn)單來(lái)說(shuō),運(yùn)行時(shí)機(jī)制使我們直到運(yùn)行時(shí)才去決定一個(gè)對(duì)象的類(lèi)別,以及調(diào)用該類(lèi)別對(duì)象指定方法。

多態(tài):不同對(duì)象以自己的方式響應(yīng)相同的消息的能力叫做多態(tài)。意思就是假設(shè)生物類(lèi)(life)都用有一個(gè)相同的方法-eat;

那人類(lèi)屬于生物,豬也屬于生物,都繼承了life后,實(shí)現(xiàn)各自的eat,但是調(diào)用是我們只需調(diào)用各自的eat方法。

也就是不同的對(duì)象以自己的方式響應(yīng)了相同的消息(響應(yīng)了eat這個(gè)選擇器)。

因此也可以說(shuō),運(yùn)行時(shí)機(jī)制是多態(tài)的基礎(chǔ)?~~~

42.what is difference between NSNotification and protocol?

通知和協(xié)議的不同之處?

答案:協(xié)議有控制鏈(has-a)的關(guān)系,通知沒(méi)有。

首先我一開(kāi)始也不太明白,什么叫控制鏈(專(zhuān)業(yè)術(shù)語(yǔ)了~)。但是簡(jiǎn)單分析下通知和代理的行為模式,我們大致可以有自己的理解

簡(jiǎn)單來(lái)說(shuō),通知的話,它可以一對(duì)多,一條消息可以發(fā)送給多個(gè)消息接受者。

代理按我們的理解,到不是直接說(shuō)不能一對(duì)多,比如我們知道的明星經(jīng)濟(jì)代理人,很多時(shí)候一個(gè)經(jīng)濟(jì)人負(fù)責(zé)好幾個(gè)明星的事務(wù)。

只是對(duì)于不同明星間,代理的事物對(duì)象都是不一樣的,一一對(duì)應(yīng),不可能說(shuō)明天要處理A明星要一個(gè)發(fā)布會(huì),代理人發(fā)出處理發(fā)布會(huì)的消息后,別稱B的

發(fā)布會(huì)了。但是通知就不一樣,他只關(guān)心發(fā)出通知,而不關(guān)心多少接收到感興趣要處理。

因此控制鏈(has-a從英語(yǔ)單詞大致可以看出,單一擁有和可控制的對(duì)應(yīng)關(guān)系。

43.What is push notification?

什么是推送消息?

答案:太簡(jiǎn)單,不作答~~~~~~~~~~

這是cocoa上的答案。

其實(shí)到不是說(shuō)太簡(jiǎn)單,只是太泛泛的一個(gè)概念的東西。就好比說(shuō),什么是人。

推送通知更是一種技術(shù)。

簡(jiǎn)單點(diǎn)就是客戶端獲取資源的一種手段。

普通情況下,都是客戶端主動(dòng)的pull。

推送則是服務(wù)器端主動(dòng)push。

44.Polymorphism?

關(guān)于多態(tài)性

答案:多態(tài),子類(lèi)指針可以賦值給父類(lèi)。

這個(gè)題目其實(shí)可以出到一切面向?qū)ο笳Z(yǔ)言中,

因此關(guān)于多態(tài),繼承和封裝基本最好都有個(gè)自我意識(shí)的理解,也并非一定要把書(shū)上資料上寫(xiě)的能背出來(lái)。

最重要的是轉(zhuǎn)化成自我理解。

45.Singleton?

對(duì)于單例的理解

答案:11,12題目其實(shí)出的有點(diǎn)泛泛的感覺(jué)了,可能說(shuō)是編程語(yǔ)言需要或是必備的基礎(chǔ)。

基本能用熟悉的語(yǔ)言寫(xiě)出一個(gè)單例,以及可以運(yùn)用到的場(chǎng)景或是你編程中碰到過(guò)運(yùn)用的此種模式的框架類(lèi)等。

進(jìn)一步點(diǎn),考慮下如何在多線程訪問(wèn)單例時(shí)的安全性。

46.What is responder chain?

說(shuō)說(shuō)響應(yīng)鏈

答案: 事件響應(yīng)鏈。包括點(diǎn)擊事件,畫(huà)面刷新事件等。在視圖棧內(nèi)從上至下,或者從下之上傳播。

可以說(shuō)點(diǎn)事件的分發(fā),傳遞以及處理。具體可以去看下touch事件這塊。因?yàn)閱?wèn)的太抽象化了

嚴(yán)重懷疑題目出到越后面就越籠統(tǒng)。

47.Difference between frame and bounds?

frame和bounds有什么不同?

答案:frame指的是:該view在父view坐標(biāo)系統(tǒng)中的位置和大小。(參照點(diǎn)是父親的坐標(biāo)系統(tǒng))

bounds指的是:該view在本身坐標(biāo)系統(tǒng)中 的位置和大小。(參照點(diǎn)是本身坐標(biāo)系統(tǒng))

48.Difference between method and selector?

方法和選擇器有何不同?

答案:selector是一個(gè)方法的名字,method是一個(gè)組合體,包含了名字和實(shí)現(xiàn).

詳情可以看apple文檔。

49.Is there any garbage collection mechanism in Objective C.?

OC的垃圾回收機(jī)制?

答案: OC2.0有Garbage collection,但是iOS平臺(tái)不提供。

一般我們了解的objective-c對(duì)于內(nèi)存管理都是手動(dòng)操作的,但是也有自動(dòng)釋放池。

但是差了大部分資料,貌似不要和arc機(jī)制搞混就好了。

求更多~~

50.NSOperation queue?

答案:存放NSOperation的集合類(lèi)。

操作和操作隊(duì)列,基本可以看成java中的線程和線程池的概念。用于處理ios多線程開(kāi)發(fā)的問(wèn)題。

網(wǎng)上部分資料提到一點(diǎn)是,雖然是queue,但是卻并不是帶有隊(duì)列的概念,放入的操作并非是按照嚴(yán)格的先進(jìn)現(xiàn)出。

這邊又有個(gè)疑點(diǎn)是,對(duì)于隊(duì)列來(lái)說(shuō),先進(jìn)先出的概念是Afunc添加進(jìn)隊(duì)列,Bfunc緊跟著也進(jìn)入隊(duì)列,Afunc先執(zhí)行這個(gè)是必然的,

但是Bfunc是等Afunc完全操作完以后,B才開(kāi)始啟動(dòng)并且執(zhí)行,因此隊(duì)列的概念離亂上有點(diǎn)違背了多線程處理這個(gè)概念。

但是轉(zhuǎn)念一想其實(shí)可以參考銀行的取票和叫號(hào)系統(tǒng)。

因此對(duì)于A比B先排隊(duì)取票但是B率先執(zhí)行完操作,我們亦然可以感性認(rèn)為這還是一個(gè)隊(duì)列。

但是后來(lái)看到一票關(guān)于這操作隊(duì)列話題的文章,其中有一句提到

“因?yàn)閮蓚€(gè)操作提交的時(shí)間間隔很近,線程池中的線程,誰(shuí)先啟動(dòng)是不定的?!?/p>

瞬間覺(jué)得這個(gè)queue名字有點(diǎn)忽悠人了,還不如pool~

綜合一點(diǎn),我們知道他可以比較大的用處在于可以幫組多線程編程就好了。

51.What is lazy loading?

答案:懶漢模式,只在用到的時(shí)候才去初始化。

也可以理解成延時(shí)加載。

我覺(jué)得最好也最簡(jiǎn)單的一個(gè)列子就是tableView中圖片的加載顯示了。

一個(gè)延時(shí)載,避免內(nèi)存過(guò)高,一個(gè)異步加載,避免線程堵塞。

52.Can we use two tableview controllers on one viewcontroller?

是否在一個(gè)視圖控制器中嵌入兩個(gè)tableview控制器?

答案:一個(gè)視圖控制只提供了一個(gè)View視圖,理論上一個(gè)tableViewController也不能放吧,

只能說(shuō)可以嵌入一個(gè)tableview視圖。當(dāng)然,題目本身也有歧義,如果不是我們定性思維認(rèn)為的UIViewController,
而是宏觀的表示視圖控制者,那我們倒是可以把其看成一個(gè)視圖控制者,它可以控制多個(gè)視圖控制器,比如TabbarController
那樣的感覺(jué)。
53.Can we use one tableview with two different datasources? How you will achieve this?
一個(gè)tableView是否可以關(guān)聯(lián)兩個(gè)不同的數(shù)據(jù)源?你會(huì)怎么處理?
答案:首先我們從代碼來(lái)看,數(shù)據(jù)源如何關(guān)聯(lián)上的,其實(shí)是在數(shù)據(jù)源關(guān)聯(lián)的代理方法里實(shí)現(xiàn)的。
因此我們并不關(guān)心如何去關(guān)聯(lián)他,他怎么關(guān)聯(lián)上,方法只是讓我返回根據(jù)自己的需要去設(shè)置如相關(guān)的數(shù)據(jù)源

  • 因此,我覺(jué)得可以設(shè)置多個(gè)數(shù)據(jù)源啊,但是有個(gè)問(wèn)題是,你這是想干嘛呢?想讓列表如何顯示,不同的數(shù)據(jù)源分區(qū)塊顯示?
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容