iOS程序員面試分類(lèi)模擬11_第1頁(yè)
iOS程序員面試分類(lèi)模擬11_第2頁(yè)
iOS程序員面試分類(lèi)模擬11_第3頁(yè)
iOS程序員面試分類(lèi)模擬11_第4頁(yè)
iOS程序員面試分類(lèi)模擬11_第5頁(yè)
已閱讀5頁(yè),還剩7頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

付費(fèi)下載

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

iOS程序員面試分類(lèi)模擬11簡(jiǎn)答題1.

iOS平臺(tái)做數(shù)據(jù)的持久化方式有哪些?正確答案:iOS中主要有5種常用的持久化數(shù)據(jù)的方式:NSUserDefault、屬性列表文件存儲(chǔ)、歸檔、SQLite和C(江南博哥)oreData。

SQLite是一個(gè)輕量級(jí)功能強(qiáng)大的關(guān)系數(shù)據(jù)引擎,可以很容易嵌入到應(yīng)用程序,可以在多個(gè)平臺(tái)使用。與CoreData框架不同的是,SQLite是使用程序式的,主要的API直接操作數(shù)據(jù)表。

CoreData不是一個(gè)關(guān)系型數(shù)據(jù)庫(kù),也不是關(guān)系型數(shù)據(jù)庫(kù)管理系統(tǒng)(RDBMS)。雖然CoreData支持SQLite作為一種存儲(chǔ)類(lèi)型,但它不能使用任意的SQLite數(shù)據(jù)庫(kù)。CoreData在使用的過(guò)程中自己創(chuàng)建這個(gè)數(shù)據(jù)庫(kù)。CoreData支持一對(duì)多的關(guān)系。

2.

如何使用NSUserDefault偏好設(shè)置保存數(shù)據(jù)?正確答案:NSUserDefault是iOS系統(tǒng)提供的一個(gè)單例類(lèi),通過(guò)它可以將用戶(hù)的偏好設(shè)置保存到應(yīng)用包的plist文件中,同時(shí)也能讀取保存的數(shù)據(jù)。通過(guò)類(lèi)方法+standardUserDefaults可以獲得NSUserDefault單例。

NSUserDefaults*userDefault=[NSUserDefaultsstandardUserDefaults];

NSUserDefault單例以key-value的形式存儲(chǔ)數(shù)據(jù),key是名稱(chēng),value是相應(yīng)的數(shù)據(jù)。使用-setObject:forKey:和-objectForKey:來(lái)存/取數(shù)據(jù)。下面的示例演示了一般的存取操作。

-(void)userDefaultSave{

NSUserDefaults*defaults=[NSUserDefaultsstandardUserDefaults];

[defaultssetObject:@"jack"forKey:@"name"];

[defaultssetInteger:10forKey:@"age"];

/*下面的代碼可以省略,這里只是作為演示*/

if([defaultssynchronize]){

NSLog(@"保存成功");

}

}

-(void)userDefaultGet{

NSUserDefaults*defaults=[NSUserDefaultsstandardUserDefaults];

NSString*name=[defaultsobjectForKey:@"name"];

NSIntegerage=[defaultsintegerForKey:@"age"];

NSLog(@"name=%@,age=%zd",name,age);

}

需要注意的是,默認(rèn)情況下NSUserDefaults只能存儲(chǔ)基本對(duì)象類(lèi)型(如NSData、NSString等類(lèi)型)和基本數(shù)據(jù)類(lèi)型,直接保存自定義對(duì)象將會(huì)拋出類(lèi)似如下的異常。

Terminatingappduetouncaughtexception'NSInvalidArgumentException',reason:'Attempttoinsertnon-propertylistobject<UIImage:0x608000092d40>,{400,250}forkeyimg'

