2017年5月iOS面試題答案總結(轉)

技術

最近正在準備換份工作, 看到網上有份題庫, 覺得不錯, 準備整理下, 複習下所學知識, 爲面試做足準備, 下面是我整理了一上午的題庫答案, 希望能幫大家溫習下知識; 當然如果同爲找工作的朋友, 也希望你能找到份誠心的工作;之後的答案已附下方, 謝謝大家(^__^) 嘻嘻……

基礎

1. 爲什麼說Objective-C是一門動態的語言?
① 什麼是動態語言?
動態語言,是指程序在運行時可以改變其結構:新的函數可以被引進,已有的函數可以被刪除等在結構上的變化。比如衆所周知的ECMAScript(JavaScript)便是一個動態語言。除此之外如Ruby、Python等也都屬於動態語言,而C、C++等語言則不屬於動態語言。
有三個名詞容易混淆:
Dynamic Programming Language (動態語言或動態編程語言)
Dynamically Typed Language (動態類型語言)
Statically Typed Language (靜態類型語言)
所謂的動態類型語言,意思就是類型的檢查是在運行時做的。
② 靜態類型
而靜態類型語言的類型判斷是在運行前判斷(如編譯階段),比如C#、Java就是靜態類型語言,靜態類型語言爲了達到多態會採取一些類型鑑別手段,如繼承、接口,而動態類型語言卻不需要,所以一般動態語言都會採用dynamic typing,常出現於腳本語言中.需要明確說明一點,那就是,是不是動態類型語言與這門語言是不是類型安全的完全不相干的,不要將它們聯繫在一起!
優缺點:
靜態類型語言的主要優點在於其結構非常規範,便於調試,方便類型安全;缺點是爲此需要寫更多的類型相關代碼,導致不便於閱讀、不清晰明瞭。動態類型語言的優點在於方便閱讀,不需要寫非常多的類型相關的代碼;缺點自然就是不方便調試,命名不規範時會造成讀不懂,不利於理解等。順便說一下,現在有這樣一種趨勢,那就是合併動態類型與靜態類型在一種語言中,這樣可以在必要的時候取長補短,Boo就是一個很好的試驗性例子。
Objective-C的動態運行性
objective-c語言是C語言的一個子類,所以objective-c是一個靜態語言,但是Objective-C的三大特性之一的多態性讓其擁有了動態性。
oc的動態性讓程序可以在運行時判斷其該有的行爲,而不是像c等靜態語言一樣在編譯構建時就確定下來。它的動態性主要體現在一下三個方面:
* 動態類型 * 如id類型。實際上靜態類型因爲其固定性和可預知性而使用得更加廣泛。靜態類型是強類型,而動態類型屬於弱類型。運行時決定接收者。
這裏補充講一下強、弱類型:語言有無類型、強類型和弱類型三種。無類型的不做任何檢查,甚至不區分指令和數據;弱類型的檢查很弱,僅能區分指令和數據;強類型的嚴格在編譯期進行檢查。強類型語言在沒有強制類型轉化前,不允許兩種不同類型的變量相互操作
* 動態綁定 * 讓代碼在運行時判斷需要調用什麼方法,而不是在編譯時。與其他面嚮對象語言一樣,方法調用和代碼並沒有在編譯時連接在一起,而是在消息發送時才進行連接。運行時決定調用哪個方法。
* 動態載入 * 讓程序在運行時添加代碼模塊以及其他資源。用戶可以根據需要加載一些可執行代碼和資源,而不是在啓動時就加載所有組件。可執行代碼中可以含有和程序運行時整合的新類。
對象是運行時類的一個實例。在類裏聲明瞭的實例變量和方法,它的每個實例都在內存中擁有同樣的實例變量,以及指向那些方法的指針。在oc中對象永遠是通過指針來引用的。

2.講一下MVC和MVVM,MVP?
MVC,MVP 和 MVVM 的圖示

3.爲什麼代理要用weak?代理的delegate和dataSource有什麼區別?block和代理的區別?
代理屬性都用weak或是assign修飾, 現整理下weak(assign)與strong(retain)修飾區別:

@property (nonatomic, weak) id<MainVCDelegate>delegate;
  • 1
  • 1

