iOS面試題

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

1). readwrite 是可讀可寫(xiě)特性;需要生成getter方法和setter方法時(shí);

2). readonly 是只讀特性 只會(huì)生成getter方法 不會(huì)生成setter方法 ;不希望屬性在類外改變時(shí);

3). assign 是賦值特性,setter方法將傳入?yún)?shù)賦值給實(shí)例變量;僅設(shè)置變量時(shí),一般用于基礎(chǔ)數(shù)據(jù)類型;

4). retain 表示持有特性,setter方法將傳入?yún)?shù)先保留,再賦值,傳入?yún)?shù)的retaincount會(huì)+1,也就是說(shuō)release舊值,retain新值;一般用于OC對(duì)象;

5). copy 表示賦值特性,setter方法將傳入對(duì)象復(fù)制一份;需要完全一份新的變量時(shí),也就是release舊值,copy新值;一般用于NSString\NSMutableString\block;

6).nonatomic 非原子操作,決定編譯器生成的setter getter是否是原子操作,atomic表示多線程安全,一般使用nonatomic。

2.#import 跟#include、@class有什么區(qū)別?#import<> 跟 #import”"又什么區(qū)別?

1).#import和#include都能完整地包含某個(gè)文件的內(nèi)容,#import能防止同一個(gè)文件被包含多次。

2). @class和#import

作用上的區(qū)別:

#import會(huì)包含引用類的所有信息(內(nèi)容), 包括引用類的變量和方法;

@class僅僅是告訴編譯器有這么一個(gè)類, 具體這個(gè)類里有什么信息, 完全不知;

效率上的區(qū)別:

如果有上百個(gè)頭文件都#import了同一個(gè)文件,或者這些文件依次被#import,那么一旦最開(kāi)始的頭文件稍有改動(dòng),后面引用到這個(gè)文件的所有類都需要重新編譯一遍 , 編譯效率非常低;

相對(duì)來(lái)講,使用@class方式就不會(huì)出現(xiàn)這種問(wèn)題了

3). #import <> 用來(lái)包含系統(tǒng)自帶的文件,#import “”用來(lái)包含自定義的文件。

3.OC有多繼承嗎?沒(méi)有的話用什么代替?

OC中沒(méi)有多繼承,可以用委托代理Protocol來(lái)實(shí)現(xiàn)。

4.Objective-C如何對(duì)內(nèi)存管理的?內(nèi)存管理的原則是?

Objective-C的內(nèi)存管理主要有三種方式ARC(自動(dòng)引用計(jì)數(shù))、MRC(手動(dòng)內(nèi)存計(jì)數(shù))、autorelease(自動(dòng)釋放池)。

每個(gè)對(duì)象都有一個(gè)引用計(jì)數(shù)器,每個(gè)新對(duì)象的計(jì)數(shù)器是1,當(dāng)對(duì)象的計(jì)數(shù)器減為0時(shí),就會(huì)被銷毀。

內(nèi)存管理原則(配對(duì)原則):只要出現(xiàn)了 new/alloc/retain,就一定配對(duì)出現(xiàn)一個(gè)release/autorelease。

5、Object C中創(chuàng)建線程的方法是什么?如果在主線程中執(zhí)行代碼,方法是什么?如果想延時(shí)執(zhí)行代碼、方法又是什么?

線程創(chuàng)建有三種方法:使用NSThread創(chuàng)建、使用GCD的dispatch、使用子類化的NSOperation,然后將其加入NSOperationQueue;在主線程執(zhí)行代碼,方法是performSelectorOnMainThread,如果想延時(shí)執(zhí)行代碼可以用performSelector:onThread:withObject:waitUntilDone:;

6、淺復(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ì)象本身。

用通俗的話講就是:淺復(fù)制好比你和你的影子,你完蛋,你的影子也完蛋;深復(fù)制好比你和你的克隆人,你完蛋,你的克隆人還活著。

7、分類的作用?分類和繼承的區(qū)別?

分類可以在不獲悉,不改變?cè)瓉?lái)代碼的情況下往里面添加新的方法,只能添加,不能刪除修改,并且如果分類和原來(lái)類中的方法產(chǎn)生名稱沖突,則分類將覆蓋原來(lái)的方法,因?yàn)榉诸惥哂懈叩膬?yōu)先級(jí)。

繼承可以增加,修改或者刪除方法,并且可以增加屬性;但是分類只能添加方法,不能刪除修改,也不能增加屬性。

8、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))

9、HTTP協(xié)議中,POST和GET的區(qū)別是什么?

1).GET 方法:

GET 方法提交數(shù)據(jù)不安全,數(shù)據(jù)置于請(qǐng)求行,客戶端地址欄可見(jiàn);

GET 方法提交的數(shù)據(jù)大小有限

GET 方法不可以設(shè)置書(shū)簽

2).POST 方法:

POST 方法提交數(shù)據(jù)安全,數(shù)據(jù)置于消息主體內(nèi),客戶端不可見(jiàn)

POST 方法提交的數(shù)據(jù)大小沒(méi)有限制

POST 方法可以設(shè)置書(shū)簽

10、視圖控制器的生命周期方法調(diào)用順序?

11、block和代理的區(qū)別,哪個(gè)更好?

代理回調(diào)更面向過(guò)程,block更面向結(jié)果。如果需要在執(zhí)行的不同步驟時(shí)被通知,你就要使用代理。如果只需要請(qǐng)求的消息或者失敗的詳情,應(yīng)該使用block。block更適合與狀態(tài)無(wú)關(guān)的操作,比如被告知某些結(jié)果,block之間是不會(huì)相互影響的。但是代理更像一個(gè)生產(chǎn)流水線,每個(gè)回調(diào)方法是生產(chǎn)線上的一個(gè)處理步驟,一個(gè)回調(diào)的變動(dòng)可能會(huì)引起另一個(gè)回調(diào)的變動(dòng)。要是一個(gè)對(duì)象有超過(guò)一個(gè)的不同事件,應(yīng)該使用代理。一個(gè)對(duì)象只有一個(gè)代理,要是某個(gè)對(duì)象是個(gè)單例對(duì)象,就不能使用代理。要是一個(gè)對(duì)象調(diào)用方法需要返回一些額外的信息,就可能需要使用代理。

12、自動(dòng)釋放池常見(jiàn)面試代碼

for(inti =0; i <10; ++i) {NSString*str =@"Hello World";? ? ? ? str = [str stringByAppendingFormat:@" - %d", i];? ? ? ? str = [str uppercaseString];NSLog(@"%@", str);}

問(wèn):以上代碼存在什么樣的問(wèn)題?如果循環(huán)的次數(shù)非常大時(shí),應(yīng)該如何修改?

解決辦法1:如果i比較大,可以用@autoreleasepool {}解決,放在for循環(huán)外,循環(huán)結(jié)束后,銷毀創(chuàng)建的對(duì)象,解決占據(jù)棧區(qū)內(nèi)存的問(wèn)題

解決方法2:如果i玩命大,一次循環(huán)都會(huì)造成自動(dòng)釋放池被填滿,自動(dòng)釋放池放在for循環(huán)內(nèi),每次循環(huán)都將上一次創(chuàng)建的對(duì)象release。

13、iOS怎么做數(shù)據(jù)的持久化?

1)、plist屬性列表

適用對(duì)象:僅僅是Foundation框架中自帶的一些類,比如NSString、、NSArray、NSDictionary、NSSet、NSNumber、NSData

調(diào)用對(duì)象的writeToFile...方法就可以寫(xiě)入文件

調(diào)用對(duì)象的...WithContentsOfFile方法就可以從文件中讀取對(duì)象內(nèi)容

2)、偏好設(shè)置(NSUserDefault)

本質(zhì)還是plist屬性列表的方式進(jìn)行存儲(chǔ)

存取非常簡(jiǎn)單(不關(guān)心文件夾和文件名)

缺點(diǎn):只能存儲(chǔ)到一個(gè)文件中(不能存放大批量數(shù)據(jù))

3)、NSCoding

能將任何遵守了NSCoding協(xié)議的對(duì)象塞進(jìn)文件中

- (void)encodeWithCoder:(NSCoder *)encoder將對(duì)象歸檔的時(shí)候會(huì)調(diào)用(將對(duì)象寫(xiě)入文件之前會(huì)調(diào)用)這個(gè)方法, 在這個(gè)方法說(shuō)清楚:a、那些屬性需要存儲(chǔ) b、怎樣存儲(chǔ)這些屬性;

