ios面試題目

Objective-C是一門動態(tài)的語言

① 什么是動態(tài)語言?

動態(tài)語言,是指程序在運行時可以改變其結(jié)構(gòu):新的函數(shù)可以被引進,已有的函數(shù)可以被刪除等在結(jié)構(gòu)上的變化。比如眾所周知的ECMAScript(JavaScript)便是一個動態(tài)語言。除此之外如Ruby、Python等也都屬于動態(tài)語言,而C、C++等語言則不屬于動態(tài)語言。

有三個名詞容易混淆:DynamicProgrammingLanguage(動態(tài)語言或動態(tài)編程語言)? ? ? ? Dynamically TypedLanguage(動態(tài)類型語言)? ? ? ? Statically TypedLanguage(靜態(tài)類型語言)

所謂的動態(tài)類型語言,意思就是類型的檢查是在運行時做的。

② 靜態(tài)類型

而靜態(tài)類型語言的類型判斷是在運行前判斷(如編譯階段),比如C#、Java就是靜態(tài)類型語言,靜態(tài)類型語言為了達到多態(tài)會采取一些類型鑒別手段,如繼承、接口,而動態(tài)類型語言卻不需要,所以一般動態(tài)語言都會采用dynamic typing,常出現(xiàn)于腳本語言中.需要明確說明一點,那就是,是不是動態(tài)類型語言與這門語言是不是類型安全的完全不相干的,不要將它們聯(lián)系在一起!

優(yōu)缺點:

靜態(tài)類型語言的主要優(yōu)點在于其結(jié)構(gòu)非常規(guī)范,便于調(diào)試,方便類型安全;缺點是為此需要寫更多的類型相關(guān)代碼,導(dǎo)致不便于閱讀、不清晰明了。動態(tài)類型語言的優(yōu)點在于方便閱讀,不需要寫非常多的類型相關(guān)的代碼;缺點自然就是不方便調(diào)試,命名不規(guī)范時會造成讀不懂,不利于理解等。順便說一下,現(xiàn)在有這樣一種趨勢,那就是合并動態(tài)類型與靜態(tài)類型在一種語言中,這樣可以在必要的時候取長補短,Boo就是一個很好的試驗性例子。

③ Objective-C的動態(tài)運行性

Objective-C語言是C語言的一個子類,所以objective-c是一個靜態(tài)語言,但是Objective-C的三大特性之一的多態(tài)性讓其擁有了動態(tài)性。

oc的動態(tài)性讓程序可以在運行時判斷其該有的行為,而不是像c等靜態(tài)語言一樣在編譯構(gòu)建時就確定下來。它的動態(tài)性主要體現(xiàn)在一下三個方面:

動態(tài)類型

如id類型。實際上靜態(tài)類型因為其固定性和可預(yù)知性而使用得更加廣泛。靜態(tài)類型是強類型,而動態(tài)類型屬于弱類型。運行時決定接收者。

這里補充講一下強、弱類型:語言有無類型、強類型和弱類型三種。無類型的不做任何檢查,甚至不區(qū)分指令和數(shù)據(jù);弱類型的檢查很弱,僅能區(qū)分指令和數(shù)據(jù);強類型的嚴(yán)格在編譯期進行檢查。強類型語言在沒有強制類型轉(zhuǎn)化前,不允許兩種不同類型的變量相互操作

動態(tài)綁定

讓代碼在運行時判斷需要調(diào)用什么方法,而不是在編譯時。與其他面向?qū)ο笳Z言一樣,方法調(diào)用和代碼并沒有在編譯時連接在一起,而是在消息發(fā)送時才進行連接。運行時決定調(diào)用哪個方法。

動態(tài)載入

讓程序在運行時添加代碼模塊以及其他資源。用戶可以根據(jù)需要加載一些可執(zhí)行代碼和資源,而不是在啟動時就加載所有組件??蓤?zhí)行代碼中可以含有和程序運行時整合的新類。