此時(shí)需要自定義類(lèi)遵守NSCoding協(xié)議并實(shí)現(xiàn)協(xié)議方法進(jìn)行編碼與反編碼,再通過(guò)NSKevedUnarchiver類(lèi)將自定義對(duì)象轉(zhuǎn)為NSData對(duì)象,之后才能使用NSUserDefaults進(jìn)行存儲(chǔ)。簡(jiǎn)單來(lái)說(shuō),對(duì)于自定義類(lèi)對(duì)象,必須要通過(guò)一些方式將其轉(zhuǎn)化為基本類(lèi)型,即遵循NSCoding協(xié)議。下面的示例展示了如何保存UIImage對(duì)象。

-(void)userDefaultSaveImage{

UIImage*img=[UIImageimageNamed:@"1"];

NSUserDefaults*defaults=[NSUserDefaultsstandardUserDefaults];

/*直接保存將產(chǎn)生錯(cuò)誤:[defaultssetObject:imgforKey:@"img"];*/

/*轉(zhuǎn)為NSData對(duì)象*/

NSData*data=UIImageJPEGRepresentation(img,1);

[defaultssetObject:dataforKey:@"img"];

}

-(void)userDefaultGetImage{

NSUserDefaults*defaults=[NSUserDefaultsstandardUserDefaults];

/*轉(zhuǎn)為NSData對(duì)象*/

NSData*data=[defaultsobjectForKey:@"img"];

/*轉(zhuǎn)為UIImage對(duì)象*/

UIImage*img=[UIImageimageWithData:data];

self.view.layer.contents=(id)img.CGImage;

}

3.

如何使用NSUserDefault保存自定義對(duì)象?正確答案:事實(shí)上,在使用NSKeyedArchiver進(jìn)行歸檔時(shí)將數(shù)據(jù)存入自定義的文件中并不是必需的,可以將歸檔后的NSData類(lèi)型對(duì)象使用NSUserDefault直接存入plist文件中(因?yàn)榇藭r(shí)自定義對(duì)象已經(jīng)轉(zhuǎn)為普通的NSData類(lèi)型了)。在需要使用的時(shí)候再使用NSUserDefault取出數(shù)據(jù)并使用NSKeyedUnarchiver進(jìn)行解檔即可。示例代碼如下:

-(void)archiver1{

Animal*person=[Animalnew];

=@"Jack";

person.age=30;

/*歸檔*/

NSData*data=[NSKeyedArchiverarchivedDataWithRootObject:person];

NSUserDefaults*defaults=[NSUserDefaultsstandardUserDefaults];

[defaultssetObject:dataforKey:@"person"];

}

-(void)unarchiver1{

NSUserDefaults*defaults=[NSUserDefaultsstandardUserDefaults];

NSData*data=[defaultsobjectForKey:@"person"];

/*解檔*/

idobj=[NSKeyedUnarchiverunarchiveObjectWithData:data];

NSLog(@"%@",obj);

}

4.

什么是序列化或者歸檔?正確答案:序列化(Serialization)或者歸檔(Archiving)指將程序語(yǔ)言中的對(duì)象轉(zhuǎn)化成二進(jìn)制流從而存儲(chǔ)到文件中,因?yàn)閷?duì)象是不可以直接存入文件的;相反反序列化(Deserialization)或者反歸檔(UnArchiving)是將二進(jìn)制流文件轉(zhuǎn)化成對(duì)象,從而可以在程序中進(jìn)行操作。

NSKeyedArchiver是NSCoder的子類(lèi),它能夠?qū)⒉煌?lèi)型的對(duì)象編碼成NSData類(lèi)型的數(shù)據(jù)并將數(shù)據(jù)寫(xiě)入文件中。NSKeyedUnarchiver類(lèi)能夠?qū)⒋鏅n的數(shù)據(jù)進(jìn)行解檔并還原成原來(lái)的對(duì)象。

+(NSData*)archivedDataWithRootObject:(id)rootObject;

+(nullableid)unarchiveObjectWithData:(NSData*)data;