- (id)initWithCoder:(NSCoder *)decoder當(dāng)從文件中解析對(duì)象的時(shí)候調(diào)用這個(gè)方法,在這個(gè)方法說(shuō)清楚:a、那些屬性需要解析(讀取) b、怎樣解析(讀取)這些屬性;

如果父類也有屬性需要?dú)w檔或者讀檔,必須調(diào)用super的encodeWithCoder:和initWithCoder:方法。

14、APNS的推送機(jī)制

首先我們看一下蘋(píng)果官方給出的對(duì)iOS推送機(jī)制的解釋。如下圖:

Provider就是我們自己程序的后臺(tái)服務(wù)器,APNS是Apple Push Notification Service的縮寫(xiě),也就是蘋(píng)果的推送服務(wù)器。

上圖可以分為三個(gè)階段:

第一階段:應(yīng)用程序的服務(wù)器端把要發(fā)送的消息、目的iPhone的標(biāo)識(shí)打包,發(fā)給APNS。

第二階段:APNS在自身的已注冊(cè)Push服務(wù)的iPhone列表中,查找有相應(yīng)標(biāo)識(shí)的iPhone,并把消息發(fā)送到iPhone。

第三階段:iPhone把發(fā)來(lái)的消息傳遞給相應(yīng)的應(yīng)用程序,并且按照設(shè)定彈出Push通知。

15、控制器View的加載過(guò)程?

當(dāng)程序訪問(wèn)了控制器的View屬性時(shí)會(huì)先判斷控制器的View是否存在,如果存在就直接返回已經(jīng)存在的View;如果不存在,就會(huì)先調(diào)用loadView這個(gè)方法;如果控制器的loadView方法實(shí)現(xiàn)了,就會(huì)按照l(shuí)oadView方法加載自定義的View;如果控制器的loadView方法沒(méi)有實(shí)現(xiàn)就會(huì)判斷storyboard是否存在;如果storyboard存在就會(huì)按照storyboard加載控制器的View;如果storyboard不存在,就會(huì)創(chuàng)建一個(gè)空視圖返回。

16、UITableView的數(shù)據(jù)源方法和代理方法?

數(shù)據(jù)源常見(jiàn)方法:

1.有多少組- (NSInteger)numberOfSectionsInTableView:(UITableView*)tableView2.第section組頭部控件有多高- (CGFloat)tableView:(UITableView*)tableView heightForHeaderInSection:(NSInteger)section3.第section組有多少行- (NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section4.indexPath這行的cell有多高- (CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath5.indexPath這行的cell長(zhǎng)什么樣子- (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath6.第section組頭部顯示什么控件- (UIView*)tableView:(UITableView*)tableView viewForHeaderInSection:(NSInteger)section

代理方法:

- (NSArray*)sectionIndexTitlesForTableView:(UITableView*)tableView//右側(cè)索引- (void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath//行點(diǎn)擊事件NSIndexPath*path = [self.tableViewindexPathForSelectedRow];//獲得被選中的indexPath可以得到section,row[self.tableViewreloadRowsAtIndexPaths:[self.tableViewindexPathsForSelectedRows] withRowAnimation:UITableViewRowAnimationNone];//刷新table指定行的數(shù)據(jù)[self.tableViewreloadData];//刷新table所有行的數(shù)據(jù)

17、UITableViewCell表格優(yōu)化?

UITableViewCell對(duì)象的重用原理:當(dāng)滾動(dòng)列表時(shí),部分UITableViewCell會(huì)移出窗口,UITableView會(huì)將窗口外的UITableViewCell放入一個(gè)對(duì)象池中,等待重用。當(dāng)UITableView要求dataSource返回UITableViewCell時(shí),dataSource會(huì)先查看這個(gè)對(duì)象池,如果池中有未使用的UITableViewCell,dataSource會(huì)用新的數(shù)據(jù)配置這個(gè)UITableViewCell,然后返回給UITableView,重新顯示到窗口中,從而避免創(chuàng)建新對(duì)象。

還有一個(gè)非常重要的問(wèn)題:有時(shí)候需要自定義UITableViewCell(用一個(gè)子類繼承UITableViewCell),而且每一行用的不一定是同一種UITableViewCell(如短信聊天布局),所以一個(gè)UITableView可能擁有不同類型的UITableViewCell,對(duì)象池中也會(huì)有很多不同類型的UITableViewCell,時(shí)可能會(huì)得到錯(cuò)誤類型的UITableViewCell那么UITableView在重用UITableViewCell。解決方案:UITableViewCell有個(gè)NSString *reuseIdentifier屬性,可以在初始化UITableViewCell的時(shí)候傳入一個(gè)特定的字符串標(biāo)識(shí)來(lái)設(shè)置reuseIdentifier(一般用UITableViewCell的類名)。當(dāng)UITableView要求dataSource返回UITableViewCell時(shí),先通過(guò)一個(gè)字符串標(biāo)識(shí)到對(duì)象池中查找對(duì)應(yīng)類型的UITableViewCell對(duì)象,如果有,就重用,如果沒(méi)有,就傳入這個(gè)字符串標(biāo)識(shí)來(lái)初始化一個(gè)UITableViewCell對(duì)象。

18、在一個(gè)對(duì)象的方法里面:self.name = @"object";和name =@"object";有什么不同嗎?

self.name = @"object";會(huì)調(diào)用對(duì)象的setName()方法,name =@"object";會(huì)直接把@"object"賦值給當(dāng)前對(duì)象的name 屬性。

19、為什么很多內(nèi)置類如UITableViewController的delegate屬性都是assign而不是retain的?

會(huì)引起循環(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)。

20、什么是Notification?

觀察者模式,controller向defaultNotificationCenter添加自己的notification,其他類注冊(cè)這個(gè)notification就可以收到通知,這些類可以在收到通知時(shí)做自己的操作(多觀察者默認(rèn)隨機(jī)順序發(fā)通知給觀察者們,而且每個(gè)觀察者都要等當(dāng)前的某個(gè)觀察者的操作做完才能輪到他來(lái)操作,可以用NotificationQueue的方式安排觀察者的反應(yīng)順序,也可以在添加觀察者中設(shè)定反映時(shí)間,取消觀察需要在viewDidUnload 跟dealloc中都要注銷)。

21、單例模式的作用?程序中有哪些常見(jiàn)的單例?單例的實(shí)現(xiàn)步驟?

單例模式的作用是解決“應(yīng)用中只有一個(gè)實(shí)例”的一類問(wèn)題。

dispatch_once函數(shù)是由GCD提供的,它的作用是在整個(gè)應(yīng)用程序生命周期中只執(zhí)行一次代碼塊。dispatch_once_t是由GCD提供的結(jié)構(gòu)體,使用時(shí)需要將GCD地址傳給dispatch_once函數(shù)。dispatch_once函數(shù)能夠記錄該代碼是否被調(diào)用過(guò)。

dispatch_once函數(shù)不僅意味著代碼僅會(huì)被執(zhí)行一次,而且還意味著此運(yùn)行還是線程同步的。也就是說(shuō),當(dāng)我們使用dispatch_once函數(shù)時(shí),就不需要再使用諸如@synchronized之類的語(yǔ)句。

應(yīng)用案例:UIApplication、NSUserDefaults、NSNotificationCenter、NSFileManager、NSBundle

UIApplication:

UIApplication類的實(shí)例提供了應(yīng)用程序的集中控制點(diǎn)來(lái)保持應(yīng)用的狀態(tài)。UIApplication實(shí)例總是分配給應(yīng)用程序委托對(duì)象(UIApplicationDelegate),通過(guò)應(yīng)用程序委托對(duì)象來(lái)響應(yīng)低內(nèi)存、應(yīng)用啟動(dòng)、后臺(tái)運(yùn)行和應(yīng)用終止等事件。

NSUserDefaults:

單例類NSUserDefaults可以很方便的讀取應(yīng)用設(shè)置項(xiàng)目。

NSNotificationCenter:

單例類NSNotificationCenter提供信息廣播通知,它采用觀察者模式的通知機(jī)制。

NSFileManager:

NSFileManager提供了訪問(wèn)文件系統(tǒng)的通用操作,可以定位、創(chuàng)建、復(fù)制文件和文件夾。

NSBundle:

NSBundle提供了動(dòng)態(tài)加載(或卸載)可執(zhí)行代碼、定位資源文件以及資源文件本地化、訪問(wèn)系統(tǒng)文件等功能。

要實(shí)現(xiàn)一個(gè)Singleton Class, 至少需要做以下四個(gè)步驟:

1). 為Singleton Object實(shí)現(xiàn)一個(gè)靜態(tài)實(shí)例, 初始化, 然后設(shè)置成nil.

2). 實(shí)現(xiàn)一個(gè)實(shí)例構(gòu)造方法(通常命名為 sharedInstance 或者 sharedManager)檢查上面聲名的靜態(tài)實(shí)例是否為nil, 如果是則新建并返回一個(gè)本類實(shí)例.

3). 重寫(xiě) allocWithZone: 方法來(lái)保證當(dāng)其他人直接使用 alloc 和 init 試圖獲得一個(gè)新實(shí)例的時(shí)候不會(huì)產(chǎn)生一個(gè)新的實(shí)例.

