iOS面試必看 最全梳理


來自網絡

序言

目前形勢,參加到iOS隊伍的人是愈來愈多,甚至已經到供過於求了。今年,找過工做人可能會更深入地體會到今年的就業形勢不容樂觀,加之,培訓機構一火車地向用人單位輸送iOS開發人員,打破了生態圈的動態平衡。矯情一下,言歸正傳,我奉獻一下,爲iOS應聘者梳理一下面試題,但願能助一臂之力!css

OC的理解與特性

  • OC做爲一門面向對象的語言,天然具備面向對象的語言特性:封裝、繼承、多態。它既具備靜態語言的特性(如C++),又有動態語言的效率(動態綁定、動態加載等)。整體來說,OC確實是一門不錯的編程語言,
  • Objective-C具備至關多的動態特性,表現爲三方面:動態類型(Dynamic typing)、動態綁定(Dynamic binding)和動態加載(Dynamic loading)。動態——必須到運行時(run time)纔會作的一些事情。
  • 動態類型:即運行時再決定對象的類型,這種動態特性在平常的應用中很是常見,簡單來講就是id類型。事實上,因爲靜態類型的固定性和可預知性,從而使用的更加普遍。靜態類型是強類型,而動態類型屬於弱類型,運行時決定接受者。
  • 動態綁定:基於動態類型,在某個實例對象被肯定後,其類型便被肯定了,該對象對應的屬性和響應消息也被徹底肯定。
  • 動態加載:根據需求加載所須要的資源,最基本就是不一樣機型的適配,例如,在Retina設備上加載@2x的圖片,而在老一些的普通蘋設備上加載原圖,讓程序在運行時添加代碼模塊以及其餘資源,用戶可根據須要加載一些可執行代碼和資源,而不是在啓動時就加載全部組件,可執行代碼能夠含有和程序運行時整合的新類。

簡述內存管理基本原則

  • 以前:OC內存管理遵循「誰建立,誰釋放,誰引用,誰管理」的機制,當建立或引用一個對象的時候,須要向她發送alloc、copy、retain消息,當釋放該對象時須要發送release消息,當對象引用計數爲0時,系統將釋放該對象,這是OC的手動管理機制(MRC)。
  • 目前:iOS 5.0以後引用自動管理機制——自動引用計數(ARC),管理機制與手動機制同樣,只是再也不須要調用retain、release、autorelease;它編譯時的特性,當你使用ARC時,在適當位置插入release和autorelease;它引用strong和weak關鍵字,strong修飾的指針變量指向對象時,當指針指向新值或者指針不復存在,相關聯的對象就會自動釋放,而weak修飾的指針變量指向對象,當對象的擁有者指向新值或者不存在時weak修飾的指針會自動置爲nil。
  • 若是使用alloccopy(mutableCopy)或者retian一個對象時,你就有義務,向它發送一條release或者autorelease消息。其餘方法建立的對象,不須要由你來管理內存。
  • 向一個對象發送一條autorelease消息,這個對象並不會當即銷燬, 而是將這個對象放入了自動釋放池,待池子釋放時,它會向池中每個對象發送 一條release消息,以此來釋放對象.
  • 向一個對象發送release消息,並不意味着這個對象被銷燬了,而是當這個對象的引用計數爲0時,系統纔會調用dealloc方法,釋放該對象和對象自己它所擁有的實例。
其餘注意事項
  • 若是一個對象有一個_strong類型的指針指向着,找個對象就不會被釋放。若是一個指針指向超出了它的做用域,就會被指向nil。若是一個指針被指向nil,那麼它原來指向的對象就被釋放了。當一個視圖控制器被釋放時,它內部的全局指針會被指向nil。用法「:無論全局變量仍是局部變量用_strong描述就行。
  • 局部變量:出了做用域,指針會被置爲nil。
  • 方法內部建立對象,外部使用須要添加_autorelease;
  • 連線的時候,用_weak描述。
  • 代理使用unsafe_unretained就至關於assign;
  • block中爲了不循環引用問題,使用_weak描述;
  • 聲明屬性時,不要以new開頭。若是非要以new開頭命名屬性的名字,須要本身定製get方法名,如
    @property(getter=theString) NSString * newString;
  • 若是要使用自動釋放池,用@autoreleasepool{}
  • ARC只能管理Foundation框架的變量,若是程序中把Foundation中的變量強制換成COre Foundation中的變量須要交換管理權;
  • 在非ARC工程中採用ARC去編譯某些類:-fobjc-arc。
  • 在ARC下的工程採用非ARC去編譯某些類:-fno-fobjc-arc。

如何理解MVC設計模式

MVC是一種架構模式,M表示MOdel,V表示視圖View,C表示控制器Controller:html

  • Model負責存儲、定義、操做數據;
  • View用來展現書給用戶,和用戶進行操做交互;
  • Controller是Model和View的協調者,Controller把Model中的數據拿過來給View用。Controller能夠直接與Model和View進行通訊,而View不能和Controller直接通訊。View與Controller通訊須要利用代理協議的方式,當有數據更新時,MOdel也要與Controller進行通訊,這個時候就要用Notification和KVO,這個方式就像一個廣播同樣,MOdel發信號,Controller設置監聽接受信號,當有數據更新時就發信號給Controller,Model和View不能直接進行通訊,這樣會違背MVC設計模式。

如何理解MVVM設計模式

  • ViewModel層,就是View和Model層的粘合劑,他是一個放置用戶輸入驗證邏輯,視圖顯示邏輯,發起網絡請求和其餘各類各樣的代碼的極好的地方。說白了,就是把原來ViewController層的業務邏輯和頁面邏輯等剝離出來放到ViewModel層。
  • View層,就是ViewController層,他的任務就是從ViewModel層獲取數據,而後顯示。
  • 如需瞭解更多,請查看這篇文章

Objective-C 中是否支持垃圾回收機制?

  • OC是支持垃圾回收機制的(Garbage collection簡稱GC),可是apple的移動終端中,是不支持GC的,Mac桌面系統開發中是支持的.
  • 移動終端開發是支持ARC(Automatic Reference Counting的簡稱),ARC是在IOS5以後推出的新技術,它與GC的機制是不一樣的。咱們在編寫代碼時, 不須要向對象發送release或者autorelease方法,也不能夠調用delloc方法,編譯器會在合適的位置自動給用戶生成release消息(autorelease),ARC 的特色是自動引用技術簡化了內存管理的難度.

協議的基本概念和協議中方法默認爲何類型

OC中的協議是一個方法列表,且多少有點相關。它的特色是能夠被任何類使用(實現),但它並非類(這裏咱們須要注意),自身不會實現這樣方法, 而是又其餘人來實現協議常常用來實現委託對象(委託設計模式)。若是一個類採用了一個協議,那麼它必須實現協議中必須須要實現的方法,在協議中的方法默認是必須實現(@required),添加關鍵字@optional,代表一旦採用該協議,這些「可選」的方法是能夠選擇不實現的。java

簡述類目category優勢和缺點

優勢:
  • 不須要經過增長子類而增長現有類的行爲(方法),且類目中的方法與原始類方法基本沒有區別;
  • 經過類目能夠將龐大一個類的方法進行劃分,從而便於代碼的往後的維護、更新以及提升代碼的閱讀性;
    缺點:
  • 沒法向類目添加實例變量,若是須要添加實例變量,只能經過定義子類的方式;
  • 類目中的方法與原始類以及父類方法相比具備更高優先級,若是覆蓋父類的方法,可能致使super消息的斷裂。所以,最好不要覆蓋原始類中的方法。