同NSUserDefault一樣,默認(rèn)情況下,只能對(duì)NSDate、NSNumber、NSString、NSArrayorNSDictionary進(jìn)行歸檔。如果要對(duì)自定義對(duì)象進(jìn)行歸檔,那么自定義對(duì)象類(lèi)要實(shí)現(xiàn)NSCoding協(xié)議。

在下面的示例中,演示了如何對(duì)自定義對(duì)象進(jìn)行編碼并保存到文件中。

首選需要在自定義的類(lèi)中遵守NSCoding協(xié)議并實(shí)現(xiàn)編碼和解碼的方法。

/*遵守協(xié)議*/

@interfaceAnimal:NSObject<NSCoding>

/*編碼*/

-(void)encodeWithCoder:(NSCoder*)aCoder{

[aCoderencodeObject:forKey:@"name"];

[aCoderencodeInteger:self.ageforKey:@"age"];

}

/*解碼*/

-(nullableinstancetype)initWithCoder:(NSCoder*)aDecoder{

=[aDecoderdecodeObjectForKey:@"name"];

self.age=[aDecoderdecodeIntegerForKey:@"age"];

returnself;

}

然后使用NSKeyedArchiver類(lèi)對(duì)自定義對(duì)象進(jìn)行歸檔,系統(tǒng)會(huì)自動(dòng)調(diào)用編碼方法。

-(void)archiver{

Animal*person=[Animalnew];

=@"Jack";

person.age=30;

/*獲取文件路徑*/

NSString*documents=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES)lastObjeet];

NSString*path=[documentsstringByAppendingPathComponent:@"person.archiver"];

/*歸檔*/

[NSKeyedArchiverarchiveRootObject:persontoFile:path];

}

此時(shí)在Documents目錄下就會(huì)生成person.archiver文件,其中保存了編碼之后的數(shù)據(jù)。接下來(lái)只需要在適當(dāng)?shù)臅r(shí)候?qū)⒈4婧玫奈募礆w檔為對(duì)象。

-(void)unarchiver{

/*獲取文件路徑*/

NSString*documents=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES)lastObject];

NSString*path=[documentsstringByAppendingPathComponent:@"person.archiver"];

/*解檔*/

idobj=[NSKeyedUnarchiverunarchiveObjectWithFile:path];

NSLog(@"%@",obj);

}

5.

什么是內(nèi)存泄漏?什么是安全釋放?正確答案:內(nèi)存泄漏指動(dòng)態(tài)分配內(nèi)存的對(duì)象在使用完后沒(méi)有被系統(tǒng)回收內(nèi)存,導(dǎo)致該對(duì)象始終占用內(nèi)存,又無(wú)法通過(guò)代碼訪問(wèn),屬于內(nèi)存管理出錯(cuò),如果出現(xiàn)大量?jī)?nèi)存泄漏,那么會(huì)導(dǎo)致系統(tǒng)內(nèi)存不足的問(wèn)題。由于內(nèi)存泄漏的檢測(cè)是程序開(kāi)發(fā)中不可避免的問(wèn)題,所以對(duì)于程序員而言,一方面要深入理解內(nèi)存管理原則,養(yǎng)成良好的編程習(xí)慣以減少內(nèi)存泄漏情況的發(fā)生;另一方面可以通過(guò)各種方法,例如使用Xcode提供的檢測(cè)調(diào)試工具Instruments,檢測(cè)可能導(dǎo)致內(nèi)存泄漏的代碼,并及時(shí)進(jìn)行優(yōu)化。

安全釋放指釋放掉不再使用的對(duì)象的同時(shí)不會(huì)造成內(nèi)存泄漏或指針懸掛問(wèn)題的操作。為了保證安全釋放,在對(duì)象dealloc后要將其指針置為nil。另外,要嚴(yán)格遵守內(nèi)存管理原則,保證對(duì)象的引用計(jì)數(shù)正確,同時(shí)要注意避免引用循環(huán)的出現(xiàn)。