4). 適當(dāng)?shù)膶?shí)現(xiàn) copyWithZone:, release, retain, retainCount 和 autorelease.

22、block使用時(shí)的注意點(diǎn)?

Block可以使用在定義之前聲明的局部變量;

inti =10;void(^myBlock)() = ^{? NSLog(@"%d", i);};i =100;myBlock();

注意:

在定義Block時(shí),會(huì)在Block中建立當(dāng)前局部變量?jī)?nèi)容的副本(拷貝)

后續(xù)再對(duì)該變量的數(shù)值進(jìn)行修改,不會(huì)影響B(tài)lock中的數(shù)值

如果需要在block中保持局部變量的數(shù)值變化,需要使用__block關(guān)鍵字

使用__block關(guān)鍵字后,同樣可以在Block中修改該變量的數(shù)值

不能直接用點(diǎn)語(yǔ)法調(diào)用self的方法,會(huì)造成循環(huán)引用,要用中括號(hào)調(diào)用。

23、@private、@protected、@public、@package類型的成員變量的作用域?

@private:只能在當(dāng)前類的對(duì)象方法中訪問(wèn);

@protected:可以在當(dāng)前類以及子類的實(shí)現(xiàn)中直接訪問(wèn),默認(rèn)類型;

@public:任何地方都可以直接訪問(wèn)對(duì)象的成員變量;

@package:同一個(gè)“體系內(nèi)”(框架)可以訪問(wèn);

24、這個(gè)寫(xiě)法會(huì)出什么問(wèn)題:@property (copy) NSMutableArray *array;?

@property 的setter方法設(shè)置成copy以后,array這個(gè)指針指向的是一個(gè)不可變數(shù)組,那么當(dāng)使用點(diǎn)語(yǔ)法為給array賦值時(shí),就會(huì)發(fā)生“unrecognized selector sent to instance”錯(cuò)誤,程序就會(huì)崩潰。


3.寫(xiě)一個(gè)setter方法用于完成@property (nonatomic,retain)NSString *name,寫(xiě)一個(gè)setter方法用于完成@property(nonatomic,copy)NSString *name.

@property (nonatomic, retain) NSString *name;

- (void)setName:(NSString *)name

{

if (_name != name) {

[_name release];

_name = [name retain];

}

}

@property(nonatomic, copy) NSString *name;

- (void)setName:(NSString *)name

{

if (_name != name) {

[_name release];

_name = [name copy];

}

}

4.對(duì)于語(yǔ)句NSString *obj = [[NSData alloc] init]; ,編譯時(shí)和運(yùn)行時(shí)obj分別是什么類型

此題主要考察對(duì)運(yùn)行時(shí)機(jī)制的理解,編譯時(shí)是NSString類型 ,運(yùn)行時(shí)是NSData類型.

NSString *obj 對(duì)obj的類型沒(méi)有任何的作用,只是告訴編輯器你要把obj當(dāng)作NSString來(lái)使用,編輯器會(huì)給obj對(duì)象智能提醒和檢測(cè)NSString的api,幫助你編寫(xiě)代碼和語(yǔ)法檢查,僅此而已。

5.常見(jiàn)的object-c的數(shù)據(jù)類型有那些, 和C的基本數(shù)據(jù)類型有什么區(qū)別?

1.常用OC類型:NSString、NSArray、NSDictionary、NSData、NSNumber等

2.OC對(duì)象需要手動(dòng)管理內(nèi)存,C的基本數(shù)據(jù)類型不需要管理內(nèi)存

6.id 聲明的變量有什么特性?

id聲明的變量能指向任何OC對(duì)象。

參照第4題,id聲明的變量,相當(dāng)于告訴編輯器,

此變量的類型暫無(wú)具體類型,就是id類型,具體什么類型運(yùn)行時(shí)來(lái)決定。

7.Objective-C如何對(duì)內(nèi)存管理的,說(shuō)說(shuō)你的看法和解決方法?

內(nèi)存管理機(jī)制是每個(gè)iOS開(kāi)發(fā)者需要了解的。

1.每個(gè)對(duì)象都有一個(gè)引用計(jì)數(shù)器,每個(gè)新對(duì)象的計(jì)數(shù)器是1,當(dāng)對(duì)象的計(jì)數(shù)器減為0時(shí),就會(huì)被銷毀

2.通過(guò)retain可以讓對(duì)象的計(jì)數(shù)器+1、release可以讓對(duì)象的計(jì)數(shù)器-1

3.還可以通過(guò)autorelease pool管理內(nèi)存

4.如果用ARC,編譯器會(huì)自動(dòng)生成管理內(nèi)存的代碼

8.深拷貝和淺拷貝的區(qū)別?

深拷貝:拷貝內(nèi)容,產(chǎn)生新的對(duì)象。

淺拷貝:拷貝指針,不會(huì)產(chǎn)生新的對(duì)象

9.使用分類有什么優(yōu)點(diǎn)?分類和繼承的區(qū)別?

分類可以在不修改原來(lái)類模型的基礎(chǔ)上拓充方法

分類只能擴(kuò)充方法、不能擴(kuò)充成員變量;繼承可以擴(kuò)充方法和成員變量

繼承會(huì)產(chǎn)生新的類

10.分類和擴(kuò)展的區(qū)別?

分類是有名稱的,類擴(kuò)展沒(méi)有名稱

分類只能擴(kuò)充方法、不能擴(kuò)充成員變量;類擴(kuò)展可以擴(kuò)充方法和成員變量

類擴(kuò)展一般就寫(xiě)在.m文件中,用來(lái)擴(kuò)充私有的方法和成員變量(屬性)

11.KVC和KVO是什么?

KVC是鍵值編碼,可以通過(guò)一個(gè)字符串的key(屬性名)修改對(duì)象的屬性值

KVO是鍵值監(jiān)聽(tīng),可以監(jiān)聽(tīng)一個(gè)對(duì)象屬性值的改變

12.代理的目的是什么?

兩個(gè)對(duì)象之間傳遞數(shù)據(jù)和消息

解耦,拆分業(yè)務(wù)邏輯

13.在Objective C中什么是mutable和immutable類型

mutable是可變類型,比如NSMutableArray,可以動(dòng)態(tài)往里面添加元素

immutable是不可變類型,比如NSArray,固定的存儲(chǔ)空間,不能添加元素

14.什么是單例

單例:保證程序運(yùn)行過(guò)程中,永遠(yuǎn)只有一個(gè)對(duì)象實(shí)例

目的是:全局共享一份資源、節(jié)省不必要的內(nèi)存開(kāi)銷

常見(jiàn)單例:UIApplication、NSUserDefaults、NSNotificationCenter、NSFileManager、NSBundle等

15.什么時(shí)候使用NSMutableArray,什么時(shí)候使用NSArray?

當(dāng)數(shù)組元素需要?jiǎng)討B(tài)地添加或者刪除時(shí),用NSMutableArray

當(dāng)數(shù)組元素固定不變時(shí),用NSArray

16.什么情況下對(duì)象引用計(jì)數(shù)器會(huì)增加?

當(dāng)做retain或者copy操作的時(shí)候,都有可能增加計(jì)數(shù)器

17.在Objective C中關(guān)鍵字atomic有什么作用?

atomic是原子性

atomic會(huì)對(duì)set方法的實(shí)現(xiàn)進(jìn)行加鎖

18.Objective C有私有方法和私有變量嗎?

Objective C中沒(méi)有private,public類似的關(guān)鍵字來(lái)控制類的權(quán)限,寫(xiě)在.h文件中,就是公共方法

在.m文件中聲明和實(shí)現(xiàn)的方法,對(duì)編輯器來(lái)說(shuō)就是私有的

19.堆和棧的區(qū)別?

堆空間的內(nèi)存是動(dòng)態(tài)分配的,一般存放對(duì)象,并且需要手動(dòng)釋放內(nèi)存

棧空間的內(nèi)存由系統(tǒng)自動(dòng)分配,一般存放局部變量等,不需要手動(dòng)管理內(nèi)存

