IOS 設計 面試題及答案

本文大部份內容源自:http://www.cnblogs.com/SharkBin/p/4618388.htmlhtml

有一部分是本身看到感受不錯以後總結的:ios

本篇的面試題是我認爲比較好的iOS開發基礎知識點,但願你們看過這後在理解的基礎上掌握而不是死記硬背。死記硬背很快也會忘記的。c++

1 iOS基礎

1.1 父類實現深拷貝時,子類如何實現深度拷貝。父類沒有實現深拷貝時,子類如何實現深度拷貝。

  • 深拷貝同淺拷貝的區別:淺拷貝是指針拷貝,對一個對象進行淺拷貝,至關於對指向對象的指針進行復制,產生一個新的指向這個對象的指針,那麼就是有兩個指針指向同一個對象,這個對象銷燬後兩個指針都應該置空。深拷貝是對一個對象進行拷貝,至關於對對象進行復制,產生一個新的對象,那麼就有兩個指針分別指向兩個對象。當一個對象改變或者被銷燬後拷貝出來的新的對象不受影響。程序員

  • 實現深拷貝須要實現NSCoying協議,實現- (id)copyWithZone:(NSZone *)zone 方法。當對一個property屬性含有copy修飾符的時候,在進行賦值操做的時候實際上就是調用這個方法。面試

  • 父類實現深拷貝以後,子類只要重寫copyWithZone方法,在方法內部調用父類的copyWithZone方法,以後實現本身的屬性的處理objective-c

  • 父類沒有實現深拷貝,子類除了須要對本身的屬性進行處理,還要對父類的屬性進行處理。算法

1.2 KVO,NSNotification,delegate及block區別

  • KVO就是cocoa框架實現的觀察者模式,通常同KVC搭配使用,經過KVO能夠監測一個值的變化,好比View的高度變化。是一對多的關係,一個值的變化會通知全部的觀察者。
  • NSNotification是通知,也是一對多的使用場景。在某些狀況下,KVO和NSNotification是同樣的,都是狀態變化以後告知對方。NSNotification的特色,就是須要被觀察者先主動發出通知,而後觀察者註冊監聽後再來進行響應,比KVO多了發送通知的一步,可是其優勢是監聽不侷限於屬性的變化,還能夠對多種多樣的狀態變化進行監聽,監聽範圍廣,使用也更靈活。編程

  • delegate 是代理,就是我不想作的事情交給別人作。好比狗須要吃飯,就經過delegate通知主人,主人就會給他作飯、盛飯、倒水,這些操做,這些狗都不須要關心,只須要調用delegate(代理人)就能夠了,由其餘類完成所須要的操做。因此delegate是一對一關係。swift

  • block是delegate的另外一種形式,是函數式編程的一種形式。使用場景跟delegate同樣,相比delegate更靈活,並且代理的實現更直觀。設計模式

  • KVO通常的使用場景是數據,需求是數據變化,好比股票價格變化,咱們通常使用KVO(觀察者模式)。delegate通常的使用場景是行爲,需求是須要別人幫我作一件事情,好比買賣股票,咱們通常使用delegate。
    Notification通常是進行全局通知,好比利好消息一出,通知你們去買入。delegate是強關聯,就是委託和代理雙方互相知道,你委託別人買股票你就須要知道經紀人,經紀人也不要知道本身的顧客。Notification是弱關聯,利好消息發出,你不須要知道是誰發的也能夠作出相應的反應,同理發消息的人也不須要知道接收的人也能夠正常發出消息。

1.3 KVC若是實現,如何進行鍵值查找。KVO如何實現

請看這兩篇博文 KVC KVO

1.4 將一個函數在主線程執行的4種方法

  • GCD方法,經過向主線程隊列發送一個block塊,使block裏的方法能夠在主線程中執行。