6.

僵尸對(duì)象、野指針、空指針?lè)謩e指什么?它們有什么區(qū)別?正確答案:1.僵尸對(duì)象

一個(gè)引用計(jì)數(shù)為0的Objective-C對(duì)象被釋放后就變成僵尸對(duì)象。僵尸對(duì)象的內(nèi)存已經(jīng)被系統(tǒng)回收,雖然該對(duì)象可能還存在,數(shù)據(jù)依然在內(nèi)存中,但僵尸對(duì)象已經(jīng)是不穩(wěn)定對(duì)象了,不可以再訪問(wèn)或者使用,它的內(nèi)存是隨時(shí)可能被別的對(duì)象申請(qǐng)而占用的。需要注意的是,僵尸對(duì)象所占的內(nèi)存是正常的,不會(huì)造成內(nèi)存泄漏。

2.野指針

野指針又叫“懸掛指針”,野指針出現(xiàn)的原因是指針沒(méi)有賦值,或者指針指向的對(duì)象已經(jīng)被釋放掉了。野指針指向一塊隨機(jī)的垃圾內(nèi)存,向它們發(fā)送消息會(huì)報(bào)EXC_BAD_ACCESS錯(cuò)誤導(dǎo)致程序崩潰。

3.空指針

空指針不同于野指針,它是一個(gè)沒(méi)有指向任何內(nèi)容的指針??罩羔樖怯行е羔?,值為nil、NuLL、Nil或0等,給空指針發(fā)送消息不會(huì)報(bào)錯(cuò),只是不響應(yīng)消息而已,應(yīng)該給野指針及時(shí)賦予零值使其變成有效的空指針,避免內(nèi)存報(bào)錯(cuò)。

7.

Objective-C有GC垃圾回收機(jī)制嗎?正確答案:垃圾回收(GarbageCollection,GC)簡(jiǎn)單地說(shuō)就是程序中及時(shí)處理廢棄不用的內(nèi)存對(duì)象的機(jī)制,防止內(nèi)存中廢棄對(duì)象堆積過(guò)多造成內(nèi)存泄漏。

Objective-C語(yǔ)言本身是支持垃圾回收機(jī)制的,但有平臺(tái)局限性,僅限于Mac桌面系統(tǒng)開(kāi)發(fā)中,而在iPhone和iPad等蘋(píng)果移動(dòng)終端設(shè)備中是不支持垃圾回收機(jī)制的。在移動(dòng)設(shè)備開(kāi)發(fā)中的內(nèi)存管理是采用手動(dòng)引用計(jì)數(shù)(ManualRearenceCotrating,MRC)以及iOS5以后的自動(dòng)引用計(jì)數(shù)(AutomaticRearenceCounting,ARC),本質(zhì)都是引用計(jì)數(shù)(RC),通過(guò)引用計(jì)數(shù)的方式來(lái)管理內(nèi)存的分配與釋放,從而防止內(nèi)存泄漏。

另外,引用計(jì)數(shù)和垃圾回收是有區(qū)別的。垃圾回收是宏觀的,對(duì)整體進(jìn)行內(nèi)存管理,雖然不同平臺(tái)垃圾回收機(jī)制不同,但基本原理都是一樣的:將所有對(duì)象看作一個(gè)集合,然后在GC循環(huán)中定時(shí)檢測(cè)活動(dòng)對(duì)象和非活動(dòng)對(duì)象,及時(shí)將用不到的非活動(dòng)對(duì)象釋放掉以避免內(nèi)存泄漏,也就是說(shuō)用不到的垃圾對(duì)象是交給GC來(lái)管理釋放的,而無(wú)需開(kāi)發(fā)者關(guān)心,典型的是Java語(yǔ)言中的垃圾回收機(jī)制;相比于GC,引用計(jì)數(shù)是局部性的,開(kāi)發(fā)者要管理控制每個(gè)對(duì)象的引用計(jì)數(shù),單個(gè)對(duì)象引用計(jì)數(shù)為0后會(huì)馬上被釋放掉。ARC是一種改進(jìn),由編譯器幫助開(kāi)發(fā)者自動(dòng)管理控制引用計(jì)數(shù)(自動(dòng)在合適的時(shí)機(jī)發(fā)送release和retain消息)。另外,自動(dòng)釋放池(autoreleasepool)像是一個(gè)局部的垃圾回收,將部分垃圾對(duì)象集中釋放,相對(duì)于單個(gè)釋放會(huì)有一定延遲。