類別的做用

  • 給系統原有類添加方法,不能擴展屬性。若是類別中方法的名字跟系統的方法名同樣,在調用的時候類別中的方法優先級更高;
  • 分散類的實現:如:
    + (NSIndexPath *)indexPathForRow:(NSInteger)row inSection:(NSInteger)section
    本來屬於NSIndexPath的方法,但由於這個方法常用的表的時候調用、跟表的關係特別密切,所以把這個方法一類別的形式、聲明在UITableView.h中。
  • 聲明私有方法,某一個方法只實現,不聲明,至關於私有方法。
  • 類別不能聲明變量,類別不能夠直接添加屬性。property描述setter方法,就不會報錯。

循環引用的產生緣由,以及解決方法

  • 產生緣由:以下圖所示,對象A和對象B相互引用了對方做爲本身的成員變量,只有本身銷燬的時候才能將成員變量的引用計數減1。對象A的銷燬依賴於對象B的銷燬,同時對象B銷燬也依賴與對象A的銷燬,從而造成循環引用,此時,即便外界沒有任何指針訪問它,它也沒法釋放。

循環引用示例圖


多個對象間依然會存在循環引用問題,造成一個環,在編程中,造成的環越大越不容易察覺,以下圖所示:ios


多個對象引用示例圖
解決方法:
  • 事先知道存在循環引用的地方,在合理的位置主動斷開一個引用,是對象回收;
  • 使用弱引用的方法。

鍵路徑(keyPath)、鍵值編碼(KVC)、鍵值觀察(KVO)

鍵路徑
  • 在一個給定的實體中,同一個屬性的全部值具備相同的數據類型。
  • 鍵-值編碼技術用於進行這樣的查找—它是一種間接訪問對象屬性的機制。 - 鍵路徑是一個由用點做分隔符的鍵組成的字符串,用於指定一個鏈接在一塊兒的對象性質序列。第一個鍵的性質是由先前的性質決定的,接下來每一個鍵的值也是相對於其前面的性質。
  • 鍵路徑使您能夠以獨立於模型實現的方式指定相關對象的性質。經過鍵路徑,您能夠指定對象圖中的一個任意深度的路徑,使其指向相關對象的特定屬性。
鍵值編碼KVC
  • 鍵值編碼是一種間接訪問對象的屬性使用字符串來標識屬性,而不是經過調用存取方法,直接或經過實例變量訪問的機制,非對象類型的變量將被自動封裝或者解封成對象,不少狀況下會簡化程序代碼;
  • KVC的缺點:一旦使用 KVC 你的編譯器沒法檢查出錯誤,即不會對設置的鍵、鍵路徑進行錯誤檢查,且執行效率要低於合成存取器方法和自定的 setter 和 getter 方法。由於使用 KVC 鍵值編碼,它必須先解析字符串,而後在設置或者訪問對象的實例變量。
鍵值觀察KVO
  • 鍵值觀察機制是一種能使得對象獲取到其餘對象屬性變化的通知 ,極大的簡化了代碼。
  • 實現 KVO 鍵值觀察模式,被觀察的對象必須使用 KVC 鍵值編碼來修 改它的實例變量,這樣才能被觀察者觀察到。所以,KVC是KVO的基礎。
Demo

好比我自定義的一個button程序員

[self addObserver:self forKeyPath:@"highlighted" options:0 context:nil]; #pragma mark KVO - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if ([keyPath isEqualToString:@"highlighted"] ) { [self setNeedsDisplay]; } }

對於系統是根據keypath去取的到相應的值發生改變,理論上來講是和kvc機制的道理是同樣的。面試

KVC機制經過key找到value的原理
  • 當經過KVC調用對象時,好比:[self valueForKey:@」someKey」]時,程序會自動試圖經過下面幾種不一樣的方式解析這個調用。
  • 首先查找對象是否帶有 someKey 這個方法,若是沒找到,會繼續查找對象是否帶有someKey這個實例變量(iVar),若是尚未找到,程序會繼續試圖調用 -(id) valueForUndefinedKey:這個方法。若是這個方法仍是沒有被實現的話,程序會拋出一個NSUndefinedKeyException異常錯誤。
  • 補充:KVC查找方法的時候,不只僅會查找someKey這個方法,還會查找getsomeKey這個方法,前面加一個get,或者_someKey以_getsomeKey這幾種形式。同時,查找實例變量的時候也會不只僅查找someKey這個變量,也會查找_someKey這個變量是否存在。
  • 設計valueForUndefinedKey:方法的主要目的是當你使用-(id)valueForKey方法從對象中請求值時,對象可以在錯誤發生前,有最後的機會響應這個請求。