dispatch_async(dispatch_get_main_queue(), ^{ //須要執行的方法 });
  • NSOperation 方法
NSOperationQueue *mainQueue = [NSOperationQueue mainQueue]; //主隊列 NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{ //須要執行的方法 }]; [mainQueue addOperation:operation];
  • NSThread 方法
[self performSelector:@selector(method) onThread:[NSThread mainThread] withObject:nil waitUntilDone:YES modes:nil]; [self performSelectorOnMainThread:@selector(method) withObject:nil waitUntilDone:YES]; [[NSThread mainThread] performSelector:@selector(method) withObject:nil];
  • RunLoop方法
[[NSRunLoop mainRunLoop] performSelector:@selector(method) withObject:nil]; 

1.5 如何讓計時器調用一個類方法

  • 計時器只能調用實例方法,可是能夠在這個實例方法裏面調用靜態方法。
  • 使用計時器須要注意,計時器必定要加入RunLoop中,而且選好model才能運行。scheduledTimerWithTimeInterval方法建立一個計時器並加入到RunLoop中因此能夠直接使用。
  • 若是計時器的repeats選擇YES說明這個計時器會重複執行,必定要在合適的時機調用計時器的invalid。不能在dealloc中調用,由於一旦設置爲repeats 爲yes,計時器會強持有self,致使dealloc永遠不會被調用,這個類就永遠沒法被釋放。好比能夠在viewDidDisappear中調用,這樣當類須要被回收的時候就能夠正常進入dealloc中了。
[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timerMethod) userInfo:nil repeats:YES]; -(void)timerMethod { //調用類方法 [[self class] staticMethod]; } -(void)invalid { [timer invalid]; timer = nil; }

1.6 如何重寫類方法

  • 一、在子類中實現一個同基類名字同樣的靜態方法
  • 二、在調用的時候不要使用類名調用,而是使用[self class]的方式調用。原理,用類名調用是早綁定,在編譯期綁定,用[self class]是晚綁定,在運行時決定調用哪一個方法。

1.7 NSTimer建立後,會在哪一個線程運行。

  • 用scheduledTimerWithTimeInterval建立的,在哪一個線程建立就會被加入哪一個線程的RunLoop中就運行在哪一個線程
  • 本身建立的Timer,加入到哪一個線程的RunLoop中就運行在哪一個線程。

1.8 id和NSObject*的區別

  • id是一個 objc_object 結構體指針,定義是
typedef struct objc_object *id
  • id能夠理解爲指向對象的指針。全部oc的對象 id均可以指向,編譯器不會作類型檢查,id調用任何存在的方法都不會在編譯階段報錯,固然若是這個id指向的對象沒有這個方法,該崩潰仍是會崩潰的。

  • NSObject *指向的必須是NSObject的子類,調用的也只能是NSObjec裏面的方法不然就要作強制類型轉換。

  • 不是全部的OC對象都是NSObject的子類,還有一些繼承自NSProxy。NSObject *可指向的類型是id的子集。

個人理解若是有錯漏請必定指出,很是感謝!

如下內容後續補充

iOS 核心框架

  • CoreAnimation
  • CoreGraphics
  • CoreLocation
  • AVFoundation
  • Foundation

iOS核心機制

  • UITableView 重用
  • ObjC內存管理;自動釋放池,ARC如何實現
  • runloop
  • runtime
  • Block的定義、特性、內存區域、如何實現
  • Responder Chain
  • NSOperation
  • GCD

數據結構

  • 8大排序算法
  • 二叉樹實現
  • 二分查找實現

面向對象編程

  • 封裝、繼承、多態

  • 設計模式6個原則

  • 設計一個類的功能,如何劃分粒度(單一職責)

  • 接口隔離。

  • 若是有一個鳥類,有飛的動做,一個鴕鳥繼承它是合適的嗎(里氏替換)

  • 類之間的依賴如何依賴偶合度最小(依賴倒轉)
    高層依賴低層,低層不能依賴高層。依賴接口,不能依賴具體的類。

  • 若是A要調用C函數,但C是B的成員類,應該如何設計?(迪米特)

  • 如何設計類,能作到只增長代碼,而不修改代碼,有哪些經驗(開放封閉)
    經過設計模式解決。

計算機技術

  • 計算機網絡: TCP/IP、HTTPCDN、SPDY
  • 計算機安全: RSA、AES、DES
  • 操做系統:線程、進程、堆棧、死鎖、調度算法

iOS新特性、新技術

  • iOS7 UIDynamic、SpritKit、新佈局、扁平化
  • iOS8 應用程序擴展、HealthKit、SceneKit、CoreLocation、TouchID、PhotoKit
  • iOS9
  • Apple Watch
  • 第三方庫:SDWebImage、AFNetwork、JSONKit、wax
  • swift
 
 

這些面試題都是 Objective-C基礎面試題,一塊兒來看看。

一、#import和#include的區別,@class表明什麼?

@class通常用於頭文件中須要聲明該類的某個實例變量的時候用到,在m文件中仍是須要使用#import

而#import比起#include的好處就是不會引發重複包含

二、談談Object-C的內存管理方式及過程?

1.當你使用new,alloc和copy方法建立一個對象時,該對象的保留計數器值爲1.當你再也不使用該對象時,你要負責向該對象發送一條release或autorelease消息.這樣,該對象將在使用壽命結束時被銷燬.

2.當你經過任何其餘方法得到一個對象時,則假設該對象的保留計數器值爲1,並且已經被設置爲自動釋放,你不須要執行任何操做來確保該對象被清理.若是你打算在一段時間內擁有該對象,則須要保留它並確保在操做完成時釋放它.

3.若是你保留了某個對象,你須要(最終)釋放或自動釋放該對象.必須保持retain方法和release方法的使用次數相等.

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

objective-c – 類裏面的方法只有兩種, 靜態方法和實例方法. 這彷佛就不是完整的面向對象了,按照OO的原則就是一個對象只暴露有用的東西. 若是沒有了私有方法的話, 對於一些小範圍的代碼重用就不那麼順手了. 在類裏面聲名一個私有方法

@interface Controller : NSObject { NSString *something; }

+ (void)thisIsAStaticMethod;

– (void)thisIsAnInstanceMethod;

@end

@interface Controller (private) -

(void)thisIsAPrivateMethod;

@end

@private能夠用來修飾私有變量

在Objective‐C中,全部實例變量默認都是私有的,全部實例方法默認都是公有的

四、Object-C有多繼承嗎?沒有的話用什麼代替?cocoa 中全部的類都是NSObject 的子類

多繼承在這裏是用protocol 委託代理 來實現的

你不用去考慮繁瑣的多繼承 ,虛基類的概念.

ood的多態特性 在 obj-c 中經過委託來實現.

五、內存管理 Autorelease、retain、copy、assign的set方法和含義?

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

NSMutableArray aArray = [[NSArray alloc] init]; 後,須要 [aArray release];

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

[aArray retain] 後,須要 [aArray release];

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

obj2 = [[obj1 someMethod] autorelease];

對象2接收對象1的一個自動釋放的值,或傳遞一個基本數據類型(NSInteger,NSString)時:你或但願將對象2進行retain,以防止它在被使用以前就被自動釋放掉。可是在retain後,必定要在適當的時候進行釋放。

關於索引計數(Reference Counting)的問題

retain值 = 索引計數(Reference Counting)

NSArray對象會retain(retain值加一)任何數組中的對象。當NSArray被卸載(dealloc)的時候,全部數組中的對象會 被 執行一次釋放(retain值減一)。不只僅是NSArray,任何收集類(Collection Classes)都執行相似操做。例如 NSDictionary,甚至UINavigationController。

Alloc/init創建的對象,索引計數爲1。無需將其再次retain。

[NSArray array]和[NSDate date]等「方法」創建一個索引計數爲1的對象,可是也是一個自動釋放對象。因此是本地臨時對象,那麼無所謂了。若是是打算在全Class中使用的變量(iVar),則必須retain它。

缺省的類方法返回值都被執行了「自動釋放」方法。(*如上中的NSArray)

在類中的卸載方法「dealloc」中,release全部未被平衡的NS對象。(*全部未被autorelease,而retain值爲1的)

六、淺拷貝和深拷貝區別是什麼

簡單的來講就是,在有指針的狀況下,淺拷貝只是增長了一個指針指向已經存在的內存,而深拷貝就是增長一個指針而且申請一個新的內存,使這個增長的指針指向這個新的內存,採用深拷貝的狀況下,釋放內存的時候就不會出如今淺拷貝時重複釋放同一內存的錯誤

七、C和obj-c 如何混用

1)obj-c的編譯器處理後綴爲m的文件時,能夠識別obj-c和c的代碼,處理mm文件能夠識別obj-c,c,c++代碼,但cpp文件必須只能用c/c++代碼,並且cpp文件include的頭文件中,也不能出現obj-c的代碼,由於cpp只是cpp

2)在mm文件中混用cpp直接使用便可,因此obj-c混cpp不是問題