8.

自動(dòng)釋放池跟GC(垃圾回收)有什么區(qū)別?iPhone上有GC嗎?[poolrelease]和[pooldrain]有什么區(qū)別?正確答案:[poolrelease]和[pooldrain]在作用上是一樣的,它們都是清理自動(dòng)釋放池,區(qū)別是drain在支持GC的系統(tǒng)中(Mac系統(tǒng))可以引起GC回收操作,而release不可以。對(duì)于自動(dòng)釋放池一般建議使用[pooldrain],原因是它的功能對(duì)系統(tǒng)兼容性更強(qiáng),二者也是為了跟普通對(duì)象的release釋放區(qū)別開(kāi)。自動(dòng)釋放池的釋放操作指向池內(nèi)所有的對(duì)象發(fā)送release消息,以讓系統(tǒng)及時(shí)釋放池內(nèi)的所有對(duì)象。

9.

在Objective-C中,與alloe語(yǔ)義相反的方法是dealloc還是release?正確答案:alloc與dealloc語(yǔ)意相反,alloc是創(chuàng)建變量,dealloc是釋放變量。

retain與release語(yǔ)義相反,retain保留一個(gè)對(duì)象,調(diào)用后使變量的引用計(jì)數(shù)加1,而release釋放一個(gè)對(duì)象,調(diào)用后使變量的引用計(jì)數(shù)減1。

雖然alloc對(duì)應(yīng)dealloc,retain對(duì)應(yīng)release,但是與alloc配對(duì)使用的方法是release,而不是dealloc。為什么呢?這要從它們的實(shí)際效果來(lái)看。事實(shí)上alloc和release配對(duì)使用只是表象,本質(zhì)上還是retain和release的配對(duì)使用。alloc用來(lái)創(chuàng)建對(duì)象,剛創(chuàng)建的對(duì)象默認(rèn)引用計(jì)數(shù)為1,相當(dāng)于調(diào)用alloc創(chuàng)建對(duì)象過(guò)程中同時(shí)會(huì)調(diào)用一次retain使對(duì)象引用計(jì)數(shù)加1,自然要有對(duì)應(yīng)的release的一次調(diào)用,使對(duì)象不再被用時(shí)能夠被釋放掉防止內(nèi)存泄漏。

此外,dealloc是在對(duì)象引用計(jì)數(shù)為0以后系統(tǒng)自動(dòng)調(diào)用的,dealloc沒(méi)有使對(duì)象引用計(jì)數(shù)減1的作用,只是在對(duì)象引用計(jì)數(shù)為0后被系統(tǒng)調(diào)用進(jìn)行內(nèi)存回收的收尾工作。

10.

當(dāng)使用block時(shí),什么情況會(huì)發(fā)生引用循環(huán)?如何解決?正確答案:常見(jiàn)的使用block引起引用循環(huán)的情況為:在一個(gè)對(duì)象中強(qiáng)引用了一個(gè)block,在該block中又強(qiáng)引用了該對(duì)象,此時(shí)就出現(xiàn)了該對(duì)象和該block的循環(huán)引用。示例代碼如下:

/*Test.h*/

#import<Foundation/Foundation.h>

/*聲明一個(gè)名為MYBlock的block,參數(shù)為空,返回值為void*/