20.@property中有哪些屬性關(guān)鍵字?

1.readwrite(默認(rèn)):同時(shí)生成get方法和set方法的聲明和實(shí)現(xiàn)

2.readonly:只生成get方法的聲明和實(shí)現(xiàn)

3.assign(默認(rèn)):set方法的實(shí)現(xiàn)是直接賦值,用于基本數(shù)據(jù)類型

4.retain:set方法的實(shí)現(xiàn)是release舊值,retain新值,用于OC對(duì)象類型

5.copy:set方法的實(shí)現(xiàn)是release舊值,copy新值,用于NSString、block等類型

6.nonatomic:非原子性,set方法的實(shí)現(xiàn)不加鎖(比atomic性能高)

7.atomic(默認(rèn)):原子性,會(huì)在set方法加上讀寫(xiě)鎖

8.weak:弱指針類型,一般用于UI控件、id類型

9、strong (就是retain):強(qiáng)指針類型? 一般用于OC對(duì)象類型,除 (UI控件、代理類型、字符串對(duì)象)

21.OC有多繼承嗎?沒(méi)有的話用什么代替?

OC是單繼承,沒(méi)有多繼承,有時(shí)可以使用分類和協(xié)議來(lái)代替多繼承。

22.關(guān)鍵字const什么含義?

const int a;

int const a;

const int *a;

int const *a;

int * const a;

int const * const a;

1> 前兩個(gè)的作用是一樣:a 是一個(gè)不可修改的常整型數(shù),只讀

2> 第三、四個(gè)意味著 a 是一個(gè)指向常整型數(shù)的指針(整型數(shù)是不可修改的,但指針可以)

3> 第五個(gè)的意思:a 是一個(gè)指向整型數(shù)的常指針(指針指向的整型數(shù)是可以修改的,但指針是不可修改的)

4> 最后一個(gè)意味著:a 是一個(gè)指向常整型數(shù)的常指針(指針指向的整型數(shù)是不可修改的,同時(shí)指針也是不可修改的)

23.static的作用?

1.static修飾的函數(shù)是一個(gè)內(nèi)部函數(shù),只能在本文件中調(diào)用,其他文件不能調(diào)用

2. static修飾的全局變量是一個(gè)內(nèi)部變量,只能在本文件中使用,其他文件不能使用

3. static修飾的局部變量只會(huì)初始化一次,并且在程序退出時(shí)才會(huì)回收內(nèi)存

24.自動(dòng)釋放池常見(jiàn)面試代碼

for (int i = 0; i < 10; ++i)

{

NSString *str = @"Hello World";

str = [str stringByAppendingFormat:@" - %d", i];

str = [str uppercaseString];? ? NSLog(@"%@", str);

}

問(wèn):以上代碼存在什么樣的問(wèn)題?如果循環(huán)的次數(shù)非常大時(shí),應(yīng)該如何修改?

解決辦法1:如果i比較大,可以用@autoreleasepool {}解決,放在for循環(huán)外,循環(huán)結(jié)束后,銷毀創(chuàng)建的對(duì)象,解決占據(jù)棧區(qū)內(nèi)存的問(wèn)題

解決方法2:如果i玩命大,一次循環(huán)都會(huì)造成自動(dòng)釋放池被填滿,自動(dòng)釋放池放在for循環(huán)內(nèi),每次循環(huán)都將上一次創(chuàng)建的對(duì)象release

25.@private、@protected、@public、@package類型的成員變量的作用域?

- @private:只能在當(dāng)前類的對(duì)象方法中訪問(wèn);

- @protected:可以在當(dāng)前類以及子類的實(shí)現(xiàn)中直接訪問(wèn),默認(rèn)類型;

- @public:任何地方都可以直接訪問(wèn)對(duì)象的成員變量;

- @package:同一個(gè)“體系內(nèi)”(框架)可以訪問(wèn);

26.這個(gè)寫(xiě)法會(huì)出什么問(wèn)題:@property (copy) NSMutableArray *array;?

@property 的setter方法設(shè)置成copy以后,array這個(gè)指針指向的是一個(gè)不可變數(shù)組,

那么當(dāng)使用點(diǎn)語(yǔ)法為給array賦值時(shí),就會(huì)發(fā)生“unrecognized selector sent to instance”錯(cuò)誤,程序就會(huì)崩潰。

27.調(diào)用對(duì)象的release 方法會(huì)銷毀對(duì)象嗎?

不會(huì),調(diào)用對(duì)象的release 方法只是將對(duì)象的引用計(jì)數(shù)器-1,當(dāng)對(duì)象的引用計(jì)數(shù)器為0的時(shí)候會(huì)調(diào)用了對(duì)象的dealloc 方法才能進(jìn)行釋放對(duì)象的內(nèi)存。

28.什么情況使用 weak 關(guān)鍵字,相比 assign 有什么不同?

1>.什么情況使用weak關(guān)鍵字?

- 在 ARC 中,在有可能出現(xiàn)循環(huán)引用的時(shí)候,往往要通過(guò)讓其中一端使用 weak 來(lái)解決,比如: delegate 代理屬性

- 自身已經(jīng)對(duì)它進(jìn)行一次強(qiáng)引用,沒(méi)有必要再?gòu)?qiáng)引用一次,此時(shí)也會(huì)使用 weak,自定義 IBOutlet 控件屬性一般也使用 weak;當(dāng)然,也可以使用strong。

2>.weak與assign的不同?

- weak 此特質(zhì)表明該屬性定義了一種“非擁有關(guān)系” (nonowning relationship)。為這種屬性設(shè)置新值時(shí),設(shè)置方法既不保留新值,也不釋放舊值。此特質(zhì)同assign類似, 然而在屬性所指的對(duì)象遭到摧毀時(shí),屬性值也會(huì)清空(nil out)。 而 assign 的“設(shè)置方法”只會(huì)執(zhí)行針對(duì)“純量類型” (scalar type,例如 CGFloat 或 NSlnteger 等)的簡(jiǎn)單賦值操作。

- assigin 可以用非 OC 對(duì)象,而 weak 必須用于 OC 對(duì)象

29.XIB與Storyboards的優(yōu)缺點(diǎn)?

- XIB:在編譯前就提供了可視化界面,可以直接拖控件,也可以直接給控件添加約束,更直觀一些,而且類文件中就少了創(chuàng)建控件的代碼,確實(shí)簡(jiǎn)化不少,通常每個(gè)XIB對(duì)應(yīng)一個(gè)類。

- Storyboard:在編譯前提供了可視化界面,可拖控件,可加約束,在開(kāi)發(fā)時(shí)比較直觀,而且一個(gè)storyboard可以有很多的界面,每個(gè)界面對(duì)應(yīng)一個(gè)類文件,通過(guò)storybard,可以直觀地看出整個(gè)App的結(jié)構(gòu)。

- XIB:需求變動(dòng)時(shí),需要修改XIB很大,有時(shí)候甚至需要重新添加約束,導(dǎo)致開(kāi)發(fā)周期變長(zhǎng)。XIB載入相比純代碼自然要慢一些。對(duì)于比較復(fù)雜邏輯控制不同狀態(tài)下顯示不同內(nèi)容時(shí),使用XIB是比較困難的。當(dāng)多人團(tuán)隊(duì)或者多團(tuán)隊(duì)開(kāi)發(fā)時(shí),如果XIB文件被發(fā)動(dòng),極易導(dǎo)致沖突,而且解決沖突相對(duì)要困難很多。

- Storyboard:需求變動(dòng)時(shí),需要修改storyboard上對(duì)應(yīng)的界面的約束,與XIB一樣可能要重新添加約束,或者添加約束會(huì)造成大量的沖突,尤其是多團(tuán)隊(duì)開(kāi)發(fā)。對(duì)于復(fù)雜邏輯控制不同顯示內(nèi)容時(shí),比較困難。當(dāng)多人團(tuán)隊(duì)或者多團(tuán)隊(duì)開(kāi)發(fā)時(shí),大家會(huì)同時(shí)修改一個(gè)storyboard,導(dǎo)致大量沖突,解決起來(lái)相當(dāng)困難。

30.@synthesize和@dynamic分別有什么作用?

- @property有兩個(gè)對(duì)應(yīng)的詞,一個(gè)是 @synthesize,一個(gè)是 @dynamic。如果 @synthesize和 @dynamic都沒(méi)寫(xiě),那么默認(rèn)的就是@syntheszie var = _var;

- @synthesize 的語(yǔ)義是如果你沒(méi)有手動(dòng)實(shí)現(xiàn) setter 方法和 getter 方法,那么編譯器會(huì)自動(dòng)為你加上這兩個(gè)方法。