3)在cpp中混用obj-c其實就是使用obj-c編寫的模塊是咱們想要的。

若是模塊以類實現,那麼要按照cpp class的標準寫類的定義,頭文件中不能出現obj-c的東西,包括#import cocoa的。實現文件中,即類的實現代碼中可使用obj-c的東西,能夠import,只是後綴是mm。

若是模塊以函數實現,那麼頭文件要按c的格式聲明函數,實現文件中,c++函數內部能夠用obj-c,但後綴仍是mm或m。

總結:只要cpp文件和cpp include的文件中不包含obj-c的東西就能夠用了,cpp混用obj-c的關鍵是使用接口,而不能直接使用 實現代 碼,實際上cpp混用的是obj-c編譯後的o文件,這個東西實際上是無差異的,因此能夠用。obj-c的編譯器支持cpp

八、Objective-C中類別和類擴展的區別。

答案:category和extensions的不一樣在於後者能夠添加屬性。另外後者添加的方法是必需要實現的。

extensions能夠認爲是一個私有的Category。

九、咱們說的Objective-C是動態運行時語言是什麼意思?

答案:多態。 主要是將數據類型的肯定由編譯時,推遲到了運行時。

這個問題其實淺涉及到兩個概念,運行時和多態。

簡單來講,運行時機制使咱們直到運行時纔去決定一個對象的類別,以及調用該類別對象指定方法。