typedefvoid(^MYBlock)();

@interfaceTest:NSObject

/*定義并強(qiáng)引用一個(gè)MYBlock*/

@property(nonatomic,strong)MYBlockblock;

/*對(duì)象屬性*/

@property(nonatomic,copy)NSString*name;

-(void)print;

@end

/*Test.m*/

#import"Test.h"

@implementationTest

-(void)ptint{

self.block=^{

NSLog(@"%@",);

};

self.block();

}

@end

解決上面的引用循環(huán)的方法有以下兩種:一是強(qiáng)制將一方置nil,破壞引用循環(huán);二是將對(duì)象使用__weak或者_(dá)_block修飾符修飾之后再在block中使用(注意是在自動(dòng)引用計(jì)數(shù)下),代碼如下:

-(void)print{

__weaktypeof(self)weakSelf=self;

self.block=^{

NSLog(@"%@",weakS);

};

self.block();

}

11.

CAAnimation的delegate是強(qiáng)引用還是弱引用?正確答案:CAAnimation的delegate(代理)是強(qiáng)引用,是內(nèi)存管理中一個(gè)罕見(jiàn)的特例。為了避免循環(huán)引用問(wèn)題,delegate通常都使用assign或weak修飾表示弱引用,而CAAnimation動(dòng)畫(huà)是異步的,如果動(dòng)畫(huà)的代理是弱應(yīng)用而不是強(qiáng)應(yīng)用,那么會(huì)導(dǎo)致其隨時(shí)都可能被釋放掉。在使用動(dòng)畫(huà)時(shí)要注意采取措施避免循環(huán)引用,例如及時(shí)在視圖移除之前的合適時(shí)機(jī)移除動(dòng)畫(huà)。

CAAnimation的代理定義如下,明確說(shuō)明動(dòng)畫(huà)的代理在動(dòng)畫(huà)對(duì)象整個(gè)生命周期間是被強(qiáng)引用的,默認(rèn)為nil。

/*Thedelegateoftheanimation.Thisobjectisretainedforthe

*lifetimeoftheanimationobject.Defaultstonil.Seebelowforthe

*supposeddelegatemethods.*/

@property(nullable,strong)id<CAAnimationDelegate>delegate;

12.

按照默認(rèn)法則,哪些關(guān)鍵字生成的對(duì)象需要手動(dòng)釋放?正確答案:起初在MRC(手動(dòng)引用計(jì)數(shù))中開(kāi)發(fā)者要自己手動(dòng)管理內(nèi)存,基本原則是:誰(shuí)創(chuàng)建,誰(shuí)釋放,誰(shuí)引用,誰(shuí)管理。其中,創(chuàng)建主要始于關(guān)鍵詞new、alloc和copy的使用,創(chuàng)建并持有開(kāi)始引用計(jì)數(shù)為1,如果引用要通過(guò)發(fā)送retain消息增加引用計(jì)數(shù),通過(guò)發(fā)送release消息減少引用計(jì)數(shù),那么引用計(jì)數(shù)變?yōu)?后對(duì)象會(huì)被系統(tǒng)清理釋放?,F(xiàn)在有了ARC(自動(dòng)引用計(jì)數(shù))后編譯器會(huì)自動(dòng)管理引用計(jì)數(shù),開(kāi)發(fā)者不再需也不可以手動(dòng)管理引用計(jì)數(shù)。

使用new、alloc、copy關(guān)鍵字生成的對(duì)象和retain了的對(duì)象需要手動(dòng)釋放。被設(shè)置為autorelease的對(duì)象不需要手動(dòng)釋放,會(huì)直接進(jìn)入自動(dòng)釋放池。

13.

以下每行代碼執(zhí)行后,person對(duì)象的retaincount分別是多少?

Person*person=[[Personalloc]init];

[personretain];

[personrelease];