- @dynamic 告訴編譯器:屬性的 setter 與 getter 方法由用戶自己實(shí)現(xiàn),不自動(dòng)生成。(當(dāng)然對(duì)于 readonly 的屬性只需提供 getter 即可)。假如一個(gè)屬性被聲明為 @dynamic var,然后你沒(méi)有提供 @setter方法和 @getter 方法,編譯的時(shí)候沒(méi)問(wèn)題,但是當(dāng)程序運(yùn)行到 instance.var = someVar,由于缺 setter 方法會(huì)導(dǎo)致程序崩潰;或者當(dāng)運(yùn)行到 someVar = var 時(shí),由于缺 getter 方法同樣會(huì)導(dǎo)致崩潰。編譯時(shí)沒(méi)問(wèn)題,運(yùn)行時(shí)才執(zhí)行相應(yīng)的方法,這就是所謂的動(dòng)態(tài)綁定。

31.objc中的類方法和實(shí)例方法有什么本質(zhì)區(qū)別和聯(lián)系?

類方法:

- 類方法是屬于類對(duì)象的

- 類方法只能通過(guò)類對(duì)象調(diào)用

- 類方法中的self是類對(duì)象

- 類方法可以調(diào)用其他的類方法

- 類方法中不能訪問(wèn)成員變量

- 類方法中不能直接調(diào)用對(duì)象方法

實(shí)例方法:

- 實(shí)例方法是屬于實(shí)例對(duì)象的

- 實(shí)例方法只能通過(guò)實(shí)例對(duì)象調(diào)用

- 實(shí)例方法中的self是實(shí)例對(duì)象

- 實(shí)例方法中可以訪問(wèn)成員變量

- 實(shí)例方法中直接調(diào)用實(shí)例方法

- 實(shí)例方法中也可以調(diào)用類方法(通過(guò)類名)

32.Objective-C 中是否支持垃圾回收機(jī)制?

- OC是支持垃圾回收機(jī)制的(Garbage collection簡(jiǎn)稱GC),但是apple的移動(dòng)終端中,是不支持GC的,Mac桌面系統(tǒng)開(kāi)發(fā)中是支持的.

- 移動(dòng)終端開(kāi)發(fā)是支持ARC(Automatic Reference Counting的簡(jiǎn)稱),ARC是在IOS5之后推出的新技術(shù),它與GC的機(jī)制是不同的。我們?cè)诰帉?xiě)代碼時(shí), 不需要向?qū)ο蟀l(fā)送release或者autorelease方法,也不可以調(diào)用delloc方法,編譯器會(huì)在合適的位置自動(dòng)給用戶生成release消息(autorelease),ARC 的特點(diǎn)是自動(dòng)引用技術(shù)簡(jiǎn)化了內(nèi)存管理的難度.

33.在 Objective-C 中如何實(shí)現(xiàn) KVO?

- 注冊(cè)觀察者(注意:觀察者和被觀察者不會(huì)被保留也不會(huì)被釋放)

- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context;

- 接收變更通知

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

- 移除對(duì)象的觀察者身份

- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath;

- KVO中誰(shuí)要監(jiān)聽(tīng)誰(shuí)注冊(cè),然后對(duì)響應(yīng)進(jìn)行處理,使得觀察者與被觀察者完全解耦。KVO只檢測(cè)類中的屬性,并且屬性名都是通過(guò)NSString來(lái)查找,編譯器不會(huì)檢錯(cuò)和補(bǔ)全,全部取決于自己。

1、KVC的底層實(shí)現(xiàn)?

當(dāng)一個(gè)對(duì)象調(diào)用setValue方法時(shí),方法內(nèi)部會(huì)做以下操作:

①檢查是否存在相應(yīng)key的set方法,如果存在,就調(diào)用set方法

②如果set方法不存在,就會(huì)查找與key相同名稱并且?guī)聞澗€的成員屬性,如果有,則直接給成員屬性賦值

③如果沒(méi)有找到_key,就會(huì)查找相同名稱的屬性key,如果有就直接賦值

④如果還沒(méi)找到,則調(diào)用valueForUndefinedKey:和setValue:forUndefinedKey:方法。

這些方法的默認(rèn)實(shí)現(xiàn)都是拋出異常,我們可以根據(jù)需要重寫(xiě)它們。

2、__block和__weak修飾符的區(qū)別?

1.__block不管是ARC還是MRC模式下都可以使用,可以修飾對(duì)象,還可以修飾基本數(shù)據(jù)類型。

2.__weak只能在ARC模式下使用,也只能修飾對(duì)象(NSString),不能修飾基本數(shù)據(jù)類型(int)。

3.__block對(duì)象可以在block中被重新賦值,__weak不可以。

3、block和代理的區(qū)別,哪個(gè)更好?

代理回調(diào)更面向過(guò)程,block更面向結(jié)果。

如果需要在執(zhí)行的不同步驟時(shí)被通知,你就要使用代理。

如果只需要請(qǐng)求的消息或者失敗的詳情,應(yīng)該使用block。

block更適合與狀態(tài)無(wú)關(guān)的操作,比如被告知某些結(jié)果,block之間是不會(huì)相互影響的。

但是代理更像一個(gè)生產(chǎn)流水線,每個(gè)回調(diào)方法是生產(chǎn)線上的一個(gè)處理步驟,一個(gè)回調(diào)的變動(dòng)可能會(huì)引起另一個(gè)回調(diào)的變動(dòng)。

要是一個(gè)對(duì)象有超過(guò)一個(gè)的不同事件,應(yīng)該使用代理。

一個(gè)對(duì)象只有一個(gè)代理,要是某個(gè)對(duì)象是個(gè)單例對(duì)象,就不能使用代理。

要是一個(gè)對(duì)象調(diào)用方法需要返回一些額外的信息,就可能需要使用代理。

4、Object C中創(chuàng)建線程的方法是什么?如果在主線程中執(zhí)行代碼,方法是什么?如果想延時(shí)執(zhí)行代碼、方法又是什么?

線程創(chuàng)建有三種方法:使用NSThread創(chuàng)建、使用GCD的dispatch、使用子類化的NSOperation,然后將其加入NSOperationQueue;

NSThread創(chuàng)建線程的三種方法:

NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(run:) object:@"nil"];

[NSThread detachNewThreadSelector:@selector(run:) toTarget:self withObject:@"我是分離出來(lái)的子線程"];

[self performSelectorInBackground:@selector(run:) withObject:@"我是后臺(tái)線程"];

在主線程執(zhí)行代碼,就調(diào)用performSelectorOnMainThread方法。

如果想延時(shí)執(zhí)行代碼可以調(diào)用performSelector:onThread:withObject:waitUntilDone:方法;

GCD:

利用異步函數(shù)dispatch_async()創(chuàng)建子線程。

在主線程執(zhí)行代碼,dispatch_async(dispatch_get_main_queue(), ^{});

延遲執(zhí)行代碼(延遲·可以控制代碼在哪個(gè)線程執(zhí)行):

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{});

NSOperationQueue:

使用NSOperation的子類封裝操作,再將操作添加到NSOperationQueue創(chuàng)建的隊(duì)列中,實(shí)現(xiàn)多線程。

在主線程執(zhí)行代碼,只要將封裝代碼的NSOperation對(duì)象添加到主隊(duì)列就可以了。

5、控制器view的生命周期?

控制器view是懶加載,用到的時(shí)候才加載。

生命周期方法調(diào)用順序:

loadView-->viewDidLoad-->viewWillAppear

-->viewDidAppear-->viewWillDisappear-->viewDidDisappear

-->didReceiveMemoryWarning(收到內(nèi)存警告)

-->viewWillUnload-->viewDidUnload

6、控制器View的加載過(guò)程?

當(dāng)程序訪問(wèn)了控制器的View屬性時(shí)會(huì)先判斷控制器的View是否存在,如果存在就直接返回已經(jīng)存在的View;

如果不存在,就會(huì)先調(diào)用loadView這個(gè)方法;如果控制器的loadView方法實(shí)現(xiàn)了,就會(huì)按照l(shuí)oadView方法加載自定義的View;

如果控制器的loadView方法沒(méi)有實(shí)現(xiàn)就會(huì)判斷storyboard是否存在;

如果storyboard存在就會(huì)按照storyboard加載控制器的View;如果storyboard不存在,就會(huì)創(chuàng)建一個(gè)空視圖返回。

7、iOS開(kāi)發(fā)中數(shù)據(jù)存儲(chǔ)的方法?