對象是運行時類的一個實例。在類里聲明了的實例變量和方法,它的每個實例都在內(nèi)存中擁有同樣的實例變量,以及指向那些方法的指針。在oc中對象永遠是通過指針來引用的。

2.講一下MVC和MVVM,MVP?

MVC,MVP 和 MVVM 的圖示

3.為什么代理要用weak?代理的delegate和dataSource有什么區(qū)別?block和代理的區(qū)別?

代理屬性都用weak或是assign修飾, 現(xiàn)整理下weak(assign)與strong(retain)修飾區(qū)別:

@property (nonatomic, weak) iddelegate;

weak:指明該對象并不負(fù)責(zé)保持delegate這個對象,delegate這個對象的銷毀由外部控制

@property (nonatomic, strong) iddelegate;

strong:該對象強引用delegate,外界不能銷毀delegate對象,會導(dǎo)致循環(huán)引用(Retain MainVC)

Datasource和Delegate兩者的區(qū)別:

Datasource 是在告訴使用者之前的view中都有什么東西,有什么屬性啊,屬性的值都是多少,是只關(guān)于數(shù)據(jù)的東西。

Delegate 是在告訴使用者之前的view有什么方法可以供我調(diào)用。

一個是數(shù)據(jù),一個是操作.

block和代理的區(qū)別:

首先兩者作用是一樣的,都是進行單一回調(diào)。不同的是,delegate是個對象,然后用過一個對象自己調(diào)用代理協(xié)議函數(shù)來完成整個流程。block是傳遞一個函數(shù)指針,利用函數(shù)指針執(zhí)行來進行回調(diào)。還有在內(nèi)存管理上需要注意,delegate不需要保存引用。block對引用數(shù)據(jù)有copy的處理。

4. 屬性的實質(zhì)是什么?包括哪幾個部分?屬性默認(rèn)的關(guān)鍵字都有哪些?@dynamic關(guān)鍵字和@synthesize關(guān)鍵字是用來做什么的?

屬性的組成: @property = ivar + getter + setter;

實例變量+get方法+set方法,也就是說使用@property 系統(tǒng)會自動生成setter和getter方法;

我們經(jīng)常使用assign,weak,strong,copy,nonatomic,atomic,readonly等關(guān)鍵字,下面我們列個表格去歸納一下屬性關(guān)鍵字具體作用:

@synthesize和@dynamic區(qū)別, 在聲明property屬性后,有2種實現(xiàn)選擇:@synthesize編譯器期間,讓編譯器自動生成getter/setter方法。當(dāng)有自定義的存或取方法時,自定義會屏蔽自動生成該方法@dynamic告訴編譯器,不自動生成getter/setter方法,避免編譯期間產(chǎn)生警告,然后由自己實現(xiàn)存取方法?;虼嫒》椒ㄔ谶\行時動態(tài)創(chuàng)建綁定:主要使用在CoreData的實現(xiàn)NSManagedObject子類時使用,由CoreData框架在程序運行的時動態(tài)生成子類屬性

iOS_研究(3)_@property 屬性的本質(zhì)是什么?

5.屬性的默認(rèn)關(guān)鍵字是什么?

對于基本數(shù)據(jù)類型默認(rèn)關(guān)鍵字是atomic,readwrite,assign

對于普通的OC對象atomic,readwrite,strong

6.NSString為什么要用copy關(guān)鍵字,如果用strong會有什么問題?(注意:這里沒有說用strong就一定不行。使用copy和strong是看情況而定的)

怎么用 copy 關(guān)鍵字?

7.如何令自己所寫的對象具有拷貝功能?

如何讓自己的類用 copy 修飾符?如何重寫帶 copy 關(guān)鍵字的 setter?

8.可變集合類 和 不可變集合類的 copy 和 mutablecopy有什么區(qū)別?如果是集合是內(nèi)容復(fù)制的話,集合里面的元素也是內(nèi)容復(fù)制么?