[personrelease];正確答案:1-2-1-0。[解析]開(kāi)始alloc創(chuàng)建對(duì)象并持有對(duì)象,初始引用計(jì)數(shù)為1,retain一次引用計(jì)數(shù)加1變?yōu)?,之后release對(duì)象兩次,引用計(jì)數(shù)減1兩次,先后變?yōu)?、0。

14.

objective-C是如何實(shí)現(xiàn)內(nèi)存管理的?正確答案:Objective-C的內(nèi)存管理本質(zhì)上是通過(guò)引用計(jì)數(shù)實(shí)現(xiàn)的,每次RunLoop都會(huì)檢查對(duì)象的引用計(jì)數(shù),如果引用計(jì)數(shù)為0,那么說(shuō)明該對(duì)象已經(jīng)沒(méi)有再被使用了,此時(shí)可以對(duì)其進(jìn)行釋放了。其中,引用計(jì)數(shù)可以大體分為3種:MRC、ARC和內(nèi)存池。

那么引用計(jì)數(shù)是如何操作的呢?其實(shí)不論哪種引用計(jì)數(shù)方式,它們本質(zhì)上都是在合適的時(shí)機(jī)將對(duì)象的引用計(jì)數(shù)加1或者減1。

所以對(duì)于引用計(jì)數(shù)可以總結(jié)如下:

1)使對(duì)象引用計(jì)數(shù)加1的常見(jiàn)操作有alloc、copy、retain。

2)使對(duì)象引用計(jì)數(shù)減1的常見(jiàn)操作有release、autorealease。

自動(dòng)釋放池是一個(gè)統(tǒng)一來(lái)釋放一組對(duì)象的容器,在向?qū)ο蟀l(fā)送autorelease消息時(shí),對(duì)象并沒(méi)有立即釋放,而是將對(duì)象加入到最新的自動(dòng)釋放池(即將該對(duì)象的引用交給自動(dòng)釋放池,之后統(tǒng)一調(diào)用release),自動(dòng)釋放池會(huì)在程序執(zhí)行到作用域結(jié)束的位置時(shí)進(jìn)行drain釋放操作,這個(gè)時(shí)候會(huì)對(duì)池中的每一個(gè)對(duì)象都發(fā)送release消息來(lái)釋放所有對(duì)象。這樣其實(shí)就實(shí)現(xiàn)了這些對(duì)象的延遲釋放。

自動(dòng)釋放池釋放的時(shí)機(jī)指自動(dòng)釋放池內(nèi)的所有對(duì)象是在什么時(shí)候釋放的,這里要提到程序的運(yùn)行周期RunLoop。對(duì)于每一個(gè)新的RunLoop,系統(tǒng)都會(huì)隱式地創(chuàng)建一個(gè)autoreleasepool,RunLoop結(jié)束時(shí)自動(dòng)釋放池便會(huì)進(jìn)行對(duì)象釋放操作。autorelease和release的區(qū)別主要是引用計(jì)數(shù)減1的時(shí)機(jī)不同,autorelease是在對(duì)象的使用真正結(jié)束的時(shí)候才做引用計(jì)數(shù)減1,而不是收到消息立馬釋放。

retain、release和autorelease的內(nèi)部實(shí)現(xiàn)代碼如下:

-(id)retain{

/*對(duì)象引用計(jì)數(shù)加1*/

NSIncrementExtraRefCount(self);

returnself;

}

-(void)release{

/*對(duì)象引用計(jì)數(shù)減1,之后如果引用計(jì)數(shù)為0,那么釋放*/

if(NSDecrementExtraRefCountWasZero(self)){

NSDeallocateObject(self);

}

}

-(id)autorelease{

/*添加對(duì)象到自動(dòng)釋放池*/

[NSAutoreteasePooladdObject:self];

returnself;

}

15.