weak:指明該對象並不負責保持delegate這個對象,delegate這個對象的銷燬由外部控制

@property (nonatomic, strong) id<MainVCDelegate>delegate;
  • 1
  • 1

strong:該對象強引用delegate,外界不能銷燬delegate對象,會導致循環引用(Retain MainVC)

Datasource和Delegate兩者的區別:
Datasource 是在告訴使用者之前的view中都有什麼東西,有什麼屬性啊,屬性的值都是多少,是隻關於數據的東西。
Delegate 是在告訴使用者之前的view有什麼方法可以供我調用。
一個是數據,一個是操作.

block和代理的區別:
首先兩者作用是一樣的,都是進行單一回調。不同的是,delegate是個對象,然後用過一個對象自己調用代理協議函數來完成整個流程。block是傳遞一個函數指針,利用函數指針執行來進行回調。還有在內存管理上需要注意,delegate不需要保存引用。block對引用數據有copy的處理。

3. 屬性的實質是什麼?包括哪幾個部分?屬性默認的關鍵字都有哪些?@dynamic關鍵字和@synthesize關鍵字是用來做什麼的?
屬性的組成: @property = ivar + getter + setter;
實例變量+get方法+set方法,也就是說使用@property 系統會自動生成setter和getter方法;

我們經常使用assign,weak,strong,copy,nonatomic,atomic,readonly等關鍵字,下面我們列個表格去歸納一下屬性關鍵字具體作用:
屬性關鍵字具體作用.png

@synthesize和@dynamic區別, 在聲明property屬性後,有2種實現選擇:
@synthesize
編譯器期間,讓編譯器自動生成getter/setter方法。
當有自定義的存或取方法時,自定義會屏蔽自動生成該方法
@dynamic
告訴編譯器,不自動生成getter/setter方法,避免編譯期間產生警告
然後由自己實現存取方法
或存取方法在運行時動態創建綁定:主要使用在CoreData的實現NSManagedObject子類時使用,由Core Data框架在程序運行的時動態生成子類屬性
iOS_研究(3)_@property 屬性的本質是什麼?

5.屬性的默認關鍵字是什麼?
對於基本數據類型默認關鍵字是
atomic,readwrite,assign
對於普通的OC對象
atomic,readwrite,strong

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

7.如何令自己所寫的對象具有拷貝功能?
如何讓自己的類用 copy 修飾符?如何重寫帶 copy 關鍵字的 setter?

8.可變集合類 和 不可變集合類的 copy 和 mutablecopy有什麼區別?如果是集合是內容複製的話,集合裏面的元素也是內容複製麼?
首先我們要先明白一個概念,什麼是淺複製,單層深複製,完全複製(每一層都深複製)
淺複製也就是所說的指針複製,並沒有進行對象複製;
單層深複製,也就是我們經常說的深複製,我這裏說的單層深複製是對於集合類所說的(即NSArray,NSDictionary,NSSet),單層深複製指的是隻複製了該集合類的最外層,裏邊的元素沒有複製,(即這兩個集合類的地址不一樣,但是兩個集合裏所存儲的元素的地址是一樣的);
完全複製,指的是完全複製整個集合類,也就是說兩個集合地址不一樣,裏邊所存儲的元素地址也不一樣;
明白了這三個概念之後,我們就來說一下他們的區別所在:
- 非集合類(NSString,NSNumber)

[immutableObject copy]  //淺複製  
[immutableObject mutableCopy] //深複製
[mutableObject copy] //深複製
[mutableObject mutableCopy] //深複製
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

結論:不可變進行copy是淺複製,mutableCopy是深複製,可變的copy,mutableCopy都是深複製
- 集合類(NSArray,NSDictionary, NSSet):

[immutableObject copy]  //淺複製
[immutableObject mutableCopy] //單層深複製
[mutableObject copy] //單層深複製
[mutableObject mutableCopy] //單層深複製
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

結論:不可變進行copy是淺複製,mutableCopy是單層深複製,可變的copy,mutableCopy都是單層深複製
那麼如何實現多層複制呢?
以NSArray舉例說明

 NSArray *copyArray = [[NSArray alloc] initWithArray:array copyItems:YES];  // 完全複製
  • 1
  • 1