首先我們要先明白一個概念,什么是淺復(fù)制,單層深復(fù)制,完全復(fù)制(每一層都深復(fù)制)

淺復(fù)制也就是所說的指針復(fù)制,并沒有進行對象復(fù)制;

單層深復(fù)制,也就是我們經(jīng)常說的深復(fù)制,我這里說的單層深復(fù)制是對于集合類所說的(即NSArray,NSDictionary,NSSet),單層深復(fù)制指的是只復(fù)制了該集合類的最外層,里邊的元素沒有復(fù)制,(即這兩個集合類的地址不一樣,但是兩個集合里所存儲的元素的地址是一樣的);

完全復(fù)制,指的是完全復(fù)制整個集合類,也就是說兩個集合地址不一樣,里邊所存儲的元素地址也不一樣;

明白了這三個概念之后,我們就來說一下他們的區(qū)別所在:

非集合類(NSString,NSNumber)

[immutableObject copy]//淺復(fù)制[immutableObject mutableCopy]//深復(fù)制[mutableObject copy]//深復(fù)制[mutableObject mutableCopy]//深復(fù)制


結(jié)論:不可變進行copy是淺復(fù)制,mutableCopy是深復(fù)制,可變的copy,mutableCopy都是深復(fù)制

集合類(NSArray,NSDictionary, NSSet):

[immutableObject copy]//淺復(fù)制[immutableObject mutableCopy]//單層深復(fù)制[mutableObject copy]//單層深復(fù)制[mutableObject mutableCopy]//單層深復(fù)制


結(jié)論:不可變進行copy是淺復(fù)制,mutableCopy是單層深復(fù)制,可變的copy,mutableCopy都是單層深復(fù)制

那么如何實現(xiàn)多層復(fù)制呢?

以NSArray舉例說明

NSArray*copyArray = [[NSArrayalloc] initWithArray:array copyItems:YES];// 完全復(fù)制

需要特別注意的是

以上我們所說的兩種情況默認(rèn)都實現(xiàn)了NSCopying和NSMutableCopying協(xié)議

對于自定義繼承自NSObject的類

copy需要實現(xiàn)NSCopying協(xié)議,然后實現(xiàn)以下方法,否則copy會crash

-(id)copyWithZone:(NSZone *)zone {? CopyObject? *copy= [[[selfclass] alloc] init];copy.name =self.name;copy.mobile =self.mobile;copy.company =self.company;copy.descInfo =self.descInfo;returncopy;}mutableCopy時,需要實現(xiàn)NSMutableCopying協(xié)議,否則mutableCopy會crash-(id)mutableCopyWithZone:(NSZone *)zone {? ? ? MutableCopyObject? *mutableCopy = [[[selfclass] alloc] init];? ? ? mutableCopy.name =self.name;? ? ? mutableCopy.mobile =self.mobile;? ? ? mutableCopy.company =self.company;? ? ? mutableCopy.descInfo =self.descInfo;returnmutableCopy;}

9.為什么IBOutlet修飾的UIView也適用weak關(guān)鍵字?

因為當(dāng)我們將控件拖到Storyboard上,相當(dāng)于新創(chuàng)建了一個對象,而這個對象是加到視圖控制器的view上,view有一個subViews屬性,這個屬性是一個數(shù)組,里面是這個view的所有子view,而我們加的控件就位于這個數(shù)組中,那么說明,實際上我們的控件對象是屬于view的,也就是說view對加到它上面的控件是強引用。當(dāng)我們使用Outlet屬性的時候,我們是在viewController里面使用,而這個Outlet屬性是有view來進行強引用的,我們在viewController里面僅僅是對其使用,并沒有必要擁有它,所以是weak的。