如何實(shí)現(xiàn)autorealeasepool?正確答案:autorealeasepool(自動(dòng)釋放池)其實(shí)并沒(méi)有其自身的結(jié)構(gòu),它是基于多個(gè)AutoreleasePoolPage(一個(gè)C++類(lèi))以雙向鏈表組合起來(lái)的結(jié)構(gòu),其基本操作都是簡(jiǎn)單封裝了AutoreleasePoolPage的操作方法。例如,可以通過(guò)push操作添加對(duì)象,或者通過(guò)pop操作彈出對(duì)象,以及通過(guò)release操作釋放銷(xiāo)毀對(duì)象,對(duì)應(yīng)的3個(gè)封裝后的操作函數(shù)為:objc_autoreleasepoolPush、objc_autoreleasepoolPop和objc_autorelease。自動(dòng)釋放池將用完的對(duì)象集中起來(lái),統(tǒng)一釋放,起到延遲釋放對(duì)象的作用。

自動(dòng)釋放池存儲(chǔ)于內(nèi)存中的棧上,釋放池之間遵循“先進(jìn)后出”原則。例如下面代碼所示的釋放池嵌套。

/*釋放池1*/

@autoreleasepool{

People*person1=[[[Personalloc]init]autoretease];

/*釋放池2*/

@autoreleasepool{

People*person2=[[[Personalloc]init]autorelease];

}

People*person3=[[[Personalloc]init]autorelease];

}

代碼中釋放池1和釋放池2在內(nèi)存中的結(jié)構(gòu)如圖所示,釋放池1先入棧,后出棧;釋放池2后入棧,先出棧。person2對(duì)象在釋放池2中,會(huì)被先釋放;person1和person3在釋放池1中,會(huì)后被釋放。

釋放池內(nèi)存結(jié)構(gòu)

自動(dòng)釋放池背后具體的實(shí)現(xiàn)機(jī)制比較復(fù)雜和巧妙,具體細(xì)節(jié)感興趣的讀者可以閱讀下面這篇博文中的討論:/2014/10/15/behind-autorelease/

16.

執(zhí)行下面的代碼會(huì)發(fā)生什么后果?

Ball*ball=[[[[Ballalloc]init]autorelease]autorelease];正確答案:上面的代碼會(huì)導(dǎo)致程序崩潰,因?yàn)檫B續(xù)兩次調(diào)用autorelease方法后,對(duì)象被加入到自動(dòng)釋放池兩次。當(dāng)對(duì)象被移除時(shí),自動(dòng)釋放池將其釋放了不止一次,其中第二次釋放必定導(dǎo)致崩潰。

17.

下面這段代碼有什么問(wèn)題?如何修改?

for(inti=0;i<someLargeNumber;i++){

NSString*string=@"Abc";

string=[stringlowereaseString];

string=[stringstringByAppendingString:@"xyz"];

NSLog(@"%@",string);

}正確答案:代碼通過(guò)循環(huán)短時(shí)間內(nèi)創(chuàng)建了大量的NSString對(duì)象,在默認(rèn)的自動(dòng)釋放池釋放之前這些對(duì)象無(wú)法被立即釋放,會(huì)占用大量?jī)?nèi)存,造成內(nèi)存高峰以致內(nèi)存不足。

為了防止大量對(duì)象堆積應(yīng)該在循環(huán)內(nèi)手動(dòng)添加自動(dòng)釋放池,這樣在每一次循環(huán)結(jié)束,循環(huán)內(nèi)的自動(dòng)釋放池都會(huì)被自動(dòng)釋放及時(shí)騰出內(nèi)存,從而大大縮短了循環(huán)內(nèi)對(duì)象的生命周期,避免內(nèi)存占用高峰。

代碼改進(jìn)方法是在循環(huán)內(nèi)部嵌套一個(gè)自動(dòng)釋放池:

for(inti=0;i<1000000;i++){

@autoreleasepool{

NSString*string=@"Abc";

string=[stringlowercaseString];

string=[stringstringByAppendingString:@"xyz"];

NSLog(@"%@";string)

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論