Objective-C 中如何實現 KVO

  • 註冊觀察者(注意:觀察者和被觀察者不會被保留也不會被釋放)正則表達式

    - (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;
  • 移除對象的觀察者身份
    - (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath;
  • KVO中誰要監聽誰註冊,而後對響應進行處理,使得觀察者與被觀察者徹底解耦。KVO只檢測類中的屬性,而且屬性名都是經過NSString來查找,編譯器不會檢錯和補全,所有取決於本身。

代理的做用

  • 代理又叫委託,是一種設計模式,代理是對象與對象之間的通訊交互,代理解除了對象之間的耦合性。
  • 改變或傳遞控制鏈。容許一個類在某些特定時刻通知到其餘類,而不須要獲取到那些類的指針。能夠減小框架複雜度。
  • 另一點,代理能夠理解爲java中的回調監聽機制的一種相似。
  • 代理的屬性常是assign的緣由:防止循環引用,以致對象沒法獲得正確的釋放。

NSNotification、Block、Delegate和KVO的區別

  • 代理是一種回調機制,且是一對一的關係,通知是一對多的關係,一個對向全部的觀察者提供變動通知;
  • 效率:Delegate比NSNOtification高;
  • Delegate和Block通常是一對一的通訊;
  • Delegate須要定義協議方法,代理對象實現協議方法,而且須要創建代理關係才能夠實現通訊;
  • Block:Block更加簡潔,不須要定義繁瑣的協議方法,但通訊事件比較多的話,建議使用Delegate;

Objective-C中可修改和不能夠修改類型

  • 可修改不可修改的集合類,就是可動態添加修改和不可動態添加修改。
  • 好比NSArrayNSMutableArray,前者在初始化後的內存控件就是固定不可變的,後者能夠添加等,能夠動態申請新的內存空間

當咱們調用一個靜態方法時,須要對對象進行 release 嗎?

  • 不須要,靜態方法(類方法)建立一個對象時,對象已被放入自動釋放池。在自動釋放池被釋放時,頗有可能被銷燬。

當咱們釋放咱們的對象時,爲何須要調用[super dealloc]方法,它的位置又是如何的呢?

  • 由於子類的某些實例是繼承自父類的,所以須要調用[super dealloc]方法, 來釋放父類擁有的實例,其實也就是子類自己的。通常來講咱們優先釋放子類擁 有的實例,最後釋放父類所擁有的實例。

對謂詞的認識

  • Cocoa 中提供了一個NSPredicate的類,該類主要用於指定過濾器的條件, 每個對象經過謂詞進行篩選,判斷條件是否匹配。若是須要了解使用方法,請看謂詞的具體使用

static、self、super關鍵字的做用

  • 函數體內static變量的做用範圍爲該函數體,不一樣於auto變量,該變量的內存只被分配一次,所以其值在下次調用時仍維持上次的值.
  • 在模塊內的 static 全局變量能夠被模塊內所用函數訪問,但不能被模塊外其它函數訪問.
  • 在模塊內的static函數只可被這一模塊內的其它函數調用,這個函數的使用範圍被限制在聲明.
  • 在類中的static成員變量屬於整個類所擁有,對類的全部對象只有一份拷貝.
  • self:當前消息的接收者。
  • super:向父類發送消息。

#include與#import的區別、#import 與@class 的區別

  • #include#import其效果相同,都是查詢類中定義的行爲(方法);
  • #import不會引發交叉編譯,確保頭文件只會被導入一次;
  • @class 的代表,只定 義了類的名稱,而具體類的行爲是未知的,通常用於.h 文件;
  • @class#import 編譯效率更高。
  • 此外@class#import 的主要區別在於解決引用死鎖的問題。

@public、@protected、@private 它們的含義與做用

  • @public:對象的實例變量的做用域在任意地方均可以被訪問 ;
  • @protected:對象的實例變量做用域在本類和子類均可以被訪問 ;
  • @private:實例變量的做用域只能在本類(自身)中訪問 .

解釋 id 類型

任意類型對象,程序運行時才決定對象的類型。sql

switch 語句 if 語句區別與聯繫

均表示條件的判斷,switch語句表達式只能處理的是整型、字符型和枚舉類型,而選擇流程語句則沒有這樣的限制。但switch語句比選擇流程控制語句效率更高。數據庫

isMemberOfClass 和 isKindOfClass 聯繫與區別

  • 聯繫:二者都能檢測一個對象是不是某個類的成員
  • 區別:isKindOfClass 不只用來肯定一個對象是不是一個類的成員,也能夠用來肯定一個對象是否派生自該類的類的成員 ,而isMemberOfClass 只能作到第一點。
  • 舉例:如 ClassA派 生 自NSObject 類 , ClassA *a = [ClassA alloc] init];,[a isKindOfClass:[NSObject class]] 能夠檢查出 a 是不是 NSObject派生類 的成員,但 isMemberOfClass 作不到。

iOS 開發中數據持久性有哪幾種?

數據存儲的核心都是寫文件。編程

  • 屬性列表:只有NSString、NSArray、NSDictionary、NSData可writeToFile;存儲依舊是plist文件。plist文件能夠存儲的7中數據類型:array、dictionary、string、bool、data、date、number。
  • 對象序列化(對象歸檔):對象序列化經過序列化的形式,鍵值關係存儲到本地,轉化成二進制流。經過runtime實現自動化歸檔/解檔,請參考這個文章。實現NSCoding協議必須實現的兩個方法:
    1.編碼(對象序列化):把不能直接存儲到plist文件中獲得數據,轉化爲二進制數據,NSData,能夠存儲到本地;
    2.解碼(對象反序列化):把二進制數據轉化爲原本的類型。
  • SQLite 數據庫:大量有規律的數據使用數據庫。
  • CoreData :經過管理對象進行增、刪、查、改操做的。它不是一個數據庫,不只能夠使用SQLite數據庫來保持數據,也能夠使用其餘的方式來存儲數據。如:XML。

CoreData的介紹:

  • CoreData是面向對象的API,CoreData是iOS中很是重要的一項技術,幾乎在全部編寫的程序中,CoreData都做爲數據存儲的基礎。
  • CoreData是蘋果官方提供的一套框架,用來解決與對象聲明週期管理、對象關係管理和持久化等方面相關的問題。
  • 大多數狀況下,咱們引用CoreData做爲持久化數據的解決方案,並利用它做爲持久化數據映射爲內存對象。提供的是對象-關係映射功能,也就是說,CoreData能夠將Objective-C對象轉換成數據,保存到SQL中,而後將保存後的數據還原成OC對象。

CoreData的特徵:

  • 經過CoreData管理應用程序的數據模型,能夠極大程度減小須要編寫的代碼數量。
  • 將對象數據存儲在SQLite數據庫已得到性能優化。
  • 提供NSFetchResultsController類用於管理表視圖的數據,即將Core Data的持久化存儲在表視圖中,並對這些數據進行管理:增刪查改。
  • 管理undo/redo操縱;
  • 檢查託管對象的屬性值是否正確。

Core Data的6成員對象

  • 1.NSManageObject:被管理的數據記錄Managed Object Model是描述應用程序的數據模型,這個模型包含實體(Entity)、特性(Property)、讀取請求(Fetch Request)等。
  • 2.NSManageObjectContext:管理對象上下文,持久性存儲模型對象,參與數據對象進行各類操做的全過程,並監測數據對象的變化,以提供對undo/redo的支持及更新綁定到數據的UI。
  • 3.NSPersistentStoreCoordinator:鏈接數據庫的Persistent Store Coordinator至關於數據文件管理器,處理底層的對數據文件的讀取和寫入,通常咱們與這個沒有交集。
  • 4.NSManagedObjectModel:被管理的數據模型、數據結構。
  • 5.NSFetchRequest:數據請求;
  • 6.NSEntityDescription:表格實體結構,還需知道.xcdatamodel文件編譯後爲.momd或者.mom文件。

Core Data的功能

  • 對於KVC和KVO完整且自動化的支持,除了爲屬性整合KVO和KVC訪問方法外,還整合了適當的集合訪問方法來處理多值關係;
  • 自動驗證屬性(property)值;
  • 支持跟蹤修改和撤銷操做;
  • 關係維護,Core Data管理數據的關係傳播,包括維護對象間的一致性;
  • 在內存上和界面上分組、過濾、組織數據;
  • 自動支持對象存儲在外部數據倉庫的功能;
  • 建立複雜請求:無需動手寫SQL語句,在獲取請求(fetch request)中關聯NSPredicate。NSPreadicate支持基本功能、相關子查詢和其餘高級的SQL特性。它支持正確的Unicode編碼、區域感知查詢、排序和正則表達式;
  • 延遲操做:Core Data使用懶加載(lazy loading)方式減小內存負載,還支持部分實體化延遲加載和複製對象的數據共享機制;
  • 合併策略:Core Data內置版本跟蹤和樂觀鎖(optimistic locking)來支持多用戶寫入衝突的解決,其中,樂觀鎖就是對數據衝突進行檢測,若衝突就返回衝突的信息;
  • 數據遷移:Core Data的Schema Migration工具能夠簡化應對數據庫結構變化的任務,在某些狀況容許你執行高效率的數據庫原地遷移工做;
  • 可選擇針對程序Controller層的集成,來支持UI的顯示同步Core Data在IPhone OS之上,提供NSFetchedResultsController對象來作相關工做,在Mac OS X上咱們用Cocoa提供的綁定(Binding)機制來完成的。

對象能夠被copy的條件

  • 只有實現了NSCopyingNSMutableCopying協議的類的對象才能被拷貝,分爲不可變拷貝和可變拷貝,具體區別戳這
  • NSCopying協議方法爲:
    - (id)copyWithZone:(NSZone *)zone { MyObject *copy = [[[self class] allocWithZone: zone] init]; copy.username = [self.username copyWithZone:zone]; return copy; }

自動釋放池工做原理

  • 自動釋放池是NSAutorelease類的一個實例,當向一個對象發送autorelease消息時,該對象會自動入池,待池銷燬時,將會向池中全部對象發送一條release消息,釋放對象。
  • [pool release]、 [pool drain]表示的是池自己不會銷燬,而是池子中的臨時對象都被髮送release,從而將對象銷燬。

在某個方法中 self.name = _name,name = _name 它 們有區別嗎,爲何?

  • 前者是存在內存管理的setter方法賦值,它會對_name對象進行保留或者拷貝操做
  • 後者是普通賦值
  • 通常來講,在對象的方法裏成員變量和方法都是能夠訪問的,咱們一般會重寫Setter方法來執行某些額外的工做。好比說,外部傳一個模型過來,那麼我會直接重寫Setter方法,當模型傳過來時,也就是意味着數據發生了變化,那麼視圖也須要更新顯示,則在賦值新模型的同時也去刷新UI。

解釋self = [super init]方法

  • 容錯處理,當父類初始化失敗,會返回一個nil,表示初始化失敗。因爲繼承的關係,子類是須要擁有父類的實例和行爲,所以,咱們必須先初始化父類,而後再初始化子類

定義屬性時,何時用 assignretaincopy 以及它們的之間的區別

  • assign:普通賦值,通常經常使用於基本數據類型,常見委託設計模式, 以此來防止循環引用。(咱們稱之爲弱引用).
  • retain:保留計數,得到到了對象的全部權,引用計數在原有基礎上加1.
  • copy:通常認爲,是在內存中從新開闢了一個新的內存空間,用來 存儲新的對象,和原來的對象是兩個不一樣的地址,引用計數分別爲1。可是當copy對象爲不可變對象時,那麼copy 的做用至關於retain。由於,這樣能夠節約內存空間

堆和棧的區別

  • 棧區(stack)由編譯器自動分配釋放 ,存放方法(函數)的參數值, 局部變量的值等,棧是向低地址擴展的數據結構,是一塊連續的內存的區域。即棧頂的地址和棧的最大容量是系統預先規定好的。
  • 堆區(heap)通常由程序員分配釋放, 若程序員不釋放,程序結束時由OS回收,向高地址擴展的數據結構,是不連續的內存區域,從而堆得到的空間比較靈活。
  • 碎片問題:對於堆來說,頻繁的new/delete勢必會形成內存空間的不連續,從而形成大量的碎片,使程序效率下降。對於棧來說,則不會存在這個問題,由於棧是先進後出的隊列,他們是如此的一一對應,以致於永遠都不可能有一個內存塊從棧中間彈出.
  • 分配方式:堆都是動態分配的,沒有靜態分配的堆。棧有2種分配方式:靜態分配和動態分配。靜態分配是編譯器完成的,好比局部變量的分配。動態分配由alloca函數進行分配,可是棧的動態分配和堆是不一樣的,他的動態分配是由編譯器進行釋放,無需咱們手工實現。
  • 分配效率:棧是機器系統提供的數據結構,計算機會在底層對棧提供支持:分配專門的寄存器存放棧的地址,壓棧出棧都有專門的指令執行,這就決定了棧的效率比較高。堆則是C/C++函數庫提供的,它的機制是很複雜的。
  • 全局區(靜態區)(static),全局變量和靜態變量的存儲是放在一塊 的,初始化的全局變量和靜態變量在一塊區域, 未初始化的全局變量和未初始化的靜態變量在相鄰的另外一塊區域。程序結束後有系統釋放。
  • 文字常量區—常量字符串就是放在這裏的。程序結束後由系統釋放。
  • 程序代碼區—存放函數體的二進制代碼

怎樣使用performSelector傳入3個以上參數,其中一個爲結構體

  • 由於系統提供的performSelector的API中,並無提供三個參數。所以,咱們只能傳數組或者字典,可是數組或者字典只有存入對象類型,而結構體並非對象類型,咱們只能經過對象放入結構做爲屬性來傳過去了.
    - (id)performSelector:(SEL)aSelector; - (id)performSelector:(SEL)aSelector withObject:(id)object; - (id)performSelector:(SEL)aSelector withObject: (id)object1 withObject:(id)object2;
  • 具體實現以下:

    typedef struct HYBStruct { int a; int b; } *my_struct; @interface HYBObject : NSObject @property (nonatomic, assign) my_struct arg3; @property (nonatomic, copy) NSString *arg1; @property (nonatomic, copy) NSString *arg2; @end @implementation HYBObject // 在堆上分配的內存,咱們要手動釋放掉 - (void)dealloc { free(self.arg3); } @end
  • 測試:
    my_struct str = (my_struct)(malloc(sizeof(my_struct))); str->a = 1; str->b = 2; HYBObject *obj = [[HYBObject alloc] init]; obj.arg1 = @"arg1"; obj.arg2 = @"arg2"; obj.arg3 = str; [self performSelector:@selector(call:) withObject:obj]; // 在回調時獲得正確的數據的 - (void)call:(HYBObject *)obj { NSLog(@"%d %d", obj.arg3->a, obj.arg3->b); }

UITableViewCell上有個UILabel,顯示NSTimer實現的秒錶時間,手指滾動cell過程當中,label是否刷新,爲何?

這是否刷新取決於timer加入到Run Loop中的Mode是什麼。Mode主要是用來指定事件在運行循環中的優先級的,分爲:

  • NSDefaultRunLoopMode(kCFRunLoopDefaultMode):默認,空閒狀態
  • UITrackingRunLoopMode:ScrollView滑動時會切換到該Mode
  • UIInitializationRunLoopMode:run loop啓動時,會切換到該mode
  • NSRunLoopCommonModes(kCFRunLoopCommonModes):Mode集合
    蘋果公開提供的Mode有兩個:
  • NSDefaultRunLoopMode(kCFRunLoopDefaultMode)
  • NSRunLoopCommonModes(kCFRunLoopCommonModes)
  • 在編程中:若是咱們把一個NSTimer對象以NSDefaultRunLoopMode(kCFRunLoopDefaultMode)添加到主運行循環中的時候, ScrollView滾動過程當中會由於mode的切換,而致使NSTimer將再也不被調度。當咱們滾動的時候,也但願不調度,那就應該使用默認模式。可是,若是但願在滾動時,定時器也要回調,那就應該使用common mode。

對於單元格重用的理解

  • 當屏幕上滑出屏幕時,系統會把這個單元格添加到重用隊列中,等待被重用,當有新單元從屏幕外滑入屏幕內時,從重用隊列中找看有沒有能夠重用的單元格,如有,就直接用,沒有就從新建立一個。

解決cell重用的問題

  • UITableView經過重用單元格來達到節省內存的目的,經過爲每一個單元格指定一個重用標示(reuseidentifier),即指定了單元格的種類,以及當單元格滾出屏幕時,容許恢復單元格以便複用。對於不一樣種類的單元格使用不一樣的ID,對於簡單的表格,一個標示符就夠了。
  • 如一個TableView中有10個單元格,但屏幕最多顯示4個,實際上iPhone只爲其分配4個單元格的內存,沒有分配10個,當滾動單元格時,屏幕內顯示的單元格重複使用這4個內存。實際上分配的cell的個數爲屏幕最大顯示數,當有新的cell進入屏幕時,會隨機調用已經滾出屏幕的Cell所佔的內存,這就是Cell的重用。
  • 對於多變的自定義Cell,這種重用機制會致使內容出錯,爲解決這種出錯的方法,把原來的
    UITableViewCell *cell = [tableview dequeueReusableCellWithIdentifier:defineString] 修改成:UITableViewCell *cell = [tableview cellForRowAtIndexPath:indexPath];
    這樣就解決掉cell重用機制致使的問題。

有a、b、c、d 4個異步請求,如何判斷a、b、c、d都完成執行?若是須要a、b、c、d順序執行,該如何實現?

  • 對於這四個異步請求,要判斷都執行完成最簡單的方式就是經過GCD的group來實現:
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_group_t group = dispatch_group_create(); dispatch_group_async(group, queue, ^{ /*任務a */ }); dispatch_group_async(group, queue, ^{ /*任務b */ }); dispatch_group_async(group, queue, ^{ /*任務c */ }); dispatch_group_async(group, queue, ^{ /*任務d */ }); dispatch_group_notify(group,dispatch_get_main_queue(), ^{ // 在a、b、c、d異步執行完成後,會回調這裏 });
  • 固然,咱們還能夠使用很是老套的方法來處理,經過四個變量來標識a、b、c、d四個任務是否完成,而後在runloop中讓其等待,當完成時才退出runloop。可是這樣作會讓後面的代碼得不到執行,直到Run loop執行完畢。
  • 解釋:要求順序執行,那麼能夠將任務放到串行隊列中,天然就是按順序來異步執行了。

使用block有什麼好處?使用NSTimer寫出一個使用block顯示(在UILabel上)秒錶的代碼

  • 代碼緊湊,傳值、回調都很方便,省去了寫代理的不少代碼。
  • NSTimer封裝成的block,具體實現
  • 實現方法:
    NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0 repeats:YES callback:^() { weakSelf.secondsLabel.text = ... } [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];

一個view已經初始化完畢,view上面添加了n個button,除用view的tag以外,還能夠採用什麼辦法來找到本身想要的button來修改button的值

有2種方法解決:

  • 第一種:若是是點擊某個按鈕後,纔會刷新它的值,其它不用修改,那麼不用引用任何按鈕,直接在回調時,就已經將接收響應的按鈕給傳過來了,直接經過它修改便可。
  • 第二種:點擊某個按鈕後,全部與之同類型的按鈕都要修改值,那麼能夠經過在建立按鈕時將按鈕存入到數組中,在須要的時候遍歷查找。

線程與進程的區別和聯繫?

  • 一個程序至少要有進城,一個進程至少要有一個線程.
  • 進程:資源分配的最小獨立單元,進程是具備必定獨立功能的程序關於某個數據集合上的一次運行活動,進程是系統進行資源分配和調度的一個獨立單位.
  • 線程:進程下的一個分支,是進程的實體,是CPU調度和分派的基本單元,它是比進程更小的能獨立運行的基本單位,線程本身基本不擁有系統資源,只擁有一點在運行中必不可少的資源(程序計數器、一組寄存器、棧),可是它可與同屬一個進程的其餘線程共享進程所擁有的所有資源。
  • 進程和線程都是由操做系統所體會的程序運行的基本單元,系統利用該基本單元實現系統對應用的併發性。
  • 進程和線程的主要差異在於它們是不一樣的操做系統資源管理方式。進程有獨立的地址空間,一個進程崩潰後,在保護模式下不會對其它進程產生影響,而線程只是一個進程中的不一樣執行路徑。線程有本身的堆棧和局部變量,但線程之間沒有單獨的地址空間,一個線程死掉就等於整個進程死掉,因此多進程的程序要比多線程的程序健壯,但在進程切換時,耗費資源較大,效率要差一些。
  • 但對於一些要求同時進行而且又要共享某些變量的併發操做,只能用線程,不能用進程。

多線程編程

  • NSThread:當須要進行一些耗時操做時會把耗時的操做放到線程中。線程同步:多個線程同時訪問一個數據會出問題,NSlock、線程同步塊、@synchronized(self){}。
  • NSOperationQueue操做隊列(不需考慮線程同步問題)。編程的重點都放在main裏面,NSInvocationOperationBSBlockOperation、自定義Operation。建立一個操做綁定相應的方法,當把操做添加到操做隊列中時,操做綁定的方法就會自動執行了,當把操做添加到操做隊列中時,默認會調用main方法。
  • GCD(`Grand Central Dispatch)宏大的中央調度,串行隊列、併發隊列、主線程隊列;
  • 同步和異步:同步指第一個任務不執行完,不會開始第二個,異步是無論第一個有沒有執行完,都開始第二個。
  • 串行和並行:串行是多個任務按必定順序執行,並行是多個任務同時執行;
  • 代碼是在分線程執行,在主線程嘟列中刷新UI。

多線程編程是防止主線程堵塞、增長運行效率的最佳方法。

  • Apple提供了NSOperation這個類,提供了一個優秀的多線程編程方法;
  • 一個NSOperationQueue操做隊列,至關於一個線程管理器,而非一個線程,由於你能夠設置這個線程管理器內能夠並行運行的線程數量等。
  • 多線程是一個比較輕量級的方法來實現單個應用程序內多個代碼執行路徑。
  • iPhoneOS下的主線程的堆棧大小是1M。第二個線程開始就是512KB,而且該值不能經過編譯器開關或線程API函數來更改,只有主線程有直接修改UI的能力。

定時器與線程的區別;

  • 定時器;能夠執行屢次,默認在主線程中。
  • 線程:只能執行一次。

Apple設備尺寸和編程尺寸


iPhone設備

IPod設備

iPad設備

TCP和UDP的區別於聯繫

  • TCP爲傳輸控制層協議,爲面向鏈接、可靠的、點到點的通訊;
  • UDP爲用戶數據報協議,非鏈接的不可靠的點到多點的通訊;
  • TCP側重可靠傳輸,UDP側重快速傳輸。

TCP鏈接的三次握手

  • 第一次握手:客戶端發送syn包(syn=j)到服務器,並進入SYN_SEND狀態,等待服務器確認;
  • 第二次握手:服務器收到syn包,必須確認客戶的SYN(ack=j+1),同時本身也發送一個SYN包,即SYN+ACK包,此時服務器進入SYN+RECV狀態;
  • 第三次握手:客戶端收到服務器的SYN+ACK包,向服務器發送確認包ACK(ack=k+1),此發送完畢,客戶端和服務器進入ESTABLISHED狀態,完成三次狀態。

Scoket鏈接和HTTP鏈接的區別:

  • HTTP協議是基於TCP鏈接的,是應用層協議,主要解決如何包裝數據。Socket是對TCP/IP協議的封裝,Socket自己並非協議,而是一個調用接口(API),經過Socket,咱們才能使用TCP/IP協議。
  • HTTP鏈接:短鏈接,客戶端向服務器發送一次請求,服務器響應後鏈接斷開,節省資源。服務器不能主動給客戶端響應(除非採用HTTP長鏈接技術),iPhone主要使用類NSURLConnection。
  • Socket鏈接:長鏈接,客戶端跟服務器端直接使用Socket進行鏈接,沒有規定鏈接後斷開,所以客戶端和服務器段保持鏈接通道,雙方能夠主動發送數據,通常多用於遊戲.Socket默認鏈接超時時間是30秒,默認大小是8K(理解爲一個數據包大小)。

HTTP協議的特色,關於HTTP請求GET和POST的區別

GET和POST的區別

  • HTTP超文本傳輸協議,是短鏈接,是客戶端主動發送請求,服務器作出響應,服務器響應以後,連接斷開。HTTP是一個屬於應用層面向對象的協議,HTTP有兩類報文:請求報文和響應報文。
  • HTTP請求報文:一個HTTP請求報文由請求行、請求頭部、空行和請求數據4部分組成。
  • HTTP響應報文:由三部分組成:狀態行、消息報頭、響應正文。
  • GET請求:參數在地址後拼接,沒有請求數據,不安全(由於全部參數都拼接在地址後面),不適合傳輸大量數據(長度有限制,爲1024個字節)。

    GET提交、請求的數據會附在URL以後,即把數據放置在HTTP協議頭<requestline>中。 以?分割URL和傳輸數據,多個參數用&鏈接。若是數據是英文字母或數字,原樣發送, 若是是空格,轉換爲+,若是是中文/其餘字符,則直接把字符串用BASE64加密。
  • POST請求:參數在請求數據區放着,相對GET請求更安全,而且數據大小沒有限制。把提交的數據放置在HTTP包的包體<request-body>中.

  • GET提交的數據會在地址欄顯示出來,而POST提交,地址欄不會改變。

傳輸數據的大小:

  • GET提交時,傳輸數據就會受到URL長度限制,POST因爲不是經過URL傳值,理論上書不受限。

安全性:

  • POST的安全性要比GET的安全性高;
  • 經過GET提交數據,用戶名和密碼將明文出如今URL上,好比登錄界面有可能被瀏覽器緩存。
  • HTTPS:安全超文本傳輸協議(Secure Hypertext Transfer Protocol),它是一個安全通訊通道,基於HTTP開發,用於客戶計算機和服務器之間交換信息,使用安全套結字層(SSI)進行信息交換,即HTTP的安全版。

ASIHttpRequest、AFNetWorking之間的區別

  • ASIHttpRequest功能強大,主要是在MRC下實現的,是對系統CFNetwork API進行了封裝,支持HTTP協議的CFHTTP,配置比較複雜,而且ASIHttpRequest框架默認不會幫你監聽網絡改變,若是須要讓ASIHttpRequest幫你監聽網絡狀態改變,而且手動開始這個功能。
  • AFNetWorking構建於NSURLConnection、NSOperation以及其餘熟悉的Foundation技術之上。擁有良好的架構,豐富的API及模塊構建方式,使用起來很是輕鬆。它基於NSOperation封裝的,AFURLConnectionOperation子類。
  • ASIHttpRequest是直接操做對象ASIHttpRequest是一個實現了NSCoding協議的NSOperation子類;AFNetWorking直接操做對象的AFHttpClient,是一個實現NSCoding和NSCopying協議的NSObject子類。
  • 同步請求:ASIHttpRequest直接經過調用一個startSynchronous方法;AFNetWorking默認沒有封裝同步請求,若是開發者須要使用同步請求,則須要重寫getPath:paraments:success:failures方法,對於AFHttpRequestOperation進行同步處理。
  • 性能對比:AFNetworking請求優於ASIHttpRequest;

XML數據解析方式各有什麼不一樣,JSON解析有哪些框架?

  • XML數據解析的兩種解析方式:DOM解析和SAX解析;
  • DOM解析必須完成DOM樹的構造,在處理規模較大的XML文檔時就很耗內存,佔用資源較多,讀入整個XML文檔並構建一個駐留內存的樹結構(節點樹),經過遍歷樹結構能夠檢索任意XML節點,讀取它的屬性和值,一般狀況下,能夠藉助XPath查詢XML節點;
  • SAX與DOM不一樣,它是事件驅動模型,解析XML文檔時每遇到一個開始或者結束標籤、屬性或者一條指令時,程序就產生一個事件進行相應的處理,一邊讀取XML文檔一邊處理,沒必要等整個文檔加載完才採起措施,當在讀取解析過程當中遇到須要處理的對象,會發出通知進行處理。所以,SAX相對於DOM來講更適合操做大的XML文檔。
    -JSON解析:性能比較好的主要是第三方的JSONKIT和iOS自帶的JSON解析類,其中自帶的JSON解析性能最高,但只能用於iOS5以後。

如何進行真機調試

  • 1.首先須要用鑰匙串建立一個鑰匙(key);
  • 2.將鑰匙串上傳到官網,獲取iOS Development證書;
  • 3.建立App ID即咱們應用程序中的Boundle ID;
  • 4.添加Device ID即UDID;
  • 5.經過勾選前面所建立的證書:App ID、Device ID;
  • 6.生成mobileprovision文件;
  • 7.先決條件:申請開發者帳號 99美刀

APP發佈的上架流程

  • 1.登陸應用發佈網站添加應用信息;
  • 2.下載安裝發佈證書;
  • 3.選擇發佈證書,使用Archive編譯發佈包,用Xcode將代碼(發佈包)上傳到服務器;
  • 4.等待審覈經過;
  • 5.生成IPA:菜單欄->Product->Archive.

SVN的使用

  • SVN=版本控制+備份服務器,能夠把SVN當成備份服務器,而且能夠幫助你記住每次上服務器的檔案內容,並自動賦予每次變動的版本;
  • SVN的版本控制:全部上傳版本都會幫您記錄下來,也有版本分支及合併等功能。SVN可讓不一樣的開發者存取一樣的檔案,而且利用SVN Server做爲檔案同步的機制,即您有檔案更新時,無需將檔案寄送給您的開發成員。SVN的存放檔案方式是採用差別備份的方式,即會備份到不一樣的地方,節省硬盤空間,也能夠對非文字文件進行差別備份。
  • SVN的重要性:備份工做檔案的重要性、版本控管的重要性、夥伴間的數據同步的重要性、備份不一樣版本是很耗費硬盤空間的;
  • 防止衝突:
    1.防止代碼衝突:不要多人同時修改同一文件,例如:A、B都修改同一個文件,先讓A修改,而後提交到服務器,而後B更新下來,再進行修改;
    2.服務器上的項目文件Xcodeproj,僅讓一我的管理提交,其餘人只更新,防止文件發生衝突。

如何進行網絡消息推送

  • 一種是Apple本身提供的通知服務(APNS服務器)、一種是用第三方推送機制。
  • 首先應用發送通知,系統彈出提示框詢問用戶是否容許,當用戶容許後向蘋果服務器(APNS)請求deviceToken,並由蘋果服務器發送給本身的應用,本身的應用將DeviceToken發送本身的服務器,本身服務器想要發送網絡推送時將deviceToken以及想要推送的信息發送給蘋果服務器,蘋果服務器將信息發送給應用。
  • 推送信息內容,總容量不超過256個字節;
  • iOS SDK自己提供的APNS服務器推送,它能夠直接推送給目標用戶並根據您的方式彈出提示。
    優勢:不論應用是否開啓,都會發送到手機端;
    缺點:消息推送機制是蘋果服務端控制,個別時候可能會有延遲,由於蘋果服務器也有隊列來處理全部的消息請求;
  • 第三方推送機制,廣泛使用Socket機制來實現,幾乎能夠達到即時的發送到目標用戶手機端,適用於即時通信類應用。
    優勢:實時的,取決於心跳包的節奏;
    缺點:iOS系統的限制,應用不能長時間的後臺運行,因此應用關閉的狀況下這種推送機制不可用。

網絡七層協議

  • 應用層
    1.用戶接口、應用程序;
    2.Application典型設備:網關;
    3.典型協議、標準和應用:TELNET、FTP、HTTP
  • 表示層
    1.數據表示、壓縮和加密presentation
    2.典型設備:網關
    3.典型協議、標準和應用:ASCLL、PICT、TIFF、JPEG|MPEG
    4.表示層至關於一個東西的表示,表示的一些協議,好比圖片、聲音和視頻MPEG。
  • 會話層
    1.會話的創建和結束;
    2.典型設備:網關;
    3.典型協議、標準和應用:RPC、SQL、NFS、X WINDOWS、ASP
  • 傳輸層
    1.主要功能:端到端控制Transport;
    2.典型設備:網關;
    3.典型協議、標準和應用:TCP、UDP、SPX
  • 網絡層
    1.主要功能:路由、尋址Network;
    2.典型設備:路由器;
    3.典型協議、標準和應用:IP、IPX、APPLETALK、ICMP;
  • 數據鏈路層
    1.主要功能:保證無差錯的疏忽鏈路的data link;
    2.典型設備:交換機、網橋、網卡;
    3.典型協議、標準和應用:802.二、802.3ATM、HDLC、FRAME RELAY;
  • 物理層
    1.主要功能:傳輸比特流Physical;
    2.典型設備:集線器、中繼器
    3.典型協議、標準和應用:V.3五、EIA/TIA-232.

對NSUserDefaults的理解

  • NSUserDefaults:系統提供的一種存儲數據的方式,主要用於保存少許的數據,默認存儲到library下的Preferences文件夾。

SDWebImage原理

調用類別的方法:

  • 從內存中(字典)找圖片(當這個圖片在本次程序加載過),找到直接使用;
  • 從沙盒中找,找到直接使用,緩存到內存。
  • 從網絡上獲取,使用,緩存到內存,緩存到沙盒。

OC中是否有二維數組,如何實現二維數組

  • OC中沒有二維數組,可經過嵌套數組實現二維數組。

LayoutSubViews在何時被調用?

  • 當View自己的frame改變時,會調用這個方法。

深拷貝和淺拷貝

  • 若是對象有個指針型成員變量指向內存中的某個資源,那麼如何複製這個對象呢?你會只是複製指針的值傳給副本的新對象嗎?指針只是存儲內存中資源地址的佔位符。在複製操做中,若是隻是將指針複製給新對象,那麼底層的資源實際上仍然由兩個實例在共享。

示例圖1
  • 淺複製:兩個實例的指針仍指向內存中的同一資源,只複製指針值而不是實際資源;
  • 深複製:不只複製指針值,還複製指向指針所指向的資源。以下圖:

示例圖2

單例模式理解與使用

  • 單例模式是一種經常使用設計模式,單例模式是一個類在系統中只有一個實例對象。經過全局的一個入口點對這個實例對象進行訪問;
  • iOS中單例模式的實現方式通常分爲兩種:非ARC和ARC+GCD。

對沙盒的理解

  • 每一個iOS應用都被限制在「沙盒」中,沙盒至關於一個加了僅主人可見權限的文件夾,及時在應用程序安裝過程當中,系統爲每一個單獨的應用程序生成它的主目錄和一些關鍵的子目錄。蘋果對沙盒有幾條限制:
    1. 應用程序在本身的沙盒中運做,可是不能訪問任何其餘應用程序的沙盒; 2. 應用之間不能共享數據,沙盒裏的文件不能被複制到其餘 應用程序的文件夾中,也不能把其餘應用文件夾複製到沙盒中; 3. 蘋果禁止任何讀寫沙盒之外的文件,禁止應用程序將內容寫到沙盒之外的文件夾中; 4. 沙盒目錄裏有三個文件夾:Documents——存儲 應用程序的數據文件,存儲用戶數據或其餘按期備份的信息; Library下有兩個文件夾,Caches存儲應用程序再次啓動所需的信息, Preferences包含應用程序的偏好設置文件,不可在這更改偏好設置; temp存放臨時文件即應用程序再次啓動不須要的文件。
  • 獲取沙盒根目錄的方法,有幾種方法:用NSHomeDirectory獲取。
  • 獲取Document路徑:
    NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES).

對瀑布流的理解

  • 首先圖片的寬度都是同樣的,1.將圖片等比例壓縮,讓圖片不變形;2.計算圖片最低應該擺放的位置,哪一列低就放在哪;3.進行最優排列,在ScrollView的基礎上添加兩個tableView,而後將以前所計算的scrollView的高度經過tableView展現出來。
  • 如何使用兩個TableView產生聯動:將兩個tableView的滾動事件禁止掉,最外層scrollView滾動時將兩個TableView跟着滾動,而且更改contentOffset,這樣產生效果滾動的兩個tableView。

ViewController 的 loadView,、viewDidLoad,、viewDidUnload 分別是在何時調用的?

  • viewDidLoad在view從nib文件初始化時調用,loadView在controller的view爲nil時調用。
  • 此方法在編程實現view時調用,view控制器默認會註冊memory warning notification,當view controller的任何view沒有用的時候,viewDidUnload會被調用,在這裏實現將retainview release,若是是retainIBOutlet view 屬性則不要在這裏release,IBOutlet會負責release

關鍵字volatile有什麼含意?並給出三個不一樣的例子:

  • 一個定義爲volatile的變量是說這變量可能會被意想不到地改變,這樣,編譯器就不會去假設這個變量的值了。精確地說就是,優化器在用到這個變量時必須每次都當心地從新讀取這個變量的值,而不是使用保存在寄存器裏的備份。下面是volatile變量的幾個例子:
    • 並行設備的硬件寄存器(如:狀態寄存器);
    •一箇中斷服務子程序中會訪問到的非自動變量(Non-automatic variables);
    • 多線程應用中被幾個任務共享的變量。

@synthesize、@dynamic的理解

  • @synthesize是系統自動生成getter和setter屬性聲明;@synthesize的意思是,除非開發人員已經作了,不然由編譯器生成相應的代碼,以知足屬性聲明;
  • @dynamic是開發者自已提供相應的屬性聲明,@dynamic意思是由開發人員提供相應的代碼:對於只讀屬性須要提供setter,對於讀寫屬性須要提供 settergetter。查閱了一些資料肯定@dynamic的意思是告訴編譯器,屬性的獲取與賦值方法由用戶本身實現, 不自動生成。

frame和bounds有什麼不一樣?

  • frame指的是:該view在父view座標系統中的位置和大小。(參照點是父親的座標系統)
  • bounds指的是:該view在自己座標系統中的位置和大小。(參照點是自己座標系統)

view的touch事件有哪些?

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event; - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event; - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event; - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;

自定義實現UITabbarController的原理

  • 運用字典,點擊五個按鈕的一個能夠從字典裏選擇一個控制器對象,將其View顯示到主控制器視圖上。

iOS中的響應者鏈的工做原理

  • 每個應用有一個響應者鏈,咱們的視圖結構是一個N叉樹(一個視圖能夠有多個子視圖,一個子視圖同一時刻只有一個父視圖),而每個繼承UIResponder的對象均可以在這個N叉樹中扮演一個節點。
  • 當葉節點成爲最高響應者的時候,從這個葉節點開始往其父節點開始追朔出一條鏈,那麼對於這一個葉節點來說,這一條鏈就是當前的響應者鏈。響應者鏈將系統捕獲到的UIEvent與UITouch從葉節點開始層層向下分發,期間能夠選擇中止分發,也能夠選擇繼續向下分發。
  • 如需瞭解更多細節,請讀這篇文章

    View和View之間傳值方式

  • 對象的property屬性傳值;
  • 方法參數傳值;
  • NSUserDefault傳值;
  • 塊傳值。

property屬性的修飾符的做用

  • getter=getName、setter=setName:設置setter與getter的方法名;
  • readwrite、readonly:設置可供訪問級別;
  • assign:方法直接賦值,不進行任何retain操做,爲了解決原類型與環循引用問題;
  • retain:其setter方法對參數進行release舊值再retain新值,全部實現都是這個順序;
  • copy:其setter方法進行copy操做,與retain處理流程同樣,先對舊值release,再copy出新的對象,retainCount爲1。這是爲了減小對上下文的依賴而引入的機制。
  • nonatomic:非原子性訪問,不加同步, 多線程併發訪問會提升性能。注意,若是不加此屬性,則默認是兩個訪問方法都爲原子型事務訪問。

對於Run Loop的理解

  • RunLoop,是多線程的法寶,即一個線程一次只能執行一個任務,執行完任務後就會退出線程。主線程執行完即時任務時會繼續等待接收事件而不退出。非主線程一般來講就是爲了執行某一任務的,執行完畢就須要歸還資源,所以默認是不運行RunLoop的;
  • 每個線程都有其對應的RunLoop,只是默認只有主線程的RunLoop是啓動的,其它子線程的RunLoop默認是不啓動的,若要啓動則須要手動啓動;
  • 在一個單獨的線程中,若是須要在處理完某個任務後不退出,繼續等待接收事件,則須要啓用RunLoop;
  • NSRunLoop提供了一個添加NSTimer的方法,能夠指定Mode,若是要讓任何狀況下都回調,則須要設置Mode爲Common模式;
  • 實質上,對於子線程的runloop默認是不存在的,由於蘋果採用了懶加載的方式。若是咱們沒有手動調用[NSRunLoop currentRunLoop]的話,就不會去查詢是否存在當前線程的RunLoop,也就不會去加載,更不會建立。

SQLite中經常使用的SQL語句

  • 建立表:creat table 表名 (字段名 字段數據類型 是否爲主鍵, 字段名 字段數據類型, 字段名 字段數據類型...);
  • 增: insert into 表名 (字段1, 字段2...) values (值1, 值2...);
  • : delete from 表名 where 字段 = 值;

XIB與Storyboards的優缺點

優勢:

  • XIB:在編譯前就提供了可視化界面,能夠直接拖控件,也能夠直接給控件添加約束,更直觀一些,並且類文件中就少了建立控件的代碼,確實簡化很多,一般每一個XIB對應一個類。
  • Storyboard:在編譯前提供了可視化界面,可拖控件,可加約束,在開發時比較直觀,並且一個storyboard能夠有不少的界面,每一個界面對應一個類文件,經過storybard,能夠直觀地看出整個App的結構。

缺點:

  • XIB:需求變更時,須要修改XIB很大,有時候甚至須要從新添加約束,致使開發週期變長。XIB載入相比純代碼天然要慢一些。對於比較複雜邏輯控制不一樣狀態下顯示不一樣內容時,使用XIB是比較困難的。當多人團隊或者多團隊開發時,若是XIB文件被髮動,極易致使衝突,並且解決衝突相對要困難不少。
  • Storyboard:需求變更時,須要修改storyboard上對應的界面的約束,與XIB同樣可能要從新添加約束,或者添加約束會形成大量的衝突,尤爲是多團隊開發。對於複雜邏輯控制不一樣顯示內容時,比較困難。當多人團隊或者多團隊開發時,你們會同時修改一個storyboard,致使大量衝突,解決起來至關困難。

將字符串「2015-04-10」格式化日期轉爲NSDate類型

NSString *timeStr = @"2015-04-10"; NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; formatter.dateFormat = @"yyyy-MM-dd"; formatter.timeZone = [NSTimeZone defaultTimeZone]; NSDate *date = [formatter dateFromString:timeStr]; // 2015-04-09 16:00:00 +0000 NSLog(@"%@", date);

隊列和多線程的使用原理

在iOS中隊列分爲如下幾種:

  • 串行隊列:隊列中的任務只會順序執行;
    dispatch_queue_t q = dispatch_queue_create("...", DISPATCH_QUEUE_SERIAL);
  • 並行隊列: 隊列中的任務一般會併發執行;
    dispatch_queue_t q = dispatch_queue_create("......",DISPATCH_QUEUE_CONCURRENT);
  • 全局隊列:是系統的,直接拿過來(GET)用就能夠;與並行隊列相似;
    dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
  • 主隊列:每個應用程序對應惟一主隊列,直接GET便可;在多線程開發中,使用主隊列更新UI;
    dispatch_queue_t q = dispatch_get_main_queue();
  • 更多細節見下圖:

    來自簡書

內存的使用和優化的注意事項

  • 重用問題:如UITableViewCells、UICollectionViewCells、UITableViewHeaderFooterViews設置正確的reuseIdentifier,充分重用;
  • 儘可能把views設置爲不透明:當opque爲NO的時候,圖層的半透明取決於圖片和其自己合成的圖層爲結果,可提升性能;
  • 不要使用太複雜的XIB/Storyboard:載入時就會將XIB/storyboard須要的全部資源,包括圖片所有載入內存,即便將來好久纔會使用。那些相比純代碼寫的延遲加載,性能及內存就差了不少;
  • 選擇正確的數據結構:學會選擇對業務場景最合適的數組結構是寫出高效代碼的基礎。好比,數組: 有序的一組值。使用索引來查詢很快,使用值查詢很慢,插入/刪除很慢。字典: 存儲鍵值對,用鍵來查找比較快。集合: 無序的一組值,用值來查找很快,插入/刪除很快。
    gzip/zip壓縮:當從服務端下載相關附件時,能夠經過gzip/zip壓縮後再下載,使得內存更小,下載速度也更快。
  • 延遲加載:對於不該該使用的數據,使用延遲加載方式。對於不須要立刻顯示的視圖,使用延遲加載方式。好比,網絡請求失敗時顯示的提示界面,可能一直都不會使用到,所以應該使用延遲加載。
  • 數據緩存:對於cell的行高要緩存起來,使得reload數據時,效率也極高。而對於那些網絡數據,不須要每次都請求的,應該緩存起來,能夠寫入數據庫,也能夠經過plist文件存儲。
  • 處理內存警告:通常在基類統一處理內存警告,將相關不用資源當即釋放掉
    重用大開銷對象:一些objects的初始化很慢,好比NSDateFormatterNSCalendar,但又不可避免地須要使用它們。一般是做爲屬性存儲起來,防止反覆建立。
  • 避免反覆處理數據:許多應用須要從服務器加載功能所需的常爲JSON或者XML格式的數據。在服務器端和客戶端使用相同的數據結構很重要;
  • 使用Autorelease Pool:在某些循環建立臨時變量處理數據時,自動釋放池以保證能及時釋放內存;
  • 正確選擇圖片加載方式:詳情閱讀細讀UIImage加載方式

UIViewController的完整生命週期

-[ViewController initWithNibName:bundle:]; -[ViewController init]; -[ViewController loadView]; -[ViewController viewDidLoad]; -[ViewController viewWillDisappear:]; -[ViewController viewWillAppear:]; -[ViewController viewDidAppear:]; -[ViewController viewDidDisappear:];

UIImageView添加圓角

  • 最直接的方法就是使用以下屬性設置
    imgView.layer.cornerRadius = 10; // 這一行代碼是很消耗性能的 imgView.clipsToBounds = YES;
    **這是離屏渲染(off-screen-rendering),消耗性能的**
  • 給UIImage添加生成圓角圖片的擴展API:這是on-screen-rendering

    - (UIImage *)imageWithCornerRadius:(CGFloat)radius { CGRect rect = (CGRect){0.f, 0.f, self.size}; UIGraphicsBeginImageContextWithOptions(self.size, NO, UIScreen.mainScreen.scale); CGContextAddPath(UIGraphicsGetCurrentContext(), [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:radius].CGPath); CGContextClip(UIGraphicsGetCurrentContext()); [self drawInRect:rect]; UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return image; }

很是感謝您的閱讀,最近開通了微信公衆號,爲您呈現更加精彩的技術文章,公衆號ID:iOSDevSkills,期待您的加入!謝謝!



此文爲轉載/Jack_lin(簡書做者)的iOS面試必看的最全梳理 原文連接:http://www.jianshu.com/p/5d2163640e26 著做權歸做者全部,轉載請聯繫做者得到受權,並標註「簡書做者」。
相關文章
相關標籤/搜索