常見(jiàn)存儲(chǔ)方法有三種:plist存儲(chǔ)、偏好設(shè)置(NSUserDefaults)和歸檔。

屬性列表(plist)存儲(chǔ):

適用對(duì)象:只有帶有writeToFil方法的對(duì)象才能用這種方法,比如NSString、、NSArray、NSDictionary、NSSet、NSNumber、NSData等,不能存儲(chǔ)自定義的對(duì)象

存儲(chǔ)方法:

調(diào)用對(duì)象的writeToFile...方法就可以寫(xiě)入文件

讀取方法:

調(diào)用對(duì)象的...WithContentsOfFile方法就可以從文件中讀取對(duì)象內(nèi)容

偏好設(shè)置(NSUserDefaults):

適用對(duì)象:使用NSUserDefaults,存儲(chǔ)用戶關(guān)于應(yīng)用的偏好設(shè)置,本質(zhì)上仍然是plist存儲(chǔ),不能存儲(chǔ)自定義的OC對(duì)象

存儲(chǔ)方法:

利用NSUserDefaults的setObject等方法進(jìn)行存儲(chǔ)

讀取方法:

利用NSUserDefaults的objectForKey等方法進(jìn)行讀取

歸檔(NSKeyedArchiver):

適用對(duì)象:可以存儲(chǔ)自定義的對(duì)象,只有遵守了NSCoding協(xié)議的對(duì)象才可以

存儲(chǔ)方法(歸檔):

調(diào)用NSKeyedArchiver的archiverRootObject: toFile: 方法存儲(chǔ)對(duì)象,archiverRootObject執(zhí)行這個(gè)方法時(shí),底層就會(huì)調(diào)用要存的對(duì)象的encodeWithCoder方法,

調(diào)用encodeWithCoder目的就是想詢問(wèn)下要存對(duì)象的哪些屬性

讀取方法(解檔):

調(diào)用NSKeyedArchiver的unarchiverObjectWithFile:方法,執(zhí)行enachiverObjectWithFile:方法時(shí)就會(huì)調(diào)用initWithCoder:方法,

調(diào)用initWithCoder:方法目的就是詢問(wèn)下要讀的對(duì)象有那些屬性要讀,怎么讀。

注意:

當(dāng)有繼承關(guān)系時(shí),必須調(diào)用父類的歸檔解檔方法,當(dāng)有組合包含關(guān)系時(shí),也必須實(shí)現(xiàn)所包含對(duì)象類的歸檔解檔方法。

8、為什么很多內(nèi)置類如UITableViewController的delegate屬性都是weak而不是strong?

會(huì)引起循環(huán)引用的問(wèn)題。

UITableViewController內(nèi)部有一個(gè)強(qiáng)指針tableView屬性,

tableView指針指向一個(gè)UITableView,UITableView內(nèi)部有一個(gè)強(qiáng)指針subviews屬性,

指向一個(gè)裝著UITableView全部的子控件的強(qiáng)指針數(shù)組,數(shù)組中又有強(qiáng)指針指向UITableView中存在的子控件。

tableView內(nèi)部有一個(gè)指針delegate,tableView的delegate就是控制器本身,二者相互引用,

如果delegate屬性是strong就會(huì)引起循環(huán)應(yīng)用,造成內(nèi)存泄露,因此必須有一個(gè)對(duì)象是弱指針,所以delegate是weak。

9、UI控件為什么不用strong用weak?

控制器有個(gè)強(qiáng)指針View屬性,View屬性指向內(nèi)存中的一個(gè)UIView,UIView內(nèi)部有一個(gè)強(qiáng)指針subviews屬性,

指向一個(gè)裝著UIView全部的子控件的強(qiáng)指針數(shù)組,數(shù)組中又有強(qiáng)指針指向UIView中存在的子控件。

所以,只要控制器在,View就在,View中的子控件就在,所以,ui控件沒(méi)必要用強(qiáng)指針,用weak就可以。

10、block使用時(shí)的注意點(diǎn)?

Block可以使用在定義之前聲明的局部變量。

int i = 10;

void(^myBlock)() = ^{

NSLog(@"%d", i);

};

i = 100;

myBlock();

注意:

在定義Block時(shí),會(huì)在Block中建立當(dāng)前局部變量?jī)?nèi)容的副本(拷貝)。

后續(xù)再對(duì)該變量的數(shù)值進(jìn)行修改,不會(huì)影響B(tài)lock中的數(shù)值。

以上代碼輸出結(jié)果為10。

如果需要在block中保持局部變量的數(shù)值變化,需要使用__block關(guān)鍵字。使用__block關(guān)鍵字后,同樣可以在Block中修改該變量的數(shù)值。

將第一行代碼改為: __block int i = 10;后,輸出結(jié)果就變成了100;

另外:block代碼塊中不能直接用點(diǎn)語(yǔ)法調(diào)用self的方法,會(huì)造成循環(huán)引用,要用中括號(hào)調(diào)用。

11、如何對(duì)UITableView進(jìn)行優(yōu)化?

UITableViewCell的重用原理:

當(dāng)滾動(dòng)列表時(shí),部分UITableViewCell會(huì)移出窗口,UITableView會(huì)將窗口外的UITableViewCell放入一個(gè)對(duì)象池中,等待重用。

當(dāng)UITableView要求dataSource返回UITableViewCell時(shí),dataSource會(huì)先查看這個(gè)對(duì)象池,如果池中有未使用的UITableViewCell,

dataSource會(huì)用新的數(shù)據(jù)配置這個(gè)UITableViewCell,然后返回給UITableView,重新顯示到窗口中,從而避免創(chuàng)建新對(duì)象。

還有一個(gè)非常重要的問(wèn)題:有時(shí)候需要自定義UITableViewCell(用一個(gè)子類繼承UITableViewCell),

而且每一行用的不一定是同一種UITableViewCell(如短信聊天布局),所以一個(gè)UITableView可能擁有不同類型的UITableViewCell,

對(duì)象池中也會(huì)有很多不同類型的UITableViewCell,時(shí)可能會(huì)得到錯(cuò)誤類型的UITableViewCell那么UITableView在重用UITableViewCell。

解決方案:UITableViewCell有個(gè)NSString *reuseIdentifier屬性,可以在初始化UITableViewCell的時(shí)候傳入一個(gè)特定的字符串標(biāo)識(shí)來(lái)設(shè)置reuseIdentifier(一般用UITableViewCell的類名)。

當(dāng)UITableView要求dataSource返回UITableViewCell時(shí),

先通過(guò)一個(gè)字符串標(biāo)識(shí)到對(duì)象池中查找對(duì)應(yīng)類型的UITableViewCell對(duì)象,

如果有,就重用,如果沒(méi)有,就傳入這個(gè)字符串標(biāo)識(shí)來(lái)初始化一個(gè)UITableViewCell對(duì)象。

12、UIView動(dòng)畫(huà)與核心動(dòng)畫(huà)的區(qū)別?

UIView動(dòng)畫(huà)與核心動(dòng)畫(huà)的區(qū)別:

1、核心動(dòng)畫(huà)只作用在CALayer上面,UIView是沒(méi)有辦法使用核心動(dòng)畫(huà)的

2、核心動(dòng)畫(huà)看到的都是假象,并沒(méi)有修改UIView的真實(shí)位置

什么時(shí)候使用UIView動(dòng)畫(huà)?

需要與用戶進(jìn)行交互的時(shí)候使用UIView動(dòng)畫(huà),如果不需要與用戶進(jìn)行交互,兩者都可以使用。

什么時(shí)候使用核心動(dòng)畫(huà)?

1、根據(jù)路徑做動(dòng)畫(huà),要使用核心動(dòng)畫(huà)(幀動(dòng)畫(huà))

2、做轉(zhuǎn)場(chǎng)動(dòng)畫(huà)時(shí),也要使用核心動(dòng)畫(huà)

13、自定義視圖中重寫(xiě)layoutsubView需要調(diào)用父類的layoutsubView嗎,為什么?

如果重寫(xiě)的控件是UIView不調(diào)用父類的layoutsubView也沒(méi)關(guān)系,里面沒(méi)有任何子控件,所以不會(huì)做什么事情。一般系統(tǒng)自帶視圖中有子控件的都會(huì)重寫(xiě)layoutSubviews方法,因此我們自定義系統(tǒng)自帶控件并且重寫(xiě)layoutSubviews必須調(diào)用[super layoutSubviews],先布局系統(tǒng)自帶子控件的位置和尺寸,才設(shè)置我們自己的控件位置和尺寸。否則會(huì)發(fā)現(xiàn)想用系統(tǒng)自帶視圖的子控件的時(shí)候,會(huì)出現(xiàn)意想不到的效果。