如果將weak改為strong,也是沒有問題的,并不會造成強引用循環(huán)。當(dāng)viewController的指針指向其他對象或者為nil,這個viewController銷毀,那么對控件就少了一個強引用指針。然后它的view也隨之銷毀,那么subViews也不存在了,那么控件就又少了一個強引用指針,如果沒有其他強引用,那么這個控件也會隨之銷毀。

不過,既然沒有必將Outlet屬性設(shè)置為strong,那么用weak就好了;一個控件可以在viewController里面有多個Outlet屬性,就相當(dāng)于一個對象,可以有多個指針指向它(多個引用)。但是一個Outlet屬性只能對應(yīng)一個控件,也就是說,如果有button1和button2,button1在viewController里面有一個名為button的Outlet屬性,此時button指向button1,但是如果用button2給button重新賦值,那么此時button指向button2。也就是說,后來的覆蓋原來的。

一個控件可以在viewController里面觸發(fā)多個IBAction。比如有一個button控件,在viewController里面有幾個方法,那么點擊button,會觸發(fā)所有的這些方法。如果我有多個控件,比如button1,button2,button3,它們也可以同時綁定一個buttonClick方法,無論點擊button1,button2還是button3,都會觸發(fā)這個buttonClick方法。

上面說了,button1,button2,button3有可能都觸發(fā)buttonClick方法,如果想在buttonClick方法里面區(qū)分到底是哪個button觸發(fā)的可能有好幾種做法。

可以給這三個button各設(shè)置一個Outlet屬性,然后在buttonClick里面判斷sender和哪個Outlet屬性是同一對象,這樣就可以區(qū)分了。但是很明顯,這樣并不合理,因為創(chuàng)建的三個屬性有些浪費。

我們可以給三個button各加一個tag,在buttonClick里面通過switch(或者if…)判斷,sender的tag和給各個button加上的tag是否一致,如果一致則為同一對象。要慎用tag。因為view有一個viewWithTag:方法,可以在view的子view里面找到和我們傳入的tag相同的view,這樣哪怕不給這個控件創(chuàng)建Outlet屬性,也可以通過tag找到這個對象。但是很明顯,這個方法要遍歷子view,比較每個子view的tag,這樣效率并不高,所以盡量要避免這種情況。

10.nonatomic和atomic的區(qū)別?atomic是絕對的線程安全么?為什么?如果不是,那應(yīng)該如何實現(xiàn)?

在默認(rèn)情況下,由編譯器所合成的方法會通過鎖定機制確保其原子性(atomicity)。如果屬性具備nonatomic特質(zhì),則不需要同步鎖。

下面說一下atomic與nonatomic的區(qū)別:

具備atomic特質(zhì)的獲取方法會通過鎖定機制來確保其操作的原子性。也就是說,如果兩個線程同時讀取一個屬性,那么不論何時,總能看到有效的屬性值。

如果不加鎖的話(或者說使用nonatomic語義),那么當(dāng)其中一個線程正在改寫某屬性值的時候,另外一個線程也許會突然闖入,把尚未修改好的屬性值讀取出來。發(fā)證這種情況時,線程讀取道德屬性值肯能不對。

一般iOS程序中,所有屬性都聲明為nonatomic。這樣做的原因是:

iOS中使用同步鎖的開銷比較大, 這會帶來性能問題。一般情況下并不要求屬性必須是“原子的”,因為這并不能保證“線程安全”(thread safety),若要實現(xiàn)“線程安全”的操作,還需采用更為深層的鎖定機制才行。

例如:一個線程在連續(xù)多次讀取某個屬性值的過程中有別的線程在同時改寫該值,那么即便將屬性聲明為atomic,也還是會讀取到不同的屬性值。因此,ios程序一般都會使用nonatomic屬性。但是在Mac OS X程序時, 使用atomic屬性通常都不會有性能瓶頸;

然而atomic一定是線程安全的么,回答是NO :