需要特別注意的是
以上我們所說的兩種情況默認都實現了NSCopying和NSMutableCopying協議
對於自定義繼承自NSObject的類
- copy需要實現NSCopying協議,然後實現以下方法,否則copy會crash

-(id)copyWithZone:(NSZone *)zone {
      CopyObject  *copy = [[[self class] alloc] init];
      copy.name = self.name;
      copy.mobile = self.mobile;
      copy.company = self.company;
      copy.descInfo = self.descInfo;
      return copy;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • mutableCopy時,需要實現NSMutableCopying協議,否則mutableCopy會crash
-(id)mutableCopyWithZone:(NSZone *)zone {
      MutableCopyObject  *mutableCopy = [[[self class] alloc] init];
      mutableCopy.name = self.name;
      mutableCopy.mobile = self.mobile;
      mutableCopy.company = self.company;
      mutableCopy.descInfo = self.descInfo;
      return mutableCopy;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

9.爲什麼IBOutlet修飾的UIView也適用weak關鍵字?
因爲當我們將控件拖到Storyboard上,相當於新創建了一個對象,而這個對象是加到視圖控制器的view上,view有一個subViews屬性,這個屬性是一個數組,裏面是這個view的所有子view,而我們加的控件就位於這個數組中,那麼說明,實際上我們的控件對象是屬於view的,也就是說view對加到它上面的控件是強引用。當我們使用Outlet屬性的時候,我們是在viewController裏面使用,而這個Outlet屬性是有view來進行強引用的,我們在viewController裏面僅僅是對其使用,並沒有必要擁有它,所以是weak的。

如果將weak改爲strong,也是沒有問題的,並不會造成強引用循環。當viewController的指針指向其他對象或者爲nil,這個viewController銷燬,那麼對控件就少了一個強引用指針。然後它的view也隨之銷燬,那麼subViews也不存在了,那麼控件就又少了一個強引用指針,如果沒有其他強引用,那麼這個控件也會隨之銷燬。

不過,既然沒有必將Outlet屬性設置爲strong,那麼用weak就好了;

一個控件可以在viewController裏面有多個Outlet屬性,就相當於一個對象,可以有多個指針指向它(多個引用)。

但是一個Outlet屬性只能對應一個控件,也就是說,如果有button1和button2,button1在viewController裏面有一個名爲button的Outlet屬性,此時button指向button1,但是如果用button2給button重新賦值,那麼此時button指向button2。也就是說,後來的覆蓋原來的。

一個控件可以在viewController裏面觸發多個IBAction。比如有一個button控件,在viewController裏面有幾個方法,那麼點擊button,會觸發所有的這些方法。

如果我有多個控件,比如button1,button2,button3,它們也可以同時綁定一個buttonClick方法,無論點擊button1,button2還是button3,都會觸發這個buttonClick方法。

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

可以給這三個button各設置一個Outlet屬性,然後在buttonClick裏面判斷sender和哪個Outlet屬性是同一對象,這樣就可以區分了。但是很明顯,這樣並不合理,因爲創建的三個屬性有些浪費。
我們可以給三個button各加一個tag,在buttonClick裏面通過switch(或者if…)判斷,sender的tag和給各個button加上的tag是否一致,如果一致則爲同一對象。
要慎用tag。因爲view有一個viewWithTag:方法,可以在view的子view裏面找到和我們傳入的tag相同的view,這樣哪怕不給這個控件創建Outlet屬性,也可以通過tag找到這個對象。但是很明顯,這個方法要遍歷子view,比較每個子view的tag,這樣效率並不高,所以儘量要避免這種情況。

10.nonatomic和atomic的區別?atomic是絕對的線程安全麼?爲什麼?如果不是,那應該如何實現?
在默認情況下,由編譯器所合成的方法會通過鎖定機制確保其原子性(atomicity)。如果屬性具備nonatomic特質,則不需要同步鎖。

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

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

一般iOS程序中,所有屬性都聲明爲nonatomic。這樣做的原因是:
ios中使用同步鎖的開銷比較大, 這會帶來性能問題。一般情況下並不要求屬性必須是“原子的”,因爲這並不能保證“線程安全”(thread safety),若要實現“線程安全”的操作,還需採用更爲深層的鎖定機制才行。

例如:一個線程在連續多次讀取某個屬性值的過程中有別的線程在同時改寫該值,那麼即便將屬性聲明爲atomic,也還是會讀取到不同的屬性值。

因此,iOS程序一般都會使用nonatomic屬性。但是在Mac OS X程序時, 使用atomic屬性通常都不會有性能瓶頸;

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

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

爲了說atomic與nonatomic的本質區別其實也就是在setter方法上的操作不同:

nonatomic的實現:

- (void)setCurrentImage:(UIImage *)currentImage
{
    if (_currentImage != currentImage) {
        [_currentImage release];
        _currentImage = [currentImage retain];

        // do something
    }
}

- (UIImage *)currentImage
{
    return _currentImage;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

atomic的實現:

- (void)setCurrentImage:(UIImage *)currentImage
{
    @synchronized(self) {
        if (_currentImage != currentImage) {
            [_currentImage release];
            _currentImage = [currentImage retain];

            // do something
        }
    }
}

- (UIImage *)currentImage
{
    @synchronized(self) {
        return _currentImage;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

Using the @synchronized Directive
The @synchronized directive is a convenient way to create mutex locks on the fly in Objective-C code. The @synchronized directive does what any other mutex lock would do—it prevents different threads from acquiring the same lock at the same time. In this case, however, you do not have to create the mutex or lock object directly. Instead, you simply use any Objective-C object as a lock token, as shown in the following example:

- (void)myMethod:(id)anObj
{
    @synchronized(anObj)
    {
        // Everything between the braces is protected by the @synchronized directive.
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

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.

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

更準確的說應該是讀寫安全,但並不是線程安全的,因爲別的線程還能進行讀寫之外的其他操作。線程安全需要開發者自己來保證。

其實無論是否是原子性的只是針對於getter和setter而言,比如用atomic去操作一個NSMutableArray ,如果一個線程循環讀數據,一個線程循環寫數據,肯定會產生內存問題,這個就跟getter和setter就木有關係了。

11.UICollectionView自定義layout如何實現?
關於自定義UICollectionViewLayout的一點個人理解

12.用StoryBoard開發界面有什麼弊端?如何避免?
- 難以維護
Storyboard在某些角度上,是難以維護的。我所遇到過的實際情況是,公司一個項目的2.0版本,設計師希望替換原有字體。然而原來項目的每一個Label都是採用Storyboard來定義字體的,因此替換新字體需要在Storyboard中更改每一個Label。
幸虧我們知道Storyboard的源文件是XML,最終寫了一個讀取-解析-替換腳本來搞定這件事。

  • 性能瓶頸
    當項目達到一定的規模,即使是高性能的MacBook Pro,在打開Storyboard是也會有3-5秒的讀取時間。無論是隻有幾個Scene的小東西,還是幾十個Scene的龐然大物,都無法避免。Scene越多的文件,打開速度越慢(從另一個方面說明了分割大故事板的重要性)。
    讓人沮喪的是,這個造成卡頓的項目規模並不是太難達到。
    我猜想是由於每一次打開都需要進行I/O操作造成的,Apple對這一塊的緩存優化沒有做到位。可能是由於Storyboard佔用了太多內存,難以在內存中進行緩存。Whatever,這個問題總是讓人困擾的。
    然而需要指出的是,採用Storyboard開發或採用純代碼開發的App,在真機的運行效率上,並沒有太大的區別。

  • 錯誤定位困難
    Storyboard的初學者應該對此深有體會。排除BAD_EXCUSE錯誤不說,單單是有提示的錯誤,就足以讓人在代碼和Storyboard之間來回摸索,卻無法找到解決方案。
    一個典型的例子是,在代碼中刪除了IBOUTLET屬性或者IBAction方法,但是卻忘了在Storyboard中刪除對應的連接,運行後crash。然而控制檯只會輸出一些模糊其詞的錯誤描述。

*** Terminating app due to uncaught exception 'NSUnknownKeyException', 
reason: '[ setValue:forUndefinedKey:]:  
this class is not key value coding-compliant for the key drawButton.'
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

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

那改如何避免這些弊端呢, 參考以下文章:
iOS項目開發實戰——storyboard設置界面技巧與注意事項

13.進程和線程的區別?同步異步的區別?並行和併發的區別?
進程和線程:
進程中所包含的一個或多個執行單元稱爲線程(thread)。比如一個應用程序就是一個進程, 而它又包含了多個線程;主要差別在於它們是不同的操作系統資源管理方式。進程有獨立的地址空間,一個進程崩潰後,在保護模式下不會對其它進程產生影響,而線程只是一個進程中的不同執行路徑。線程有自己的堆棧和局部變量,但線程之間沒有單獨的地址空間,一個線程死掉就等於整個進程死掉,所以多進程的程序要比多線程的程序健壯,但在進程切換時,耗費資源較大,效率要差一些。但對於一些要求同時進行並且又要共享某些變量的併發操作,只能用線程,不能用進程;

同步和異步:
在進行網絡編程時,我們通常會看到同步、異步、阻塞、非阻塞四種調用方式以及他們的組合。
其中同步方式、異步方式主要是由客戶端(client)控制的,具體如下:
同步(Sync)
所謂同步,就是發出一個功能調用時,在沒有得到結果之前,該調用就不返回或繼續執行後續操作。
根據這個定義,Java中所有方法都是同步調用,應爲必須要等到結果後纔會繼續執行。我們在說同步、異步的時候,一般而言是特指那些需要其他端協作或者需要一定時間完成的任務。
簡單來說,同步就是必須一件一件事做,等前一件做完了才能做下一件事。
例如:B/S模式中的表單提交,具體過程是:客戶端提交請求->等待服務器處理->處理完畢返回,在這個過程中客戶端瀏覽器不能做其他事。
異步(Async)
異步與同步相對,當一個異步過程調用發出後,調用者在沒有得到結果之前,就可以繼續執行後續操作。當這個調用完成後,一般通過狀態、通知和回調來通知調用者。對於異步調用,調用的返回並不受調用者控制。
總結來說,同步和異步的區別:請求發出後,是否需要等待結果,才能繼續執行其他操作。

並行(parallellism)和併發(concurrency)的區別:
並行是指兩個或者多個事件在同一時刻發生;而併發是指兩個或多個事件在同一時間間隔發生。
並行圖解.jpg
並行,是每個cpu運行一個程序;
併發圖解.jpg
併發,是在同一個cpu上同時(不是真正的同時,而是看來是同時,因爲cpu要在多個程序間切換)運行多個程序;
併發和並行的區別

14.線程間通信?
- 使用全局變量主要由於多個線程可能更改全局變量,因此全局變量最好聲明爲violate
- 使用消息實現通信在Windows程序設計中,每一個線程都可以擁有自己的消息隊列(UI線程默認自帶消息隊列和消息循環,工作線程需要手動實現消息循環),因此可以採用消息進行線程間通信sendMessage,postMessage。

1)定義消息#define WM_THREAD_SENDMSG=WM_USER+20;  
2)添加消息函數聲明afx_msg int OnTSendmsg(); 
3)添加消息映射ON_MESSAGE(WM_THREAD_SENDMSG,OnTSM) 
4)添加OnTSM()的實現函數;
5)在線程函數中添加PostMessage消息Post函數
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5
  • 使用事件CEvent類實現線程間通信
    Event對象有兩種狀態:有信號和無信號,線程可以監視處於有信號狀態的事件,以便在適當的時候執行對事件的操作。
1)創建一個CEvent類的對象:CEvent threadStart;它默認處在未通信狀態; 
2)threadStart.SetEvent();使其處於通信狀態; 
3)調用WaitForSingleObject()來監視CEvent對象
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

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