14、應(yīng)用程序的啟動(dòng)流程?

1.執(zhí)行Main

2.執(zhí)行UIApplicationMain函數(shù).

3.創(chuàng)建UIApplication對(duì)象,并設(shè)置UIApplicationMain對(duì)象的代理.

UIApplication的第三個(gè)參數(shù)就是UIApplication的名稱,如果指定為nil,它會(huì)默認(rèn)為UIApplication.

UIApplication的第四個(gè)參數(shù)為UIApplication的代理.

4.開(kāi)啟一個(gè)主運(yùn)行循環(huán).保證應(yīng)用程序不退出.

5.加載info.plist.加載配置文件.判斷一下info.plist文件當(dāng)中有沒(méi)有Main storyboard file base name里面有沒(méi)有指定storyboard文件,如果有就去加載info.plist文件,如果沒(méi)有,那么應(yīng)用程序加載完畢.

15、NSString 的時(shí)候用copy和strong的區(qū)別?

OC中NSString為不可變字符串的時(shí)候,用copy和strong都是只分配一次內(nèi)存,但是如果用copy的時(shí)候,需要先判斷字符串是否是不可變字符串,如果是不可變字符串,就不再分配空間,如果是可變字符串才分配空間。如果程序中用到NSString的地方特別多,每一次都要先進(jìn)行判斷就會(huì)耗費(fèi)性能,影響用戶體驗(yàn),用strong就不會(huì)再進(jìn)行判斷,所以,不可變字符串可以直接用strong。

16、事件傳遞與響應(yīng)的完整過(guò)程?

在產(chǎn)生一個(gè)事件時(shí),系統(tǒng)會(huì)將該事件加入到一個(gè)由UIApplication管理的事件隊(duì)列中,

UIApplication會(huì)從事件隊(duì)列中取出最前面的事件,將它傳遞給先發(fā)送事件給應(yīng)用程序的主窗口.

主窗口會(huì)調(diào)用hitTest方法尋找最適合的視圖控件,找到后就會(huì)調(diào)用視圖控件的touches方法來(lái)做具體的事情.

當(dāng)調(diào)用touches方法,它的默認(rèn)做法, 就會(huì)將事件順著響應(yīng)者鏈條往上傳遞,

傳遞給上一個(gè)響應(yīng)者,接著就會(huì)調(diào)用上一個(gè)響應(yīng)者的touches方法

17.ASIHttpRequest、AFNetWorking之間的區(qū)別?

- ASIHttpRequest功能強(qiáng)大,主要是在MRC下實(shí)現(xiàn)的,是對(duì)系統(tǒng)CFNetwork API進(jìn)行了封裝,支持HTTP協(xié)議的CFHTTP,配置比較復(fù)雜,并且ASIHttpRequest框架默認(rèn)不會(huì)幫你監(jiān)聽(tīng)網(wǎng)絡(luò)改變,如果需要讓ASIHttpRequest幫你監(jiān)聽(tīng)網(wǎng)絡(luò)狀態(tài)改變,并且手動(dòng)開(kāi)始這個(gè)功能。

- AFNetWorking構(gòu)建于NSURLConnection、NSOperation以及其他熟悉的Foundation技術(shù)之上。擁有良好的架構(gòu),豐富的API及模塊構(gòu)建方式,使用起來(lái)非常輕松。它基于NSOperation封裝的,AFURLConnectionOperation子類。

- ASIHttpRequest是直接操作對(duì)象ASIHttpRequest是一個(gè)實(shí)現(xiàn)了NSCoding協(xié)議的NSOperation子類;AFNetWorking直接操作對(duì)象的AFHttpClient,是一個(gè)實(shí)現(xiàn)NSCoding和NSCopying協(xié)議的NSObject子類。

- 同步請(qǐng)求:ASIHttpRequest直接通過(guò)調(diào)用一個(gè)startSynchronous方法;AFNetWorking默認(rèn)沒(méi)有封裝同步請(qǐng)求,如果開(kāi)發(fā)者需要使用同步請(qǐng)求,則需要重寫(xiě)getPath:paraments:success:failures方法,對(duì)于AFHttpRequestOperation進(jìn)行同步處理。

- 性能對(duì)比:AFNetworking請(qǐng)求優(yōu)于ASIHttpRequest;

18.如何進(jìn)行真機(jī)調(diào)試?

1.首先需要用鑰匙串創(chuàng)建一個(gè)鑰匙(key);

2.將鑰匙串上傳到官網(wǎng),獲取iOS Development證書(shū);

3.創(chuàng)建App ID即我們應(yīng)用程序中的Boundle ID;

4.添加Device ID即UDID;

5.通過(guò)勾選前面所創(chuàng)建的證書(shū):App ID、Device ID;

6.生成mobileprovision文件;

7.先決條件:申請(qǐng)開(kāi)發(fā)者賬號(hào) 99美刀

19.APP發(fā)布的上架流程?

1.登錄應(yīng)用發(fā)布網(wǎng)站添加應(yīng)用信息;

2.下載安裝發(fā)布證書(shū);

3.選擇發(fā)布證書(shū),使用Archive編譯發(fā)布包,用Xcode將代碼(發(fā)布包)上傳到服務(wù)器;

4.等待審核通過(guò);

5.生成IPA:菜單欄->Product->Archive.

20.能否向編譯后得到的類中增加實(shí)例變量?能否向運(yùn)行時(shí)創(chuàng)建的類中添加實(shí)例變量?為什么?

- 不能向編譯后得到的類中增加實(shí)例變量;

- 能向運(yùn)行時(shí)創(chuàng)建的類中添加實(shí)例變量;

解釋如下:

因?yàn)榫幾g后的類已經(jīng)注冊(cè)在 runtime 中,類結(jié)構(gòu)體中的 objc_ivar_list 實(shí)例變量的鏈表 和 instance_size 實(shí)例變量的內(nèi)存大小已經(jīng)確定,同時(shí)runtime 會(huì)調(diào)用 class_setIvarLayout 或 class_setWeakIvarLayout 來(lái)處理 strong weak 引用。所以不能向存在的類中添加實(shí)例變量;

運(yùn)行時(shí)創(chuàng)建的類是可以添加實(shí)例變量,調(diào)用 class_addIvar 函數(shù)。但是得在調(diào)用 objc_allocateClassPair 之后,objc_registerClassPair 之前,原因同上。

21.以+ scheduledTimerWithTimeInterval...的方式觸發(fā)的timer,在滑動(dòng)頁(yè)面上的列表時(shí),timer會(huì)暫定回調(diào),為什么?如何解決?

RunLoop只能運(yùn)行在一種mode下,如果要換mode,當(dāng)前的loop也需要停下重啟成新的。利用這個(gè)機(jī)制,ScrollView滾動(dòng)過(guò)程中NSDefaultRunLoopMode(kCFRunLoopDefaultMode)的mode會(huì)切換到UITrackingRunLoopMode來(lái)保證ScrollView的流暢滑動(dòng):只能在NSDefaultRunLoopMode模式下處理的事件會(huì)影響ScrollView的滑動(dòng)。

如果我們把一個(gè)NSTimer對(duì)象以NSDefaultRunLoopMode(kCFRunLoopDefaultMode)添加到主運(yùn)行循環(huán)中的時(shí)候, ScrollView滾動(dòng)過(guò)程中會(huì)因?yàn)閙ode的切換,而導(dǎo)致NSTimer將不再被調(diào)度。

同時(shí)因?yàn)閙ode還是可定制的,所以:

Timer計(jì)時(shí)會(huì)被scrollView的滑動(dòng)影響的問(wèn)題可以通過(guò)將timer添加到NSRunLoopCommonModes(kCFRunLoopCommonModes)來(lái)解決。代碼如下:

//將timer添加到NSDefaultRunLoopMode中

[NSTimer scheduledTimerWithTimeInterval: target: selector:@selector(timerTick:) userInfo: repeats:];

//然后再添加到NSRunLoopCommonModes里

NSTimer *timer = [NSTimer timerWithTimeInterval: target: selector:@selector(timerTick:) userInfo: repeats:];

[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];

22.runloop和線程有什么關(guān)系?

總的說(shuō)來(lái),Run loop,正如其名,loop表示某種循環(huán),和run放在一起就表示一直在運(yùn)行著的循環(huán)。實(shí)際上,run loop和線程是緊密相連的,可以這樣說(shuō)run loop是為了線程而生,沒(méi)有線程,它就沒(méi)有存在的必要。Run loops是線程的基礎(chǔ)架構(gòu)部分, Cocoa 和 CoreFundation 都提供了 run loop 對(duì)象方便配置和管理線程的 run loop (以下都以 Cocoa 為例)。每個(gè)線程,包括程序的主線程( main thread )都有與之相應(yīng)的 run loop 對(duì)象。