nonatomic的內(nèi)存管理語義是非原子性的,非原子性的操作本來就是線程不安全,而atomic的操作是原子性的,但并不意味著他就是線程安全的,它會增加正確的幾率,能夠更好的避免線程錯誤,但仍舊是不安全的。

為了說atomic與nonatomic的本質(zhì)區(qū)別其實也就是在setter方法上的操作不。nonatomic的實現(xiàn):

- (void)setCurrentImage:(UIImage *)currentImage{? ? if (_currentImage != currentImage) {? ? ? ? [_currentImage release];? ? ? ? _currentImage = [currentImage retain];? ? ? ? //dosomething? ? }}- (UIImage *)currentImage{? ? return _currentImage;}? ? ? ? atomic的實現(xiàn):- (void)setCurrentImage:(UIImage *)currentImage{? ? @synchronized(self) {? ? ? ? if (_currentImage != currentImage) {? ? ? ? ? ? [_currentImage release];? ? ? ? ? ? _currentImage = [currentImage retain];? ? ? ? ? ? //dosomething? ? ? ? }? ? }}- (UIImage *)currentImage{? ? @synchronized(self) {? ? ? ? return _currentImage;}}Using the @synchronized DirectiveThe @synchronized directive is a convenient way tocreatemutex locksonthe flyinObjective-C code. The @synchronized directive does whatanyother mutexlockwoulddo—it prevents different threadsfromacquiring the samelockatthe sametime.Inthiscase, however, youdonothavetocreatethe mutexorlockobject directly. Instead, you simply useanyObjective-C objectasalocktoken,asshowninthe following example:


- (void)myMethod:(id)anObj{@synchronized(anObj)? ? {//Everything between the bracesisprotectedbythe@synchronizeddirective.? ? }}

The object passed to the @synchronized directive is a unique identifier used to distinguish the protected block. If you execute the preceding method in two different threads, passing a different object for the anObj parameter on each thread, each would take its lock and continue processing without being blocked by the other. If you pass the same object in both cases, however, one of the threads would acquire the lock first and the other would block until the first thread completed the critical section.

As a precautionary measure, the @synchronized block implicitly adds an exception handler to the protected code. This handler automatically releases the mutex in the event that an exception is thrown. This means that in order to use the @synchronized directive, you must also enable Objective-C exception handling in your code. If you do not want the additional overhead caused by the implicit exception handler, you should consider using the lock classes.

For more information about the @synchronized directive, see The Objective-C Programming Language.

當(dāng)使用atomic時,雖然對屬性的讀和寫是原子性的,但是仍然可能出現(xiàn)線程錯誤:當(dāng)線程A進行寫操作,這時其他線程的讀或者寫操作會因為等該操作而等待。當(dāng)A線程的寫操作結(jié)束后,B線程進行寫操作,所有這些不同線程上的操作都將依次順序執(zhí)行——也就是說,如果一個線程正在執(zhí)行 getter/setter,其他線程就得等待。如果有線程C在A線程讀操作之前release了該屬性,那么還會導(dǎo)致程序崩潰。所以僅僅使用atomic并不會使得線程安全,我們還要為線程添加lock來確保線程的安全。

更準(zhǔn)確的說應(yīng)該是讀寫安全,但并不是線程安全的,因為別的線程還能進行讀寫之外的其他操作。線程安全需要開發(fā)者自己來保證。

其實無論是否是原子性的只是針對于getter和setter而言,比如用atomic去操作一個NSMutableArray ,如果一個線程循環(huán)讀數(shù)據(jù),一個線程循環(huán)寫數(shù)據(jù),肯定會產(chǎn)生內(nèi)存問題,這個就跟getter和setter就木有關(guān)系了。

11.UICollectionView自定義layout如何實現(xiàn)?

關(guān)于自定義UICollectionViewLayout的一點個人理解

12.用StoryBoard開發(fā)界面有什么弊端?如何避免?

難以維護

Storyboard在某些角度上,是難以維護的。我所遇到過的實際情況是,公司一個項目的2.0版本,設(shè)計師希望替換原有字體。然而原來項目的每一個Label都是采用Storyboard來定義字體的,因此替換新字體需要在Storyboard中更改每一個Label。

幸虧我們知道Storyboard的源文件是XML,最終寫了一個讀取-解析-替換腳本來搞定這件事。

性能瓶頸

當(dāng)項目達到一定的規(guī)模,即使是高性能的MacBook Pro,在打開Storyboard是也會有3-5秒的讀取時間。無論是只有幾個Scene的小東西,還是幾十個Scene的龐然大物,都無法避免。Scene越多的文件,打開速度越慢(從另一個方面說明了分割大故事板的重要性)。

讓人沮喪的是,這個造成卡頓的項目規(guī)模并不是太難達到。

我猜想是由于每一次打開都需要進行I/O操作造成的,Apple對這一塊的緩存優(yōu)化沒有做到位。可能是由于Storyboard占用了太多內(nèi)存,難以在內(nèi)存中進行緩存。Whatever,這個問題總是讓人困擾的。

然而需要指出的是,采用Storyboard開發(fā)或采用純代碼開發(fā)的App,在真機的運行效率上,并沒有太大的區(qū)別。

錯誤定位困難

Storyboard的初學(xué)者應(yīng)該對此深有體會。排除BAD_EXCUSE錯誤不說,單單是有提示的錯誤,就足以讓人在代碼和Storyboard之間來回摸索,卻無法找到解決方案。

一個典型的例子是,在代碼中刪除了IBOUTLET屬性或者IBAction方法,但是卻忘了在Storyboard中刪除對應(yīng)的連接,運行后crash。然而控制臺只會輸出一些模糊其詞的錯誤描述。

*** Terminating app duetouncaught exception'NSUnknownKeyException',reason:'[ setValue:forUndefinedKey:]:thisclassisnotkeyvalue coding-compliantforthekeydrawButton.'


最后一方面是其提供的便利,另一方面是Apple對Storyboard的大力支持。這一點宏觀上看,可以在以往對Storyboard的改進和增強上看出,微觀上看,幾乎所有iOS 8之后的simple code都或多或少采用了Storyboard作為界面開發(fā)工具;

那改如何避免這些弊端呢, 參考以下文章:

iOS項目開發(fā)實戰(zhàn)——storyboard設(shè)置界面技巧與注意事項

13.進程和線程的區(qū)別?同步異步的區(qū)別?并行和并發(fā)的區(qū)別?

進程和線程:

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

同步和異步:

在進行網(wǎng)絡(luò)編程時,我們通常會看到同步、異步、阻塞、非阻塞四種調(diào)用方式以及他們的組合。

其中同步方式、異步方式主要是由客戶端(client)控制的,具體如下:

同步(Sync)

所謂同步,就是發(fā)出一個功能調(diào)用時,在沒有得到結(jié)果之前,該調(diào)用就不返回或繼續(xù)執(zhí)行后續(xù)操作。

根據(jù)這個定義,Java中所有方法都是同步調(diào)用,應(yīng)為必須要等到結(jié)果后才會繼續(xù)執(zhí)行。我們在說同步、異步的時候,一般而言是特指那些需要其他端協(xié)作或者需要一定時間完成的任務(wù)。

簡單來說,同步就是必須一件一件事做,等前一件做完了才能做下一件事。

例如:B/S模式中的表單提交,具體過程是:客戶端提交請求->等待服務(wù)器處理->處理完畢返回,在這個過程中客戶端瀏覽器不能做其他事。

異步(Async)

異步與同步相對,當(dāng)一個異步過程調(diào)用發(fā)出后,調(diào)用者在沒有得到結(jié)果之前,就可以繼續(xù)執(zhí)行后續(xù)操作。當(dāng)這個調(diào)用完成后,一般通過狀態(tài)、通知和回調(diào)來通知調(diào)用者。對于異步調(diào)用,調(diào)用的返回并不受調(diào)用者控制。

總結(jié)來說,同步和異步的區(qū)別:請求發(fā)出后,是否需要等待結(jié)果,才能繼續(xù)執(zhí)行其他操作。

并行(parallellism)和并發(fā)(concurrency)的區(qū)別:

并行是指兩個或者多個事件在同一時刻發(fā)生;而并發(fā)是指兩個或多個事件在同一時間間隔發(fā)生。

并行,是每個cpu運行一個程序;

并發(fā),是在同一個cpu上同時(不是真正的同時,而是看來是同時,因為cpu要在多個程序間切換)運行多個程序;

并發(fā)和并行的區(qū)別

14.線程間通信?

使用全局變量主要由于多個線程可能更改全局變量,因此全局變量最好聲明為violate

使用消息實現(xiàn)通信在Windows程序設(shè)計中,每一個線程都可以擁有自己的消息隊列(UI線程默認(rèn)自帶消息隊列和消息循環(huán),工作線程需要手動實現(xiàn)消息循環(huán)),因此可以采用消息進行線程間通信sendMessage,postMessage。

1)定義消息#defineWM_THREAD_SENDMSG=WM_USER+20;2)添加消息函數(shù)聲明afx_msgintOnTSendmsg();3)添加消息映射ON_MESSAGE(WM_THREAD_SENDMSG,OnTSM)4)添加OnTSM()的實現(xiàn)函數(shù);5)在線程函數(shù)中添加PostMessage消息Post函數(shù)

使用事件CEvent類實現(xiàn)線程間通信

Event對象有兩種狀態(tài):有信號和無信號,線程可以監(jiān)視處于有信號狀態(tài)的事件,以便在適當(dāng)?shù)臅r候執(zhí)行對事件的操作。

1)創(chuàng)建一個CEvent類的對象:CEvent threadStart;它默認(rèn)處在未通信狀態(tài);2)threadStart.SetEvent();使其處于通信狀態(tài);3)調(diào)用WaitForSingleObject()來監(jiān)視CEvent對象