多態:不一樣對象以本身的方式響應相同的消息的能力叫作多態。意思就是假設生物類(life)都用有一個相同的方法-eat;

那人類屬於生物,豬也屬於生物,都繼承了life後,實現各自的eat,可是調用是咱們只需調用各自的eat方法。

也就是不一樣的對象以本身的方式響應了相同的消息(響應了eat這個選擇器)。

所以也能夠說,運行時機制是多態的基礎?

十、Objective-C堆和棧的區別?

管理方式:對於棧來說,是由編譯器自動管理,無需咱們手工控制;對於堆來講,釋放工做由程序員控制,容易產生memory leak。

申請大小:

棧:在Windows下,棧是向低地址擴展的數據結構,是一塊連續的內存的區域。這句話的意思是棧頂的地址和棧的最大容量是系統預先規定好的,在 WINDOWS下,棧的大小是2M(也有的說是1M,總之是一個編譯時就肯定的常數),若是申請的空間超過棧的剩餘空間時,將提示overflow。因 此,能從棧得到的空間較小。

堆:堆是向高地址擴展的數據結構,是不連續的內存區域。這是因爲系統是用鏈表來存儲的空閒內存地址的,天然是不連續的,而鏈表的遍歷方向是由低地址向高地址。堆的大小受限於計算機系統中有效的虛擬內存。因而可知,堆得到的空間比較靈活,也比較大。

碎片問題:對於堆來說,頻繁的new/delete勢必會形成內存空間的不連續,從而形成大量的碎片,使程序效率下降。對於棧來說,則不會存在這個問題,由於棧是先進後出的隊列,他們是如此的一一對應,以致於永遠都不可能有一個內存塊從棧中間彈出

分配方式:堆都是動態分配的,沒有靜態分配的堆。棧有2種分配方式:靜態分配和動態分配。靜態分配是編譯器完成的,好比局部變量的分配。動態分配由alloca函數進行分配,可是棧的動態分配和堆是不一樣的,他的動態分配是由編譯器進行釋放,無需咱們手工實現。

分配效率:棧是機器系統提供的數據結構,計算機會在底層對棧提供支持:分配專門的寄存器存放棧的地址,壓棧出棧都有專門的指令執行,這就決定了棧的效率比較高。堆則是C/C++函數庫提供的,它的機制是很複雜的。

相關文章
相關標籤/搜索