runloop 和線程的關(guān)系:

- 主線程的run loop默認(rèn)是啟動(dòng)的。

iOS的應(yīng)用程序里面,程序啟動(dòng)后會(huì)有一個(gè)如下的main()函數(shù)

( argc,? * argv[]) {

@autoreleasepool {

return UIApplicationMain(argc, argv, , NSStringFromClass([AppDelegate class]));

}

}

重點(diǎn)是UIApplicationMain()函數(shù),這個(gè)方法會(huì)為main thread設(shè)置一個(gè)NSRunLoop對(duì)象,這就解釋了:為什么我們的應(yīng)用可以在無(wú)人操作的時(shí)候休息,需要讓它干活的時(shí)候又能立馬響應(yīng)。

- 對(duì)其它線程來(lái)說(shuō),run loop默認(rèn)是沒(méi)有啟動(dòng)的,如果你需要更多的線程交互則可以手動(dòng)配置和啟動(dòng),如果線程只是去執(zhí)行一個(gè)長(zhǎng)時(shí)間的已確定的任務(wù)則不需要。

- 在任何一個(gè) Cocoa 程序的線程中,都可以通過(guò)以下代碼來(lái)獲取到當(dāng)前線程的 run loop 。

NSRunLoop *runloop = [NSRunLoop currentRunLoop];

23.如何用GCD同步若干個(gè)異步調(diào)用?(如根據(jù)若干個(gè)url異步加載多張圖片,然后在都下載完成后合成一張整圖)

使用Dispatch Group追加block到Global Group Queue,這些block如果全部執(zhí)行完畢,就會(huì)執(zhí)行Main Dispatch Queue中的結(jié)束處理的block。

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, );

dispatch_group_t group = dispatch_group_create();

dispatch_group_async(group, queue, ^{ /*加載圖片1 */ });

dispatch_group_async(group, queue, ^{ /*加載圖片2 */ });

dispatch_group_async(group, queue, ^{ /*加載圖片3 */ });

dispatch_group_notify(group, dispatch_get_main_queue(), ^{

// 合并圖片

});

24.HTTP協(xié)議的特點(diǎn),關(guān)于HTTP請(qǐng)求GET和POST的區(qū)別?

HTTP協(xié)議的特點(diǎn):

- HTTP超文本傳輸協(xié)議,是短連接,是客戶端主動(dòng)發(fā)送請(qǐng)求,服務(wù)器做出響應(yīng),服務(wù)器響應(yīng)之后,鏈接斷開(kāi)。HTTP是一個(gè)屬于應(yīng)用層面向?qū)ο蟮膮f(xié)議,HTTP有兩類報(bào)文:請(qǐng)求報(bào)文和響應(yīng)報(bào)文。

- HTTP請(qǐng)求報(bào)文:一個(gè)HTTP請(qǐng)求報(bào)文由請(qǐng)求行、請(qǐng)求頭部、空行和請(qǐng)求數(shù)據(jù)4部分組成。

- HTTP響應(yīng)報(bào)文:由三部分組成:狀態(tài)行、消息報(bào)頭、響應(yīng)正文。

GET和POST的區(qū)別:

- GET請(qǐng)求:參數(shù)在地址后拼接,沒(méi)有請(qǐng)求數(shù)據(jù),不安全(因?yàn)樗袇?shù)都拼接在地址后面),不適合傳輸大量數(shù)據(jù)(長(zhǎng)度有限制,為1024個(gè)字節(jié))。

GET提交、請(qǐng)求的數(shù)據(jù)會(huì)附在URL之后,即把數(shù)據(jù)放置在HTTP協(xié)議頭中。以?分割URL和傳輸數(shù)據(jù),多個(gè)參數(shù)用&連接。如果數(shù)據(jù)是英文字母或數(shù)字,原樣發(fā)送,如果是空格,轉(zhuǎn)換為+,如果是中文/其他字符,則直接把字符串用BASE64加密。

- POST請(qǐng)求:參數(shù)在請(qǐng)求數(shù)據(jù)區(qū)放著,相對(duì)GET請(qǐng)求更安全,并且數(shù)據(jù)大小沒(méi)有限制。把提交的數(shù)據(jù)放置在HTTP包的包體中.

- GET提交的數(shù)據(jù)會(huì)在地址欄顯示出來(lái),而POST提交,地址欄不會(huì)改變。

傳輸數(shù)據(jù)的大小:

- GET提交時(shí),傳輸數(shù)據(jù)就會(huì)受到URL長(zhǎng)度限制,POST由于不是通過(guò)URL傳值,理論上書(shū)不受限。

- POST的安全性要比GET的安全性高;

- 通過(guò)GET提交數(shù)據(jù),用戶名和密碼將明文出現(xiàn)在URL上,比如登陸界面有可能被瀏覽器緩存。

25.如何理解MVC設(shè)計(jì)模式?

MVC是一種架構(gòu)模式,M表示MOdel,V表示視圖View,C表示控制器Controller:

- Model負(fù)責(zé)存儲(chǔ)、定義、操作數(shù)據(jù);

- View用來(lái)展示書(shū)給用戶,和用戶進(jìn)行操作交互;

- Controller是Model和View的協(xié)調(diào)者,Controller把Model中的數(shù)據(jù)拿過(guò)來(lái)給View用。Controller可以直接與Model和View進(jìn)行通信,而View不能和Controller直接通信。View與Controller通信需要利用代理協(xié)議的方式,當(dāng)有數(shù)據(jù)更新時(shí),Model也要與Controller進(jìn)行通信,這個(gè)時(shí)候就要用Notification和KVO,這個(gè)方式就像一個(gè)廣播一樣,MOdel發(fā)信號(hào),Controller設(shè)置監(jiān)聽(tīng)接受信號(hào),當(dāng)有數(shù)據(jù)更新時(shí)就發(fā)信號(hào)給Controller,Model和View不能直接進(jìn)行通信,這樣會(huì)違背MVC設(shè)計(jì)模式。

26.線程與進(jìn)程的區(qū)別和聯(lián)系?

- 一個(gè)程序至少要有進(jìn)城,一個(gè)進(jìn)程至少要有一個(gè)線程。

- 進(jìn)程:資源分配的最小獨(dú)立單元,進(jìn)程是具有一定獨(dú)立功能的程序關(guān)于某個(gè)數(shù)據(jù)集合上的一次運(yùn)行活動(dòng),進(jìn)程是系統(tǒng)進(jìn)行資源分配和調(diào)度的一個(gè)獨(dú)立單位。

- 線程:進(jìn)程下的一個(gè)分支,是進(jìn)程的實(shí)體,是CPU調(diào)度和分派的基本單元,它是比進(jìn)程更小的能獨(dú)立運(yùn)行的基本單位,線程自己基本不擁有系統(tǒng)資源,只擁有一點(diǎn)在運(yùn)行中必不可少的資源(程序計(jì)數(shù)器、一組寄存器、棧),但是它可與同屬一個(gè)進(jìn)程的其他線程共享進(jìn)程所擁有的全部資源。

- 進(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)程。

http://www.lxweimin.com/p/1a796d0f13f4

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • *面試心聲:其實(shí)這些題本人都沒(méi)怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個(gè)offer,總結(jié)起來(lái)就是把...
    Dove_iOS閱讀 27,209評(píng)論 30 471
  • 之前看了很多面試題,感覺(jué)要不是不夠就是過(guò)于冗余,于是我將網(wǎng)上的一些面試題進(jìn)行了刪減和重排,現(xiàn)在分享給大家。(題...
    Job_Yang閱讀 12,109評(píng)論 12 143
  • 轉(zhuǎn):http://www.cocoachina.com/programmer/20151019/13746.htm...
    Style_偉閱讀 1,331評(píng)論 0 3
  • 注:此文章來(lái)源:Job_Yang 的簡(jiǎn)書(shū) 1. Object-c的類可以多重繼承么?可以實(shí)現(xiàn)多個(gè)接口么?Categ...
    廣益散人閱讀 1,360評(píng)論 0 13
  • 又是排名TOP10 的星期五!每隔一個(gè)星期五,Artprice會(huì)發(fā)布基于主題性的拍賣(mài)排名。本周,ArtLinks會(huì)...
    ArtLinks閱讀 1,074評(píng)論 0 0