線程間的通信、同步方式與進程間通信方式

15.GCD的一些常用的函數(shù)?(group,barrier,信號量,線程同步)

dispatch_groupdispatch_barrierdispatch_semaphore(信號量)附:iOSGCD線程同步方法

16.如何使用隊列來避免資源搶奪?

ios多線程——鎖(解決多線程搶奪同一塊資源的問題)

17.數(shù)據(jù)持久化的幾個方案(fmdb用沒用過)

plist文件(屬性列表)

preference(偏好設(shè)置)

NSKeyedArchiver(歸檔)

SQLite 3

CoreData

iOS中幾種數(shù)據(jù)持久化方案

18.說一下AppDelegate的幾個方法?從后臺到前臺調(diào)用了哪些方法?第一次啟動調(diào)用了哪些方法?從前臺到后臺調(diào)用了哪些方法?

1. – (BOOL)application:(UIApplication)application didFinishLaunchingWithOptions:(NSDictionary)launchOptions NS_AVAILABLE_IOS(3_0);

當(dāng)應(yīng)用程序啟動時(不包括已在后臺的情況下轉(zhuǎn)到前臺),調(diào)用此回調(diào)。launchOptions是啟動參數(shù),假如用戶通過點擊push通知啟動的應(yīng)用,這個參數(shù)里會存儲一些push通知的信息。