15.GCD的一些常用的函數?(group,barrier,信號量,線程同步)
- dispatch_group
- dispatch_barrier
- dispatch_semaphore(信號量)
附:
iOS GCD 線程同步方法

16.如何使用隊列來避免資源搶奪?
ios多線程——鎖(解決多線程搶奪同一塊資源的問題)

17.數據持久化的幾個方案(fmdb用沒用過)
- plist文件(屬性列表)
- preference(偏好設置)
- NSKeyedArchiver(歸檔)
- SQLite 3
- CoreData
iOS中幾種數據持久化方案

18.說一下AppDelegate的幾個方法?從後臺到前臺調用了哪些方法?第一次啓動調用了哪些方法?從前臺到後臺調用了哪些方法?

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

當應用程序啓動時(不包括已在後臺的情況下轉到前臺),調用此回調。launchOptions是啓動參數,假如用戶通過點擊push通知啓動的應用,這個參數裏會存儲一些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.
  • 1
  • 2
  • 1
  • 2

當應用程序全新啓動,或者在後臺轉到前臺,完全激活時,都會調用這個方法。如果應用程序是以前運行在後臺,這時可以選擇刷新用戶界面。

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.
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

當用戶從前臺狀態轉入後臺時,調用此方法。使用此方法來釋放資源共享,保存用戶數據,無效計時器,並儲存足夠的應用程序狀態信息的情況下被終止後,將應用 程序恢復到目前的狀態。如果您的應用程序支持後臺運行,這種方法被調用,否則調用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.
  • 1
  • 2
  • 1
  • 2