2. – (void)applicationDidBecomeActive:(UIApplication *)application;

// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.

當(dāng)應(yīng)用程序全新啟動,或者在后臺轉(zhuǎn)到前臺,完全激活時,都會調(diào)用這個方法。如果應(yīng)用程序是以前運行在后臺,這時可以選擇刷新用戶界面。

3. – (void)applicationDidEnterBackground:(UIApplication *)application NS_AVAILABLE_IOS(4_0);

// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.

// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.

當(dāng)用戶從前臺狀態(tài)轉(zhuǎn)入后臺時,調(diào)用此方法。使用此方法來釋放資源共享,保存用戶數(shù)據(jù),無效計時器,并儲存足夠的應(yīng)用程序狀態(tài)信息的情況下被終止后,將應(yīng)用 程序恢復(fù)到目前的狀態(tài)。如果您的應(yīng)用程序支持后臺運行,這種方法被調(diào)用,否則調(diào)用applicationWillTerminate:用戶退出。

4. – (void)applicationWillEnterForeground:(UIApplication *)application NS_AVAILABLE_IOS(4_0);

// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.

當(dāng)應(yīng)用在后臺狀態(tài),將要進行動前臺運行狀態(tài)時,會調(diào)用此方法。

如果應(yīng)用不在后臺狀態(tài),而是直接啟動,則不會回調(diào)此方法。

從后臺到前臺2, 4; 第一次啟動1, 2; 從前臺到后臺3;

iOS APP啟動時所有方法的調(diào)用順序分析

19.NSCache優(yōu)于NSDictionary的幾點?

NSCache勝過NSDictionary之處在于,當(dāng)系統(tǒng)資源將要耗盡時,它可以自動刪減緩存。如果采用普通的字典,那么就要自己編寫掛鉤,在系統(tǒng)發(fā)出“低內(nèi)存”通知時手工刪減緩存。

NSCache并不會“拷貝”鍵,而是會“保留”它。此行為用NSDictionary也可以實現(xiàn),然而需要編寫相當(dāng)復(fù)雜的代碼。NSCache對象不拷貝鍵的原因在于:很多時候,鍵都是不支持拷貝操作的對象來充當(dāng)?shù)?。因此,NSCache不會自動拷貝鍵,所以說,在鍵不支持拷貝操作的情況下,該類用起來比字典更方便。另外,NSCache是線程安全的,而NSDictionary則絕對不具備此優(yōu)勢。

20.知不知道Designated Initializer?使用它的時候有什么需要注意的問題?

iOS: 聊聊 Designated Initializer(指定初始化函數(shù))

正確編寫Designated Initializer的幾個原則

21.實現(xiàn)description方法能取到什么效果?

一般情況下,我們在使用NSLog 和 %@ 輸出某個對象時,就會調(diào)用這個對象的 description 方法,它的返回值就是 NSString 字符串類型,所以 description 默認(rèn)實現(xiàn)返回的格式是 <類名: 對象的內(nèi)存地址>

如圖:

以上輸出實現(xiàn)的具體步驟為:

①調(diào)用對象p的-description方法②拿到-description方法的返回值(NSString*)顯示到屏幕上③-description方法默認(rèn)返回的是“類名+內(nèi)存地址”

那么,既然description方法的默認(rèn)實現(xiàn)是返回類名和對象的內(nèi)存地址,所以在必要情況下,我們需要重寫description方法以達到改變輸出結(jié)果目的,覆蓋description方法的默認(rèn)實現(xiàn),比如重寫上述代碼 Person 類的 description方法,返回_age和_name成員變量的值:

重寫完description方法后,再調(diào)用NSLog(@”%@”,p)時輸出結(jié)果不再是<類名: 內(nèi)存地址>,而是返回的字符串:

22.objc使用什么機制管理對象內(nèi)存?

MRC(manual retain-release)手動內(nèi)存管理

ARC(automatic reference counting)自動引用計數(shù)

Garbage collection (垃圾回收)。但是iOS不支持垃圾回收, ARC作為LLVM3.0編譯器的一項特性, 在iOS5.0 (Xcode4) 版本后推出的。

ARC的判斷準(zhǔn)則, 只要沒有強指針指向?qū)ο? 對象就會被釋放.

iOS開發(fā)系列—Objective-C之內(nèi)存管理

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

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