當應用在後臺狀態,將要進行動前臺運行狀態時,會調用此方法。
如果應用不在後臺狀態,而是直接啓動,則不會回調此方法。
從後臺到前臺2, 4; 第一次啓動1, 2; 從前臺到後臺3;

iOS APP啓動時所有方法的調用順序分析

19.NSCache優於NSDictionary的幾點?
NSCache勝過NSDictionary之處在於,當系統資源將要耗盡時,它可以自動刪減緩存。如果採用普通的字典,那麼就要自己編寫掛鉤,在系統發出“低內存”通知時手工刪減緩存。

NSCache並不會“拷貝”鍵,而是會“保留”它。此行爲用NSDictionary也可以實現,然而需要編寫相當複雜的代碼。NSCache對象不拷貝鍵的原因在於:很多時候,鍵都是不支持拷貝操作的對象來充當的。因此,NSCache不會自動拷貝鍵,所以說,在鍵不支持拷貝操作的情況下,該類用起來比字典更方便。另外,NSCache是線程安全的,而NSDictionary則絕對不具備此優勢。

20.知不知道Designated Initializer?使用它的時候有什麼需要注意的問題?
iOS: 聊聊 Designated Initializer(指定初始化函數)
正確編寫Designated Initializer的幾個原則

21.實現description方法能取到什麼效果?
一般情況下,我們在使用NSLog 和 %@ 輸出某個對象時,就會調用這個對象的 description 方法,它的返回值就是 NSString 字符串類型,所以 description 默認實現返回的格式是 <類名: 對象的內存地址>
如圖:
默認description輸出.png
以上輸出實現的具體步驟爲:
①調用對象p的-description方法
②拿到-description方法的返回值(NSString*)顯示到屏幕上
③-description方法默認返回的是“類名+內存地址”

那麼,既然description方法的默認實現是返回類名和對象的內存地址,所以在必要情況下,我們需要重寫description方法以達到改變輸出結果目的,覆蓋description方法的默認實現,比如重寫上述代碼 Person 類的 description方法,返回_age和_name成員變量的值:
重寫description.png
重寫完description方法後,再調用NSLog(@”%@”,p)時輸出結果不再是<類名: 內存地址>,而是返回的字符串:
重寫description方法後輸出.png

22.objc使用什麼機制管理對象內存?
- MRC(manual retain-release)手動內存管理
- ARC(automatic reference counting)自動引用計數
- Garbage collection (垃圾回收)。但是iOS不支持垃圾回收, ARC作爲LLVM3.0編譯器的一項特性, 在iOS5.0 (Xcode4) 版本後推出的。
- ARC的判斷準則, 只要沒有強指針指向對象, 對象就會被釋放.
iOS開發系列—Objective-C之內存管理

附:
2017年5月iOS招人心得答案總結(基礎篇)
2017年5月iOS招人心得答案總結(中級篇)
2017年5月iOS招人心得答案總結(高級篇)

題庫:
2017年5月iOS招人心得(附面試題)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章