序言
目前形勢(shì)呼股,參加到iOS隊(duì)伍的人是越來(lái)越多,甚至已經(jīng)供過(guò)于求了画恰。今年彭谁,找過(guò)工作的人可能會(huì)更深刻地體會(huì)到今年的就業(yè)形勢(shì)不容樂(lè)觀,加之允扇,培訓(xùn)機(jī)構(gòu)一火車(chē)的向用人單位輸送iOS開(kāi)發(fā)人員缠局,打破了生態(tài)圈的動(dòng)態(tài)平衡。以我以往的經(jīng)驗(yàn)及在公司原有的技術(shù)考润,為iOS應(yīng)聘者梳理一下面試題狭园,希望能祝一臂之力!
一糊治、OC的理解與特性
- OC作為一門(mén)面向?qū)ο蟮恼Z(yǔ)言唱矛,自然具有面向?qū)ο蟮奶匦裕悍庋b、繼承井辜、多態(tài)绎谦。它具有靜態(tài)語(yǔ)言的特征(如C++),又有動(dòng)態(tài)語(yǔ)言的效率(動(dòng)態(tài)綁定粥脚、動(dòng)態(tài)加載等)窃肠。總體來(lái)講刷允,OC確實(shí)是一門(mén)不錯(cuò)的編程語(yǔ)言铭拧。
- OC具有相當(dāng)多的動(dòng)態(tài)特性赃蛛,表現(xiàn)為三方面:動(dòng)態(tài)類(lèi)型(Dynamic typing)、動(dòng)態(tài)綁定(Dynamic binding)和動(dòng)態(tài)加載(Dynamic loading)搀菩。動(dòng)態(tài)——必須在運(yùn)行時(shí)(run time)才會(huì)做的一些事情呕臂。
1.動(dòng)態(tài)類(lèi)型
- 即運(yùn)行時(shí)再?zèng)Q定對(duì)象的類(lèi)型,這種動(dòng)態(tài)特征在日常的應(yīng)用中非常常見(jiàn)肪跋,簡(jiǎn)單來(lái)說(shuō)就是id類(lèi)型歧蒋。事實(shí)上,由于靜態(tài)類(lèi)型的固定性和可預(yù)知性州既,從而使用的更加廣泛谜洽。靜態(tài)類(lèi)型是強(qiáng)類(lèi)型,而動(dòng)態(tài)類(lèi)型屬于弱類(lèi)型吴叶,運(yùn)行時(shí)決定接受者阐虚。
2.動(dòng)態(tài)綁定
基于動(dòng)態(tài)類(lèi)型,在某個(gè)實(shí)例對(duì)象被確定之后蚌卤,其類(lèi)型便被確定了实束,該對(duì)象對(duì)應(yīng)屬性和響應(yīng)消息也被完全確定。
3.動(dòng)態(tài)加載
根據(jù)需求加載所需要的資源逊彭,最基本就是不同機(jī)型的適配咸灿,例如,在retina設(shè)備上加載@2x的圖片侮叮,而在老一些的普通蘋(píng)果設(shè)備上加載原圖避矢,讓程序在運(yùn)行時(shí)添加代碼模塊以及其他資源,用戶可根據(jù)需要加載一些可執(zhí)行代碼和資源囊榜,而不是在啟動(dòng)時(shí)就加載所有組件审胸,可執(zhí)行代碼可以含有和程序運(yùn)行時(shí)整合的新類(lèi)。
二卸勺、簡(jiǎn)述內(nèi)存管理基本原則
- 以前:OC內(nèi)存管理遵循“誰(shuí)創(chuàng)建歹嘹,誰(shuí)釋放,誰(shuí)引用孔庭,誰(shuí)管理”的機(jī)制,當(dāng)創(chuàng)建或引用一個(gè)對(duì)象的時(shí)候材蛛,需要向它發(fā)送alloc圆到、copy、retain消息卑吭,當(dāng)釋放該對(duì)象時(shí)需要發(fā)送release消息芽淡,當(dāng)對(duì)象引用計(jì)數(shù)為0時(shí),系統(tǒng)將釋放該對(duì)象豆赏,這是OC的手動(dòng)管理機(jī)制(MRC)挣菲。
- 目前:iOS 5.0 之后引用自動(dòng)管理機(jī)制——自動(dòng)引用計(jì)數(shù)(ARC)富稻,管理機(jī)制與手動(dòng)機(jī)制一樣,只是不再需要調(diào)用
retain
白胀、release
椭赋、autorelease
;它引用strong
和weak
關(guān)鍵字或杠,strong
修飾的指針變量指向?qū)ο髸r(shí)當(dāng)指針指向新值或者指針不復(fù)存在哪怔,相關(guān)聯(lián)的對(duì)象就會(huì)自動(dòng)釋放,而weak
修飾的指針變量指向?qū)ο笙蚯溃?dāng)對(duì)象的擁有者指向新值或者不存在時(shí)weak修飾的指針會(huì)自動(dòng)置為nil认境。 - 如果使用
alloc
、copy(mutablecopy)
或者retain
一個(gè)對(duì)象時(shí),你就有義務(wù),向它發(fā)送一條release
或者autorelease
消息挟鸠,這個(gè)對(duì)象并不會(huì)立即銷(xiāo)毀, 而是將這個(gè)對(duì)象放入了自動(dòng)釋放池,待池子釋放時(shí),它會(huì)向池中每一個(gè)對(duì)象發(fā)送 一條release
消息,以此來(lái)釋放對(duì)象叉信。 - 向一個(gè)對(duì)象發(fā)送
release
消息,并不意味著這個(gè)對(duì)象被銷(xiāo)毀了,而是當(dāng)這個(gè)對(duì)象的引用計(jì)數(shù)為0時(shí),系統(tǒng)才會(huì)調(diào)用dealloc
方法,釋放該對(duì)象和對(duì)象本身它所擁有的實(shí)例。
自動(dòng)釋放池工作原理
- 自動(dòng)釋放池是
NSAutorelease
類(lèi)的一個(gè)實(shí)例,當(dāng)向一個(gè)對(duì)象發(fā)送autorelease
消息時(shí),該對(duì)象會(huì)自動(dòng)入池,待池銷(xiāo)毀時(shí),將會(huì)向池中所有對(duì)象發(fā)送一條release
消息,釋放對(duì)象艘希。 -
[pool release]
硼身、[pool drain]
表示的是池本身不會(huì)銷(xiāo)毀,而是池子中的臨時(shí)對(duì)象都被發(fā)送release
,從而將對(duì)象銷(xiāo)毀。
Objective-C中可修改和不可以修改類(lèi)型
- 可修改不可修改的集合類(lèi)枢冤,就是可動(dòng)態(tài)添加修改和不可動(dòng)態(tài)添加修改鸠姨。
- 比如
NSArray
和NSMutableArray
,前者在初始化后的內(nèi)存控件就是固定不可變的,后者可以添加等淹真,可以動(dòng)態(tài)申請(qǐng)新的內(nèi)存空間
當(dāng)我們調(diào)用一個(gè)靜態(tài)方法時(shí),需要對(duì)對(duì)象進(jìn)行 **release **嗎?
- 不需要,靜態(tài)方法(類(lèi)方法)創(chuàng)建一個(gè)對(duì)象時(shí),對(duì)象已被放入自動(dòng)釋放池讶迁。在自動(dòng)釋放池被釋放時(shí),很有可能被銷(xiāo)毀。
當(dāng)我們釋放我們的對(duì)象時(shí),為什么需要調(diào)用[super dealloc]方法,它的位置又是如何的呢?
- 因?yàn)樽宇?lèi)的某些實(shí)例是繼承自父類(lèi)的,因此需要調(diào)用
[super dealloc]
方法, 來(lái)釋放父類(lèi)擁有的實(shí)例,其實(shí)也就是子類(lèi)本身的核蘸。一般來(lái)說(shuō)我們優(yōu)先釋放子類(lèi)擁 有的實(shí)例,最后釋放父類(lèi)所擁有的實(shí)例巍糯。
static、self客扎、super關(guān)鍵字的作用
- 函數(shù)體內(nèi)static變量的作用范圍為該函數(shù)體祟峦,不同于auto變量,該變量的內(nèi)存只被分配一次徙鱼,因此其值在下次調(diào)用時(shí)仍維持上次的值.
- 在模塊內(nèi)的 static 全局變量可以被模塊內(nèi)所用函數(shù)訪問(wèn)宅楞,但不能被模塊外其它函數(shù)訪問(wèn).
- 在模塊內(nèi)的static函數(shù)只可被這一模塊內(nèi)的其它函數(shù)調(diào)用,這個(gè)函數(shù)的使用范圍被限制在聲明袱吆。
- 在類(lèi)中的static成員變量屬于整個(gè)類(lèi)所擁有厌衙,對(duì)類(lèi)的所有對(duì)象只有一份拷貝.
- self:當(dāng)前消息的接收者。
- super:向父類(lèi)發(fā)送消息绞绒。
解釋self = [super init]方法
- 容錯(cuò)處理,當(dāng)父類(lèi)初始化失敗,會(huì)返回一個(gè)nil,表示初始化失敗婶希。由于繼承的關(guān)系,子類(lèi)是需要擁有父類(lèi)的實(shí)例和行為,因此,我們必須先初始化父類(lèi),然后再初始化子類(lèi)
在某個(gè)方法中 self.name = _name,name = _name 它 們有區(qū)別嗎,為什么?
- 前者是存在內(nèi)存管理的setter方法賦值,它會(huì)對(duì)_name對(duì)象進(jìn)行保留或者拷貝操作
- 后者是普通賦值
- 一般來(lái)說(shuō)蓬衡,在對(duì)象的方法里成員變量和方法都是可以訪問(wèn)的喻杈,我們通常會(huì)重寫(xiě)Setter方法來(lái)執(zhí)行某些額外的工作彤枢。比如說(shuō),外部傳一個(gè)模型過(guò)來(lái)筒饰,那么我會(huì)直接重寫(xiě)Setter方法缴啡,當(dāng)模型傳過(guò)來(lái)時(shí),也就是意味著數(shù)據(jù)發(fā)生了變化龄砰,那么視圖也需要更新顯示盟猖,則在賦值新模型的同時(shí)也去刷新UI。
對(duì)象可以被copy的條件
- 只有實(shí)現(xiàn)了
NSCopying
和NSMutableCopying
協(xié)議的類(lèi)的對(duì)象才能被拷貝,分為不可變拷貝和可變拷貝,具體區(qū)別戳這换棚; -
NSCopying
協(xié)議方法為:
- (id)copyWithZone:(NSZone *)zone {
MyObject *copy = [[[self class] allocWithZone: zone] init];
copy.username = [self.username copyWithZone:zone];
return copy;
}
定義屬性時(shí),什么時(shí)候用 assign式镐、retain、**copy **以及它們的之間的區(qū)別
-
assign
:普通賦值,一般常用于基本數(shù)據(jù)類(lèi)型,常見(jiàn)委托設(shè)計(jì)模式, 以此來(lái)防止循環(huán)引用固蚤。(我們稱之為弱引用). -
retain
:保留計(jì)數(shù),獲得到了對(duì)象的所有權(quán),引用計(jì)數(shù)在原有基礎(chǔ)上加1. -
copy
:一般認(rèn)為,是在內(nèi)存中重新開(kāi)辟了一個(gè)新的內(nèi)存空間,用來(lái) 存儲(chǔ)新的對(duì)象,和原來(lái)的對(duì)象是兩個(gè)不同的地址,引用計(jì)數(shù)分別為1娘汞。但是當(dāng)copy
對(duì)象為不可變對(duì)象時(shí),那么copy
的作用相當(dāng)于retain
。因?yàn)?這樣可以節(jié)約內(nèi)存空間
堆和棧的區(qū)別
-
棧區(qū)(stack)
由編譯器自動(dòng)分配釋放 ,存放方法(函數(shù))的參數(shù)值, 局部變量的值等夕玩,棧是向低地址擴(kuò)展的數(shù)據(jù)結(jié)構(gòu)你弦,是一塊連續(xù)的內(nèi)存的區(qū)域。即棧頂?shù)牡刂泛蜅5淖畲笕萘渴窍到y(tǒng)預(yù)先規(guī)定好的燎孟。 -
堆區(qū)(heap)
一般由程序員分配釋放, 若程序員不釋放,程序結(jié)束時(shí)由OS回收禽作,向高地址擴(kuò)展的數(shù)據(jù)結(jié)構(gòu),是不連續(xù)的內(nèi)存區(qū)域揩页,從而堆獲得的空間比較靈活旷偿。 -
碎片問(wèn)題
:對(duì)于堆來(lái)講,頻繁的new/delete
勢(shì)必會(huì)造成內(nèi)存空間的不連續(xù)爆侣,從而造成大量的碎片萍程,使程序效率降低。對(duì)于棧來(lái)講兔仰,則不會(huì)存在這個(gè)問(wèn)題茫负,因?yàn)闂J窍冗M(jìn)后出的隊(duì)列,他們是如此的一一對(duì)應(yīng)乎赴,以至于永遠(yuǎn)都不可能有一個(gè)內(nèi)存塊從棧中間彈出. -
分配方式
:堆都是動(dòng)態(tài)分配的忍法,沒(méi)有靜態(tài)分配的堆。棧有2種分配方式:靜態(tài)分配和動(dòng)態(tài)分配榕吼。靜態(tài)分配是編譯器完成的饿序,比如局部變量的分配。動(dòng)態(tài)分配由alloca函數(shù)進(jìn)行分配友题,但是棧的動(dòng)態(tài)分配和堆是不同的,他的動(dòng)態(tài)分配是由編譯器進(jìn)行釋放戴质,無(wú)需我們手工實(shí)現(xiàn)度宦。 -
分配效率
:棧是機(jī)器系統(tǒng)提供的數(shù)據(jù)結(jié)構(gòu)踢匣,計(jì)算機(jī)會(huì)在底層對(duì)棧提供支持:分配專(zhuān)門(mén)的寄存器存放棧的地址,壓棧出棧都有專(zhuān)門(mén)的指令執(zhí)行戈抄,這就決定了棧的效率比較高离唬。堆則是C/C++函數(shù)庫(kù)提供的,它的機(jī)制是很復(fù)雜的划鸽。 -
全局區(qū)(靜態(tài)區(qū))(static)
,全局變量和靜態(tài)變量的存儲(chǔ)是放在一塊 的,初始化的全局變量和靜態(tài)變量在一塊區(qū)域, 未初始化的全局變量和未初始化的靜態(tài)變量在相鄰的另一塊區(qū)域输莺。程序結(jié)束后有系統(tǒng)釋放。 -
文字常量區(qū)
:常量字符串就是放在這里的裸诽。程序結(jié)束后由系統(tǒng)釋放嫂用。 -
程序代碼區(qū)
:存放函數(shù)體的二進(jìn)制代碼
內(nèi)存的使用和優(yōu)化的注意事項(xiàng)
- 重用問(wèn)題:如UITableViewCells、UICollectionViewCells丈冬、UITableViewHeaderFooterViews設(shè)置正確的reuseIdentifier嘱函,充分重用;
- 盡量把views設(shè)置為不透明:當(dāng)opque為NO的時(shí)候埂蕊,圖層的半透明取決于圖片和其本身合成的圖層為結(jié)果往弓,可提高性能;
- 不要使用太復(fù)雜的XIB/Storyboard:載入時(shí)就會(huì)將XIB/storyboard需要的所有資源蓄氧,包括圖片全部載入內(nèi)存函似,即使未來(lái)很久才會(huì)使用。那些相比純代碼寫(xiě)的延遲加載喉童,性能及內(nèi)存就差了很多撇寞;
- 選擇正確的數(shù)據(jù)結(jié)構(gòu):學(xué)會(huì)選擇對(duì)業(yè)務(wù)場(chǎng)景最合適的數(shù)組結(jié)構(gòu)是寫(xiě)出高效代碼的基礎(chǔ)。比如泄朴,數(shù)組: 有序的一組值重抖。使用索引來(lái)查詢很快,使用值查詢很慢祖灰,插入/刪除很慢钟沛。字典: 存儲(chǔ)鍵值對(duì),用鍵來(lái)查找比較快局扶。集合: 無(wú)序的一組值恨统,用值來(lái)查找很快,插入/刪除很快三妈。gzip/zip壓縮:當(dāng)從服務(wù)端下載相關(guān)附件時(shí)畜埋,可以通過(guò)gzip/zip壓縮后再下載,使得內(nèi)存更小畴蒲,下載速度也更快悠鞍。
- 延遲加載:對(duì)于不應(yīng)該使用的數(shù)據(jù),使用延遲加載方式模燥。對(duì)于不需要馬上顯示的視圖咖祭,使用延遲加載方式掩宜。比如,網(wǎng)絡(luò)請(qǐng)求失敗時(shí)顯示的提示界面么翰,可能一直都不會(huì)使用到牺汤,因此應(yīng)該使用延遲加載。
- 數(shù)據(jù)緩存:對(duì)于cell的行高要緩存起來(lái)浩嫌,使得reload數(shù)據(jù)時(shí)檐迟,效率也極高。而對(duì)于那些網(wǎng)絡(luò)數(shù)據(jù)码耐,不需要每次都請(qǐng)求的追迟,應(yīng)該緩存起來(lái),可以寫(xiě)入數(shù)據(jù)庫(kù)伐坏,也可以通過(guò)plist文件存儲(chǔ)怔匣。
-
處理內(nèi)存警告:一般在基類(lèi)統(tǒng)一處理內(nèi)存警告,將相關(guān)不用資源立即釋放掉重用大開(kāi)銷(xiāo)對(duì)象:一些objects的初始化很慢桦沉,比如NSDateFormatter
和NSCalendar
每瞒,但又不可避免地需要使用它們。通常是作為屬性存儲(chǔ)起來(lái)纯露,防止反復(fù)創(chuàng)建剿骨。 - 避免反復(fù)處理數(shù)據(jù):許多應(yīng)用需要從服務(wù)器加載功能所需的常為JSON或者XML格式的數(shù)據(jù)。在服務(wù)器端和客戶端使用相同的數(shù)據(jù)結(jié)構(gòu)很重要;
- 使用Autorelease Pool:在某些循環(huán)創(chuàng)建臨時(shí)變量處理數(shù)據(jù)時(shí)埠褪,自動(dòng)釋放池以保證能及時(shí)釋放內(nèi)存;
- 正確選擇圖片加載方式:詳情閱讀細(xì)讀UIImage加載方式
其他注意事項(xiàng)
- 如果一個(gè)對(duì)象有一個(gè)_strong類(lèi)型的指針指向著浓利,找個(gè)對(duì)象就不會(huì)被釋放。如果一個(gè)指針指向超出了它的作用域钞速,就會(huì)被指向nil贷掖。如果一個(gè)指針被指向nil,那么它原來(lái)指向的對(duì)象就被釋放了渴语。當(dāng)一個(gè)視圖控制器被釋放時(shí)苹威,它內(nèi)部的全局指針會(huì)被指向nil。用法“:不管全局變量還是局部變量用_strong描述就行驾凶。
局部變量:出了作用域牙甫,指針會(huì)被置為nil。
方法內(nèi)部創(chuàng)建對(duì)象调违,外部使用需要添加_autorelease;
連線的時(shí)候窟哺,用_weak描述。
代理使用unsafe_unretained就相當(dāng)于assign技肩;
block中為了避免循環(huán)引用問(wèn)題且轨,使用_weak描述;
聲明屬性時(shí),不要以new
開(kāi)頭旋奢。如果非要以new
開(kāi)頭命名屬性的名字阿蝶,需要自己定制get方法名,如
@property(getter=theString) NSString * newString;
- 如果使用自動(dòng)釋放池黄绩,用
@autoreleasepool{}
- ARC只能管理Foundation框架的變量,如果程序中把Foundation中的變量強(qiáng)制換成COre Foundation中的變量需要交換管理權(quán)玷过;
- 在非ARC工程中采用ARC去編譯某些類(lèi):
-fobjc-arc
爽丹。 - 在ARC下的工程采用非ARC去編譯某些類(lèi):
-fno-fobjc-arc
。
三辛蚊、如何理解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ì)模式础浮。
四、如何理解MVVM設(shè)計(jì)模式
- ViewModel層奠骄,就是View和Model層的粘合劑豆同,他是一個(gè)放置用戶輸入驗(yàn)證邏輯,視圖顯示邏輯含鳞,發(fā)起網(wǎng)絡(luò)請(qǐng)求和其他各種各樣的代碼的極好的地方影锈。說(shuō)白了,就是把原來(lái)ViewController層的業(yè)務(wù)邏輯和頁(yè)面邏輯等剝離出來(lái)放到ViewModel層。
- View層鸭廷,就是ViewController層枣抱,他的任務(wù)就是從ViewModel層獲取數(shù)據(jù),然后顯示辆床。
五佳晶、**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)存管理的難度轿秧。
六、協(xié)議的基本概念和協(xié)議中方法默認(rèn)為什么類(lèi)型
OC中的協(xié)議是一個(gè)方法列表,且多少有點(diǎn)相關(guān)咨堤。它的特點(diǎn)是可以被任何類(lèi)使用(實(shí)現(xiàn)),但它并不是類(lèi)(這里我們需要注意),自身不會(huì)實(shí)現(xiàn)這樣方法, 而是又其他人來(lái)實(shí)現(xiàn)協(xié)議經(jīng)常用來(lái)實(shí)現(xiàn)委托對(duì)象(委托設(shè)計(jì)模式)菇篡。如果一個(gè)類(lèi)采用了一個(gè)協(xié)議,那么它必須實(shí)現(xiàn)協(xié)議中必須需要實(shí)現(xiàn)的方法,在協(xié)議中的方法默認(rèn)是必須實(shí)現(xiàn)(@required),添加關(guān)鍵字@optional,表明一旦采用該協(xié)議,這些“可選”的方法是可以選擇不實(shí)現(xiàn)的。
七一喘、簡(jiǎn)述類(lèi)目 category 優(yōu)點(diǎn)和缺點(diǎn)
優(yōu)點(diǎn):
- 不需要通過(guò)增加子類(lèi)而增加現(xiàn)有類(lèi)的行為(方法),且類(lèi)目中的方法與原始類(lèi)方法基本沒(méi)有區(qū)別;
- 通過(guò)類(lèi)目可以將龐大一個(gè)類(lèi)的方法進(jìn)行劃分,從而便于代碼的日后的維護(hù)驱还、更新以及提高代碼的閱讀性;
缺點(diǎn): - 無(wú)法向類(lèi)目添加實(shí)例變量,如果需要添加實(shí)例變量,只能通過(guò)定義子類(lèi)的方式;
- 類(lèi)目中的方法與原始類(lèi)以及父類(lèi)方法相比具有更高優(yōu)先級(jí),如果覆蓋父類(lèi)的方法,可能導(dǎo)致super消息的斷裂。因此,最好不要覆蓋原始類(lèi)中的方法凸克。
八议蟆、類(lèi)別的作用
- 給系統(tǒng)原有類(lèi)添加方法,不能擴(kuò)展屬性。如果類(lèi)別中方法的名字跟系統(tǒng)的方法名一樣萎战,在調(diào)用的時(shí)候類(lèi)別中的方法優(yōu)先級(jí)更高咪鲜;
- 分散類(lèi)的實(shí)現(xiàn),如:
+ (NSIndexPath *)indexPathForRow:(NSInteger)rowinSection:
(NSInteger)section
原本屬于NSIndexPath的方法,但因?yàn)檫@個(gè)方法經(jīng)常使用的表的時(shí)候調(diào)用,跟表的關(guān)系特別密切,因此把這個(gè)方法一類(lèi)別的形式,聲明在UITableView.中撞鹉。
- 聲明私有方法疟丙,某一個(gè)方法只實(shí)現(xiàn),不聲明鸟雏,相當(dāng)于私有方法享郊。
- 類(lèi)別不能聲明變量,類(lèi)別不可以直接添加屬性孝鹊。
property
描述setter方法炊琉,就不會(huì)報(bào)錯(cuò)。
九又活、循環(huán)引用的產(chǎn)生原因苔咪,以及解決方法
- 產(chǎn)生原因:如下圖所示,對(duì)象A和對(duì)象B相互引用了對(duì)方作為自己的成員變量柳骄,只有自己銷(xiāo)毀的時(shí)候才能將成員變量的引用計(jì)數(shù)減1团赏。對(duì)象A的銷(xiāo)毀依賴于對(duì)象B的銷(xiāo)毀,同時(shí)對(duì)象B銷(xiāo)毀也依賴與對(duì)象A的銷(xiāo)毀耐薯,從而形成循環(huán)引用舔清,此時(shí)丝里,即使外界沒(méi)有任何指針訪問(wèn)它,它也無(wú)法釋放
多個(gè)對(duì)象間依然會(huì)存在循環(huán)引用問(wèn)題体谒,形成一個(gè)環(huán)杯聚,在編程中,形成的環(huán)越大越不容易察覺(jué)抒痒,如下圖所示:
解決方法
- 事先知道存在循環(huán)引用的地方幌绍,在合理的位置主動(dòng)斷開(kāi)一個(gè)引用,是對(duì)象回收故响;
- 使用弱引用的方法纷捞。
十、鍵路徑(keyPath)被去、鍵值編碼(KVC)、鍵值觀察(KVO)
鍵路徑
- 在一個(gè)給定的實(shí)體中奖唯,同一個(gè)屬性的所有值具有相同的數(shù)據(jù)類(lèi)型惨缆。
- 鍵值編碼技術(shù)用于這樣的查找——它是一種間接訪問(wèn)對(duì)象屬性的機(jī)制。
鍵路徑是一個(gè)由用點(diǎn)做分隔符的鍵組成的字符串丰捷,用于指定一個(gè)連接在一起的對(duì)象性質(zhì)序列坯墨。第一個(gè)鍵的性質(zhì)是由先前的性質(zhì)決定的,接下來(lái)每個(gè)鍵的值也是相對(duì)于其前面的性質(zhì)病往。 - 鍵路徑使您可以以獨(dú)立于模型實(shí)現(xiàn)的方式指定相關(guān)對(duì)象的性質(zhì)捣染。通過(guò)鍵路徑,您可以指定對(duì)象圖中的一個(gè)任意深度的路徑停巷,使其指定相關(guān)對(duì)象的特定屬性耍攘。
鍵值編碼 KVC
- 鍵值編碼是一種間接訪問(wèn)對(duì)象的屬性使用字符串來(lái)標(biāo)識(shí)屬性,而不是通過(guò)調(diào)用存取方法畔勤,直接或通過(guò)實(shí)例變量訪問(wèn)的機(jī)制蕾各,非對(duì)象類(lèi)型的變量將被自動(dòng)封裝或者解封成對(duì)象,很多情況下會(huì)簡(jiǎn)化程序代碼庆揪;
- KVC 的缺點(diǎn):一旦使用 KVC 你的編譯器無(wú)法檢查出錯(cuò)誤式曲,既不會(huì)對(duì)設(shè)置的鍵鍵路徑進(jìn)行錯(cuò)誤檢查,且執(zhí)行效率要低于合成存儲(chǔ)器方法和自定義的 setter 和 getter 方法缸榛。因?yàn)槭褂?KVC 鍵值編碼吝羞,他必須先解析字符串,然后在設(shè)置或者訪問(wèn)對(duì)象的實(shí)力變量内颗。
Demo
比如我自定義的一個(gè)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];
}
}
對(duì)于系統(tǒng)是根據(jù)keypath去取的到相應(yīng)的值發(fā)生改變钧排,理論上來(lái)說(shuō)是和kvc機(jī)制的道理是一樣的。
KVC機(jī)制通過(guò)key
找到value
的原理
- 當(dāng)通過(guò)KVC調(diào)用對(duì)象時(shí)均澳,比如:
[self valueForKey:@”someKey”]
時(shí)卖氨,程序會(huì)自動(dòng)試圖通過(guò)下面幾種不同的方式解析這個(gè)調(diào)用会烙。 - 首先查找對(duì)象是否帶有
someKey
這個(gè)方法,如果沒(méi)找到筒捺,會(huì)繼續(xù)查找對(duì)象是否帶有someKey這個(gè)實(shí)例變量(iVar
)柏腻,如果還沒(méi)有找到,程序會(huì)繼續(xù)試圖調(diào)用-(id) valueForUndefinedKey:
這個(gè)方法系吭。如果這個(gè)方法還是沒(méi)有被實(shí)現(xiàn)的話五嫂,程序會(huì)拋出一個(gè)NSUndefinedKeyException
異常錯(cuò)誤。 - 補(bǔ)充:KVC查找方法的時(shí)候肯尺,不僅僅會(huì)查找someKey這個(gè)方法沃缘,還會(huì)查找getsomeKey這個(gè)方法,前面加一個(gè)get则吟,或者_(dá)someKey以_getsomeKey這幾種形式槐臀。同時(shí),查找實(shí)例變量的時(shí)候也會(huì)不僅僅查找someKey這個(gè)變量氓仲,也會(huì)查找_someKey這個(gè)變量是否存在水慨。
- 設(shè)計(jì)
valueForUndefinedKey:
方法的主要目的是當(dāng)你使用-(id)valueForKey
方法從對(duì)象中請(qǐng)求值時(shí),對(duì)象能夠在錯(cuò)誤發(fā)生前敬扛,有最后的機(jī)會(huì)響應(yīng)這個(gè)請(qǐng)求晰洒。
在 **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è)類(lèi)中的屬性,并且屬性名都是通過(guò)NSString來(lái)查找急侥,編譯器不會(huì)檢錯(cuò)和補(bǔ)全砌滞,全部取決于自己。
十一坏怪、代理的作用
- 代理又叫委托布持,是一種設(shè)計(jì)模式,代理是對(duì)象與對(duì)象之間的通信交互陕悬,代理解除了對(duì)象之間的耦合性题暖。
- 改變或傳遞控制鏈。允許一個(gè)類(lèi)在某些特定時(shí)刻通知到其他類(lèi)捉超,而不需要獲取到那些類(lèi)的指針胧卤。可以減少框架復(fù)雜度拼岳。
- 另外一點(diǎn)枝誊,代理可以理解為java中的回調(diào)監(jiān)聽(tīng)機(jī)制的一種類(lèi)似。
- 代理的屬性常是
assign
的原因:防止循環(huán)引用,以至對(duì)象無(wú)法得到正確的釋放惜纸。
十二叶撒、NSNotification绝骚、Block、Delegate 和 KVO 的區(qū)別
- 代理是一種回調(diào)機(jī)制祠够,且是一對(duì)一的關(guān)系压汪,通知是一對(duì)多的關(guān)系,一個(gè)對(duì)向所有的觀察者提供變更通知古瓤;
- 效率:Delegate比NSNOtification高止剖;
- Delegate和Block一般是一對(duì)一的通信;
- Delegate需要定義協(xié)議方法落君,代理對(duì)象實(shí)現(xiàn)協(xié)議方法穿香,并且需要建立代理關(guān)系才可以實(shí)現(xiàn)通信;
- Block:Block更加簡(jiǎn)潔绎速,不需要定義繁瑣的協(xié)議方法皮获,但通信事件比較多的話,建議使用Delegate纹冤;
十三洒宝、 對(duì)謂詞的認(rèn)識(shí)
- Cocoa 中提供了一個(gè)
NSPredicate
的類(lèi),該類(lèi)主要用于指定過(guò)濾器的條件, 每一個(gè)對(duì)象通過(guò)謂詞進(jìn)行篩選,判斷條件是否匹配。如果需要了解使用方法赵哲,請(qǐng)看謂詞的具體使用
十四、#include與#import的區(qū)別君丁、**#import **與@class 的區(qū)別
-
#include
和#import
其效果相同,都是查詢類(lèi)中定義的行為(方法); -
#import
不會(huì)引起交叉編譯,確保頭文件只會(huì)被導(dǎo)入一次枫夺; -
@class
的表明,只定 義了類(lèi)的名稱,而具體類(lèi)的行為是未知的,一般用于.h 文件; -
@class
比#import
編譯效率更高绘闷。 - 此外
@class
和#import
的主要區(qū)別在于解決引用死鎖的問(wèn)題橡庞。
十五、@public印蔗、@protected扒最、@private 它們的含義與作用
-
@public
:對(duì)象的實(shí)例變量的作用域在任意地方都可以被訪問(wèn) ; -
@protected
:對(duì)象的實(shí)例變量作用域在本類(lèi)和子類(lèi)都可以被訪問(wèn) ; -
@private
:實(shí)例變量的作用域只能在本類(lèi)(自身)中訪問(wèn) .
十六、isMemberOfClass 和 isKindOfClass 聯(lián)系與區(qū)別
- 聯(lián)系:兩者都能檢測(cè)一個(gè)對(duì)象是否是某個(gè)類(lèi)的成員
- 區(qū)別:
isKindOfClass
不僅用來(lái)確定一個(gè)對(duì)象是否是一個(gè)類(lèi)的成員,也可以用來(lái)確定一個(gè)對(duì)象是否派生自該類(lèi)的類(lèi)的成員 ,而isMemberOfClass
只能做到第一點(diǎn)华嘹。 - 舉例:如
ClassA
派 生 自NSObject
類(lèi) ,
ClassA *a = [ClassA alloc] init]
;,
[a isKindOfClass:[NSObject class]]
可以檢查出 a 是否是 NSObject派生類(lèi) 的成員,但 isMemberOfClass 做不到吧趣。
十七、**iOS **開(kāi)發(fā)中數(shù)據(jù)持久性有哪幾種?
數(shù)據(jù)存儲(chǔ)的核心都是寫(xiě)文件耙厚。
- 屬性列表:只有NSString强挫、NSArray、NSDictionary薛躬、NSData可writeToFile俯渤;存儲(chǔ)依舊是plist文件。plist文件可以存儲(chǔ)的7中數(shù)據(jù)類(lèi)型:array型宝、dictionary八匠、string絮爷、bool、data梨树、date坑夯、number。
- 對(duì)象序列化(對(duì)象歸檔):對(duì)象序列化通過(guò)序列化的形式劝萤,鍵值關(guān)系存儲(chǔ)到本地渊涝,轉(zhuǎn)化成二進(jìn)制流。通過(guò)runtime實(shí)現(xiàn)自動(dòng)化歸檔/解檔床嫌,請(qǐng)參考這個(gè)文章跨释。實(shí)現(xiàn)NSCoding協(xié)議必須實(shí)現(xiàn)的兩個(gè)方法:1.編碼(對(duì)象序列化):把不能直接存儲(chǔ)到plist文件中得到數(shù)據(jù),轉(zhuǎn)化為二進(jìn)制數(shù)據(jù)厌处,NSData鳖谈,可以存儲(chǔ)到本地;2.解碼(對(duì)象反序列化):把二進(jìn)制數(shù)據(jù)轉(zhuǎn)化為本來(lái)的類(lèi)型阔涉。
- SQLite 數(shù)據(jù)庫(kù):大量有規(guī)律的數(shù)據(jù)使用數(shù)據(jù)庫(kù)缆娃。
- CoreData :通過(guò)管理對(duì)象進(jìn)行增、刪瑰排、查贯要、改操作的。它不是一個(gè)數(shù)據(jù)庫(kù)椭住,不僅可以使用SQLite數(shù)據(jù)庫(kù)來(lái)保持?jǐn)?shù)據(jù)崇渗,也可以使用其他的方式來(lái)存儲(chǔ)數(shù)據(jù)。如:XML京郑。
CoreData的介紹:
- CoreData是面向?qū)ο蟮腁PI宅广,CoreData是iOS中非常重要的一項(xiàng)技術(shù),幾乎在所有編寫(xiě)的程序中些举,CoreData都作為數(shù)據(jù)存儲(chǔ)的基礎(chǔ)跟狱。
- CoreData是蘋(píng)果官方提供的一套框架,用來(lái)解決與對(duì)象聲明周期管理户魏、對(duì)象關(guān)系管理和持久化等方面相關(guān)的問(wèn)題驶臊。
- 大多數(shù)情況下,我們引用CoreData作為持久化數(shù)據(jù)的解決方案叼丑,并利用它作為持久化數(shù)據(jù)映射為內(nèi)存對(duì)象资铡。提供的是對(duì)象-關(guān)系映射功能,也就是說(shuō)幢码,CoreData可以將Objective-C對(duì)象轉(zhuǎn)換成數(shù)據(jù)笤休,保存到SQL中,然后將保存后的數(shù)據(jù)還原成OC對(duì)象症副。
CoreData的特征:
- 通過(guò)CoreData管理應(yīng)用程序的數(shù)據(jù)模型店雅,可以極大程度減少需要編寫(xiě)的代碼數(shù)量政基。
- 將對(duì)象數(shù)據(jù)存儲(chǔ)在SQLite數(shù)據(jù)庫(kù)已獲得性能優(yōu)化。
- 提供NSFetchResultsController類(lèi)用于管理表視圖的數(shù)據(jù)闹啦,即將Core Data的持久化存儲(chǔ)在表視圖中沮明,并對(duì)這些數(shù)據(jù)進(jìn)行管理:增刪查改。
- 管理undo/redo操縱窍奋;
- 檢查托管對(duì)象的屬性值是否正確荐健。
Core Data的6成員對(duì)象
- 1.NSManageObject:被管理的數(shù)據(jù)記錄Managed Object Model是描述應(yīng)用程序的數(shù)據(jù)模型,這個(gè)模型包含實(shí)體(Entity)琳袄、特性(Property)江场、讀取請(qǐng)求(Fetch Request)等。
- 2.NSManageObjectContext:管理對(duì)象上下文窖逗,持久性存儲(chǔ)模型對(duì)象址否,參與數(shù)據(jù)對(duì)象進(jìn)行各種操作的全過(guò)程,并監(jiān)測(cè)數(shù)據(jù)對(duì)象的變化碎紊,以提供對(duì)undo/redo的支持及更新綁定到數(shù)據(jù)的UI佑附。
- 3.NSPersistentStoreCoordinator:連接數(shù)據(jù)庫(kù)的Persistent Store Coordinator相當(dāng)于數(shù)據(jù)文件管理器,處理底層的對(duì)數(shù)據(jù)文件的讀取和寫(xiě)入仗考,一般我們與這個(gè)沒(méi)有交集音同。
- 4.NSManagedObjectModel:被管理的數(shù)據(jù)模型、數(shù)據(jù)結(jié)構(gòu)秃嗜。
- 5.NSFetchRequest:數(shù)據(jù)請(qǐng)求权均;
-6.NSEntityDescription:表格實(shí)體結(jié)構(gòu),還需知道.xcdatamodel文件編譯后為.momd或者.mom文件痪寻。
Core Data的功能
- 對(duì)于KVC和KVO完整且自動(dòng)化的支持螺句,除了為屬性整合KVO和KVC訪問(wèn)方法外虽惭,還整合了適當(dāng)?shù)募显L問(wèn)方法來(lái)處理多值關(guān)系橡类;
- 自動(dòng)驗(yàn)證屬性(property)值;
- 支持跟蹤修改和撤銷(xiāo)操作芽唇;
- 關(guān)系維護(hù)顾画,Core Data管理數(shù)據(jù)的關(guān)系傳播,包括維護(hù)對(duì)象間的一致性匆笤;
- 在內(nèi)存上和界面上分組研侣、過(guò)濾、組織數(shù)據(jù)炮捧;
- 自動(dòng)支持對(duì)象存儲(chǔ)在外部數(shù)據(jù)倉(cāng)庫(kù)的功能庶诡;
- 創(chuàng)建復(fù)雜請(qǐng)求:無(wú)需動(dòng)手寫(xiě)SQL語(yǔ)句,在獲取請(qǐng)求(fetch request)中關(guān)聯(lián)NSPredicate咆课。NSPreadicate支持基本功能末誓、相關(guān)子查詢和其他高級(jí)的SQL特性扯俱。它支持正確的Unicode編碼、區(qū)域感知查詢喇澡、排序和正則表達(dá)式迅栅;
- 延遲操作:Core Data使用懶加載(lazy loading)方式減少內(nèi)存負(fù)載,還支持部分實(shí)體化延遲加載和復(fù)制對(duì)象的數(shù)據(jù)共享機(jī)制晴玖;
- 合并策略:Core Data內(nèi)置版本跟蹤和樂(lè)觀鎖(optimistic locking)來(lái)支持多用戶寫(xiě)入沖突的解決读存,其中,樂(lè)觀鎖就是對(duì)數(shù)據(jù)沖突進(jìn)行檢測(cè)呕屎,若沖突就返回沖突的信息让簿;
- 數(shù)據(jù)遷移:Core Data的Schema Migration工具可以簡(jiǎn)化應(yīng)對(duì)數(shù)據(jù)庫(kù)結(jié)構(gòu)變化的任務(wù),在某些情況允許你執(zhí)行高效率的數(shù)據(jù)庫(kù)原地遷移工作榨惰;
- 可選擇針對(duì)程序Controller層的集成拜英,來(lái)支持UI的顯示同步Core Data在IPhone OS之上,提供NSFetchedResultsController對(duì)象來(lái)做相關(guān)工作琅催,在Mac OS X上我們用Cocoa提供的綁定(Binding)機(jī)制來(lái)完成的居凶。
十八、怎樣使用performSelector傳入3個(gè)以上參數(shù)藤抡,其中一個(gè)為結(jié)構(gòu)體
- 因?yàn)橄到y(tǒng)提供的
performSelector
的API中侠碧,并沒(méi)有提供三個(gè)參數(shù)。因此缠黍,我們只能傳數(shù)組或者字典弄兜,但是數(shù)組或者字典只有存入對(duì)象類(lèi)型,而結(jié)構(gòu)體并不是對(duì)象類(lèi)型,我們只能通過(guò)對(duì)象放入結(jié)構(gòu)作為屬性來(lái)傳過(guò)去了.
- (id)performSelector:(SEL)aSelector;
- (id)performSelector:(SEL)aSelector withObject:(id)object;
- (id)performSelector:(SEL)aSelector withObject: (id)object1 withObject:(id)object2;
- 具體實(shí)現(xiàn)如下:
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
// 在堆上分配的內(nèi)存瓷式,我們要手動(dòng)釋放掉
- (void)dealloc {
free(self.arg3);
}
@end
- 測(cè)試:
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];
// 在回調(diào)時(shí)得到正確的數(shù)據(jù)的
- (void)call:(HYBObject *)obj {
NSLog(@"%d %d", obj.arg3->a, obj.arg3->b);
}
十九替饿、UITableViewCell上有個(gè)UILabel,顯示NSTimer實(shí)現(xiàn)的秒表時(shí)間贸典,手指滾動(dòng)cell過(guò)程中视卢,label是否刷新,為什么廊驼?
這是否刷新取決于timer加入到Run Loop中的Mode是什么据过。Mode主要是用來(lái)指定事件在運(yùn)行循環(huán)中的優(yōu)先級(jí)的,分為:
-
NSDefaultRunLoopMode(kCFRunLoopDefaultMode)
:默認(rèn)妒挎,空閑狀態(tài) -
UITrackingRunLoopMode
:ScrollView滑動(dòng)時(shí)會(huì)切換到該Mode -
UIInitializationRunLoopMode
:run loop啟動(dòng)時(shí)绳锅,會(huì)切換到該mode -
NSRunLoopCommonModes(kCFRunLoopCommonModes)
:Mode集合
蘋(píng)果公開(kāi)提供的Mode有兩個(gè): NSDefaultRunLoopMode(kCFRunLoopDefaultMode
NSRunLoopCommonModes(kCFRunLoopCommonModes)
- 在編程中:如果我們把一個(gè)
NSTimer
對(duì)象以NSDefaultRunLoopMode(kCFRunLoopDefaultMode)
添加到主運(yùn)行循環(huán)中的時(shí)候, ScrollView滾動(dòng)過(guò)程中會(huì)因?yàn)閙ode的切換,而導(dǎo)致NSTimer
將不再被調(diào)度酝掩。當(dāng)我們滾動(dòng)的時(shí)候鳞芙,也希望不調(diào)度,那就應(yīng)該使用默認(rèn)模式。但是原朝,如果希望在滾動(dòng)時(shí)闯割,定時(shí)器也要回調(diào),那就應(yīng)該使用common mode竿拆。
二十宙拉、對(duì)于單元格重用的理解
- 當(dāng)屏幕上滑出屏幕時(shí),系統(tǒng)會(huì)把這個(gè)單元格添加到重用隊(duì)列中丙笋,等待被重用谢澈,當(dāng)有新單元從屏幕外滑入屏幕內(nèi)時(shí),從重用隊(duì)列中找看有沒(méi)有可以重用的單元格御板,若有锥忿,就直接用,沒(méi)有就重新創(chuàng)建一個(gè)怠肋。
解決cell重用的問(wèn)題
- UITableView通過(guò)重用單元格來(lái)達(dá)到節(jié)省內(nèi)存的目的敬鬓,通過(guò)為每個(gè)單元格指定一個(gè)重用標(biāo)示(reuseidentifier),即指定了單元格的種類(lèi)笙各,以及當(dāng)單元格滾出屏幕時(shí)钉答,允許恢復(fù)單元格以便復(fù)用。對(duì)于不同種類(lèi)的單元格使用不同的ID杈抢,對(duì)于簡(jiǎn)單的表格数尿,一個(gè)標(biāo)示符就夠了。
- 如一個(gè)TableView中有10個(gè)單元格惶楼,但屏幕最多顯示4個(gè)右蹦,實(shí)際上iPhone只為其分配4個(gè)單元格的內(nèi)存,沒(méi)有分配10個(gè)歼捐,當(dāng)滾動(dòng)單元格時(shí)何陆,屏幕內(nèi)顯示的單元格重復(fù)使用這4個(gè)內(nèi)存。實(shí)際上分配的cell的個(gè)數(shù)為屏幕最大顯示數(shù)豹储,當(dāng)有新的cell進(jìn)入屏幕時(shí)贷盲,會(huì)隨機(jī)調(diào)用已經(jīng)滾出屏幕的Cell所占的內(nèi)存,這就是Cell的重用颂翼。
- 對(duì)于多變的自定義Cell晃洒,這種重用機(jī)制會(huì)導(dǎo)致內(nèi)容出錯(cuò)慨灭,為解決這種出錯(cuò)的方法朦乏,把原來(lái)的
UITableViewCell *cell = [tableview dequeueReusableCellWithIdentifier:defineString]
修改為:UITableViewCell *cell = [tableview cellForRowAtIndexPath:indexPath];
這樣就解決掉cell重用機(jī)制導(dǎo)致的問(wèn)題。
二十一氧骤、有a呻疹、b、c筹陵、d 4個(gè)異步請(qǐng)求刽锤,如何判斷a镊尺、b、c并思、d都完成執(zhí)行庐氮?如果需要a、b宋彼、c弄砍、d順序執(zhí)行,該如何實(shí)現(xiàn)输涕?
- 對(duì)于這四個(gè)異步請(qǐng)求音婶,要判斷都執(zhí)行完成最簡(jiǎn)單的方式就是通過(guò)GCD的group來(lái)實(shí)現(xiàn):
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, ^{ /*任務(wù)a */ });
dispatch_group_async(group, queue, ^{ /*任務(wù)b */ });
dispatch_group_async(group, queue, ^{ /*任務(wù)c */ });
dispatch_group_async(group, queue, ^{ /*任務(wù)d */ });
dispatch_group_notify(group,dispatch_get_main_queue(), ^{
// 在a、b莱坎、c衣式、d異步執(zhí)行完成后,會(huì)回調(diào)這里
});
- 當(dāng)然檐什,我們還可以使用非常老套的方法來(lái)處理碴卧,通過(guò)四個(gè)變量來(lái)標(biāo)識(shí)a、b乃正、c螟深、d四個(gè)任務(wù)是否完成,然后在runloop中讓其等待烫葬,當(dāng)完成時(shí)才退出runloop界弧。但是這樣做會(huì)讓后面的代碼得不到執(zhí)行,直到Run loop執(zhí)行完畢搭综。
- 解釋?zhuān)阂箜樞驁?zhí)行垢箕,那么可以將任務(wù)放到串行隊(duì)列中,自然就是按順序來(lái)異步執(zhí)行了兑巾。
二十二条获、使用block有什么好處?使用NSTimer寫(xiě)出一個(gè)使用block顯示(在UILabel上)秒表的代碼
- 代碼緊湊蒋歌,傳值帅掘、回調(diào)都很方便,省去了寫(xiě)代理的很多代碼堂油。
- NSTimer封裝成的block修档,具體實(shí)現(xiàn)
- 實(shí)現(xiàn)方法:
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0
repeats:YES
callback:^() {
weakSelf.secondsLabel.text = ...
}
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
二十三、一個(gè)view已經(jīng)初始化完畢府框,view上面添加了n個(gè)button吱窝,除用view的tag之外,還可以采用什么辦法來(lái)找到自己想要的button來(lái)修改button的值
有2種方法解決:
- 第一種:如果是點(diǎn)擊某個(gè)按鈕后,才會(huì)刷新它的值院峡,其它不用修改兴使,那么不用引用任何按鈕,直接在回調(diào)時(shí)照激,就已經(jīng)將接收響應(yīng)的按鈕給傳過(guò)來(lái)了发魄,直接通過(guò)它修改即可。
- 第二種:點(diǎn)擊某個(gè)按鈕后俩垃,所有與之同類(lèi)型的按鈕都要修改值欠母,那么可以通過(guò)在創(chuàng)建按鈕時(shí)將按鈕存入到數(shù)組中,在需要的時(shí)候遍歷查找吆寨。
二十四赏淌、線程與進(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)程哮兰。
多線程編程
-
NSThread
:當(dāng)需要進(jìn)行一些耗時(shí)操作時(shí)會(huì)把耗時(shí)的操作放到線程中毛萌。線程同步:多個(gè)線程同時(shí)訪問(wèn)一個(gè)數(shù)據(jù)會(huì)出問(wèn)題,NSlock喝滞、線程同步塊阁将、@synchronized(self){}。 -
NSOperationQueue
操作隊(duì)列(不需考慮線程同步問(wèn)題)囤躁。編程的重點(diǎn)都放在main里面冀痕,NSInvocationOperation
、BSBlockOperation
狸演、自定義Operation言蛇。創(chuàng)建一個(gè)操作綁定相應(yīng)的方法,當(dāng)把操作添加到操作隊(duì)列中時(shí)宵距,操作綁定的方法就會(huì)自動(dòng)執(zhí)行了腊尚,當(dāng)把操作添加到操作隊(duì)列中時(shí),默認(rèn)會(huì)調(diào)用main方法满哪。 - GCD(
Grand Central Dispatch
)宏大的中央調(diào)度婿斥,串行隊(duì)列、并發(fā)隊(duì)列哨鸭、主線程隊(duì)列民宿; - 同步和異步:同步指第一個(gè)任務(wù)不執(zhí)行完,不會(huì)開(kāi)始第二個(gè)像鸡,異步是不管第一個(gè)有沒(méi)有執(zhí)行完活鹰,都開(kāi)始第二個(gè)。
- 串行和并行:串行是多個(gè)任務(wù)按一定順序執(zhí)行只估,并行是多個(gè)任務(wù)同時(shí)執(zhí)行志群;
- 代碼是在分線程執(zhí)行,在主線程嘟列中刷新UI蛔钙。
多線程編程是防止主線程堵塞锌云、增加運(yùn)行效率的最佳方法。
- Apple提供了NSOperation這個(gè)類(lèi)吁脱,提供了一個(gè)優(yōu)秀的多線程編程方法桑涎;
- 一個(gè)NSOperationQueue操作隊(duì)列,相當(dāng)于一個(gè)線程管理器兼贡,而非一個(gè)線程石洗,因?yàn)槟憧梢栽O(shè)置這個(gè)線程管理器內(nèi)可以并行運(yùn)行的線程數(shù)量等。
- 多線程是一個(gè)比較輕量級(jí)的方法來(lái)實(shí)現(xiàn)單個(gè)應(yīng)用程序內(nèi)多個(gè)代碼執(zhí)行路徑紧显。
- iPhoneOS下的主線程的堆棧大小是1M讲衫。第二個(gè)線程開(kāi)始就是512KB,并且該值不能通過(guò)編譯器開(kāi)關(guān)或線程API函數(shù)來(lái)更改孵班,只有主線程有直接修改UI的能力涉兽。
定時(shí)器與線程的區(qū)別;
- 定時(shí)器;可以執(zhí)行多次,默認(rèn)在主線程中篙程。
- 線程:只能執(zhí)行一次枷畏。
隊(duì)列和多線程的使用原理
在iOS中隊(duì)列分為以下幾種:
- 串行隊(duì)列:隊(duì)列中的任務(wù)只會(huì)順序執(zhí)行;
dispatch_queue_t q = dispatch_queue_create("...", DISPATCH_QUEUE_SERIAL);
- 并行隊(duì)列: 隊(duì)列中的任務(wù)通常會(huì)并發(fā)執(zhí)行虱饿;
dispatch_queue_t q = dispatch_queue_create("......",DISPATCH_QUEUE_CONCURRENT);
- 全局隊(duì)列:是系統(tǒng)的拥诡,直接拿過(guò)來(lái)(GET)用就可以触趴;與并行隊(duì)列類(lèi)似;
dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
- 主隊(duì)列:每一個(gè)應(yīng)用程序?qū)?yīng)唯一主隊(duì)列渴肉,直接GET即可冗懦;在多線程開(kāi)發(fā)中,使用主隊(duì)列更新UI仇祭;
dispatch_queue_t q = dispatch_get_main_queue();
-
更多細(xì)節(jié)見(jiàn)下圖:
二十五披蕉、TCP和UDP的區(qū)別于聯(lián)系
- TCP為傳輸控制層協(xié)議,為面向連接乌奇、可靠的没讲、點(diǎn)到點(diǎn)的通信;
- UDP為用戶數(shù)據(jù)報(bào)協(xié)議礁苗,非連接的不可靠的點(diǎn)到多點(diǎn)的通信爬凑;
- TCP側(cè)重可靠傳輸,UDP側(cè)重快速傳輸试伙。
TCP連接的三次握手
- 第一次握手:客戶端發(fā)送syn包(syn=j)到服務(wù)器贰谣,并進(jìn)入SYN_SEND狀態(tài),等待服務(wù)器確認(rèn)迁霎;
- 第二次握手:服務(wù)器收到syn包吱抚,必須確認(rèn)客戶的SYN(ack=j+1),同時(shí)自己也發(fā)送一個(gè)SYN包考廉,即SYN+ACK包秘豹,此時(shí)服務(wù)器進(jìn)入SYN+RECV狀態(tài);
- 第三次握手:客戶端收到服務(wù)器的SYN+ACK包昌粤,向服務(wù)器發(fā)送確認(rèn)包ACK(ack=k+1)既绕,此發(fā)送完畢,客戶端和服務(wù)器進(jìn)入ESTABLISHED狀態(tài)涮坐,完成三次狀態(tài)凄贩。
二十六、Scoket連接和HTTP連接的區(qū)別:
- HTTP協(xié)議是基于TCP連接的袱讹,是應(yīng)用層協(xié)議疲扎,主要解決如何包裝數(shù)據(jù)。Socket是對(duì)TCP/IP協(xié)議的封裝捷雕,Socket本身并不是協(xié)議椒丧,而是一個(gè)調(diào)用接口(API),通過(guò)Socket救巷,我們才能使用TCP/IP協(xié)議壶熏。
- HTTP連接:短連接,客戶端向服務(wù)器發(fā)送一次請(qǐng)求浦译,服務(wù)器響應(yīng)后連接斷開(kāi)棒假,節(jié)省資源溯职。服務(wù)器不能主動(dòng)給客戶端響應(yīng)(除非采用HTTP長(zhǎng)連接技術(shù)),iPhone主要使用類(lèi)NSURLConnection帽哑。
- Socket連接:長(zhǎng)連接谜酒,客戶端跟服務(wù)器端直接使用Socket進(jìn)行連接,沒(méi)有規(guī)定連接后斷開(kāi)祝拯,因此客戶端和服務(wù)器段保持連接通道甚带,雙方可以主動(dòng)發(fā)送數(shù)據(jù)她肯,一般多用于游戲.Socket默認(rèn)連接超時(shí)時(shí)間是30秒佳头,默認(rèn)大小是8K(理解為一個(gè)數(shù)據(jù)包大小)晴氨。
HTTP協(xié)議的特點(diǎn)康嘉,關(guān)于HTTP請(qǐng)求GET和POST的區(qū)別
GET和POST的區(qū)別:
- HTTP超文本傳輸協(xié)議,是短連接籽前,是客戶端主動(dòng)發(fā)送請(qǐng)求亭珍,服務(wù)器做出響應(yīng),服務(wù)器響應(yīng)之后枝哄,鏈接斷開(kāi)肄梨。HTTP是一個(gè)屬于應(yīng)用層面向?qū)ο蟮膮f(xié)議,HTTP有兩類(lèi)報(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請(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é)議頭<requestline>中。
以"共螺?"分割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包的包體
<request-body>
中.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上这嚣,比如登陸界面有可能被瀏覽器緩存鸥昏。
- HTTPS:安全超文本傳輸協(xié)議(
Secure Hypertext Transfer Protocol
),它是一個(gè)安全通信通道姐帚,基于HTTP開(kāi)發(fā)吏垮,用于客戶計(jì)算機(jī)和服務(wù)器之間交換信息,使用安全套結(jié)字層(SSI
)進(jìn)行信息交換卧土,即HTTP的安全版惫皱。
二十七、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子類(lèi)。
- ASIHttpRequest是直接操作對(duì)象ASIHttpRequest是一個(gè)實(shí)現(xiàn)了NSCoding協(xié)議的NSOperation子類(lèi)椒振;AFNetWorking直接操作對(duì)象的AFHttpClient昭伸,是一個(gè)實(shí)現(xiàn)NSCoding和NSCopying協(xié)議的NSObject子類(lèi)。
- 同步請(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;
二十八罩引、XML數(shù)據(jù)解析方式各有什么不同各吨,JSON解析有哪些框架枝笨?
- XML數(shù)據(jù)解析的兩種解析方式:DOM解析和SAX解析袁铐;
- DOM解析必須完成DOM樹(shù)的構(gòu)造,在處理規(guī)模較大的XML文檔時(shí)就很耗內(nèi)存横浑,占用資源較多剔桨,讀入整個(gè)XML文檔并構(gòu)建一個(gè)駐留內(nèi)存的樹(shù)結(jié)構(gòu)(節(jié)點(diǎn)樹(shù)),通過(guò)遍歷樹(shù)結(jié)構(gòu)可以檢索任意XML節(jié)點(diǎn)徙融,讀取它的屬性和值洒缀,通常情況下,可以借助XPath查詢XML節(jié)點(diǎn)欺冀;
- SAX與DOM不同树绩,它是事件驅(qū)動(dòng)模型,解析XML文檔時(shí)每遇到一個(gè)開(kāi)始或者結(jié)束標(biāo)簽隐轩、屬性或者一條指令時(shí)饺饭,程序就產(chǎn)生一個(gè)事件進(jìn)行相應(yīng)的處理,一邊讀取XML文檔一邊處理职车,不必等整個(gè)文檔加載完才采取措施瘫俊,當(dāng)在讀取解析過(guò)程中遇到需要處理的對(duì)象,會(huì)發(fā)出通知進(jìn)行處理悴灵。因此扛芽,SAX相對(duì)于DOM來(lái)說(shuō)更適合操作大的XML文檔。
-JSON解析:性能比較好的主要是第三方的JSONKIT和iOS自帶的JSON解析類(lèi)积瞒,其中自帶的JSON解析性能最高川尖,但只能用于iOS5之后。
二十九茫孔、SVN的使用
- SVN=版本控制+備份服務(wù)器叮喳,可以把SVN當(dāng)成備份服務(wù)器庐船,并且可以幫助你記住每次上服務(wù)器的檔案內(nèi)容,并自動(dòng)賦予每次變更的版本嘲更;
- SVN的版本控制:所有上傳版本都會(huì)幫您記錄下來(lái)筐钟,也有版本分支及合并等功能。SVN可以讓不同的開(kāi)發(fā)者存取同樣的檔案赋朦,并且利用SVN Server作為檔案同步的機(jī)制篓冲,即您有檔案更新時(shí),無(wú)需將檔案寄送給您的開(kāi)發(fā)成員宠哄。SVN的存放檔案方式是采用差異備份的方式壹将,即會(huì)備份到不同的地方,節(jié)省硬盤(pán)空間毛嫉,也可以對(duì)非文字文件進(jìn)行差異備份诽俯。
- SVN的重要性:備份工作檔案的重要性、版本控管的重要性承粤、伙伴間的數(shù)據(jù)同步的重要性暴区、備份不同版本是很耗費(fèi)硬盤(pán)空間的;
- 防止沖突:
1.防止代碼沖突:不要多人同時(shí)修改同一文件辛臊,例如:A仙粱、B都修改同一個(gè)文件,先讓A修改彻舰,然后提交到服務(wù)器伐割,然后B更新下來(lái),再進(jìn)行修改刃唤;
2.服務(wù)器上的項(xiàng)目文件Xcodeproj隔心,僅讓一個(gè)人管理提交,其他人只更新尚胞,防止文件發(fā)生沖突硬霍。
三十、如何進(jìn)行網(wǎng)絡(luò)消息推送
- 一種是Apple自己提供的通知服務(wù)(APNS服務(wù)器)辐真、一種是用第三方推送機(jī)制须尚。
- 首先應(yīng)用發(fā)送通知,系統(tǒng)彈出提示框詢問(wèn)用戶是否允許侍咱,當(dāng)用戶允許后向蘋(píng)果服務(wù)器(APNS)請(qǐng)求deviceToken耐床,并由蘋(píng)果服務(wù)器發(fā)送給自己的應(yīng)用,自己的應(yīng)用將DeviceToken發(fā)送自己的服務(wù)器楔脯,自己服務(wù)器想要發(fā)送網(wǎng)絡(luò)推送時(shí)將deviceToken以及想要推送的信息發(fā)送給蘋(píng)果服務(wù)器撩轰,蘋(píng)果服務(wù)器將信息發(fā)送給應(yīng)用。
- 推送信息內(nèi)容,總?cè)萘坎怀^(guò)256個(gè)字節(jié)堪嫂;
- iOS SDK本身提供的APNS服務(wù)器推送偎箫,它可以直接推送給目標(biāo)用戶并根據(jù)您的方式彈出提示。
優(yōu)點(diǎn):不論應(yīng)用是否開(kāi)啟皆串,都會(huì)發(fā)送到手機(jī)端淹办;
缺點(diǎn):消息推送機(jī)制是蘋(píng)果服務(wù)端控制,個(gè)別時(shí)候可能會(huì)有延遲恶复,因?yàn)樘O(píng)果服務(wù)器也有隊(duì)列來(lái)處理所有的消息請(qǐng)求怜森; - 第三方推送機(jī)制,普遍使用Socket機(jī)制來(lái)實(shí)現(xiàn)谤牡,幾乎可以達(dá)到即時(shí)的發(fā)送到目標(biāo)用戶手機(jī)端副硅,適用于即時(shí)通訊類(lèi)應(yīng)用。
優(yōu)點(diǎn):實(shí)時(shí)的翅萤,取決于心跳包的節(jié)奏恐疲;
缺點(diǎn):iOS系統(tǒng)的限制,應(yīng)用不能長(zhǎng)時(shí)間的后臺(tái)運(yùn)行套么,所以應(yīng)用關(guān)閉的情況下這種推送機(jī)制不可用培己。
三十一、UIViewController的完整生命周期
-[ViewController initWithNibName:bundle:]违诗;
-[ViewController init]漱凝;
-[ViewController loadView]疮蹦;
-[ViewController viewDidLoad]诸迟;
-[ViewController viewWillAppear:];
-[ViewController viewDidAppear:]愕乎;
-[ViewController viewWillDisappear:]阵苇;
-[ViewController viewDidDisappear:];
三十二感论、深拷貝和淺拷貝
- 如果對(duì)象有個(gè)指針型成員變量指向內(nèi)存中的某個(gè)資源绅项,那么如何復(fù)制這個(gè)對(duì)象呢?你會(huì)只是復(fù)制指針的值傳給副本的新對(duì)象嗎比肄?指針只是存儲(chǔ)內(nèi)存中資源地址的占位符快耿。在復(fù)制操作中,如果只是將指針復(fù)制給新對(duì)象芳绩,那么底層的資源實(shí)際上仍然由兩個(gè)實(shí)例在共享掀亥。
- 淺復(fù)制:兩個(gè)實(shí)例的指針仍指向內(nèi)存中的同一資源,只復(fù)制指針值而不是實(shí)際資源妥色;
- 深復(fù)制:不僅復(fù)制指針值搪花,還復(fù)制指向指針?biāo)赶虻馁Y源。如下圖:
三十三、對(duì)沙盒的理解
每個(gè)iOS應(yīng)用都被限制在“沙盒”中撮竿,沙盒相當(dāng)于一個(gè)加了僅主人可見(jiàn)權(quán)限的文件夾吮便,及時(shí)在應(yīng)用程序安裝過(guò)程中,系統(tǒng)為每個(gè)單獨(dú)的應(yīng)用程序生成它的主目錄和一些關(guān)鍵的子目錄幢踏。蘋(píng)果對(duì)沙盒有幾條限制:
1. 應(yīng)用程序在自己的沙盒中運(yùn)作髓需,但是不能訪問(wèn)任何其他應(yīng)用程序的沙盒;
2. 應(yīng)用之間不能共享數(shù)據(jù)房蝉,沙盒里的文件不能被復(fù)制到其他 應(yīng)用程序的文件夾中授账,也不能把其他應(yīng)用文件夾復(fù)制到沙盒中;
3. 蘋(píng)果禁止任何讀寫(xiě)沙盒以外的文件惨驶,禁止應(yīng)用程序?qū)?nèi)容寫(xiě)到沙盒以外的文件夾中白热;
4. 沙盒目錄里有三個(gè)文件夾:Documents——存儲(chǔ)應(yīng)用程序的數(shù)據(jù)文件,
存儲(chǔ)用戶數(shù)據(jù)或其他定期備份的信息粗卜;Library下有兩個(gè)文件夾屋确,Caches存儲(chǔ)應(yīng)用程序再次啟動(dòng)所需的信息,
Preferences包含應(yīng)用程序的偏好設(shè)置文件续扔,不可在這更改偏好設(shè)置攻臀;
temp存放臨時(shí)文件即應(yīng)用程序再次啟動(dòng)不需要的文件。
- 獲取沙盒根目錄的方法纱昧,有幾種方法:用NSHomeDirectory獲取刨啸。
- 獲取Document路徑:
NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES)
.
三十四、ViewController 的 loadView,识脆、viewDidLoad,设联、viewDidUnload 分別是在什么時(shí)候調(diào)用的?
-
viewDidLoad
在view從nib文件初始化時(shí)調(diào)用灼捂,loadView
在controller的view為nil時(shí)調(diào)用离例。 - 此方法在編程實(shí)現(xiàn)view時(shí)調(diào)用,view控制器默認(rèn)會(huì)注冊(cè)
memory warning notification
,當(dāng)view controller
的任何view沒(méi)有用的時(shí)候,viewDidUnload
會(huì)被調(diào)用悉稠,在這里實(shí)現(xiàn)將retain
的view release
,如果是retain
的IBOutlet view
屬性則不要在這里release
,IBOutlet
會(huì)負(fù)責(zé)release
宫蛆。
三十四、@synthesize的猛、@dynamic的理解
-
@synthesize
是系統(tǒng)自動(dòng)生成getter和setter屬性聲明;@synthesize的意思是耀盗,除非開(kāi)發(fā)人員已經(jīng)做了,否則由編譯器生成相應(yīng)的代碼卦尊,以滿足屬性聲明叛拷; -
@dynamic
是開(kāi)發(fā)者自已提供相應(yīng)的屬性聲明,@dynamic
意思是由開(kāi)發(fā)人員提供相應(yīng)的代碼:對(duì)于只讀屬性需要提供setter
,對(duì)于讀寫(xiě)屬性需要提供setter
和getter
猫牡。查閱了一些資料確定@dynamic的意思是告訴編譯器,屬性的獲取與賦值方法由用戶自己實(shí)現(xiàn), 不自動(dòng)生成胡诗。
三十五邓线、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))
三十六、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;
三十七你雌、property屬性的修飾符的作用
- getter=getName、setter=setName:設(shè)置setter與getter的方法名二汛;
- readwrite婿崭、readonly:設(shè)置可供訪問(wèn)級(jí)別;
- assign:方法直接賦值肴颊,不進(jìn)行任何retain操作氓栈,為了解決原類(lèi)型與環(huán)循引用問(wèn)題;
- retain:其setter方法對(duì)參數(shù)進(jìn)行release舊值再retain新值婿着,所有實(shí)現(xiàn)都是這個(gè)順序授瘦;
- copy:其setter方法進(jìn)行copy操作,與retain處理流程一樣竟宋,先對(duì)舊值release提完,再copy出新的對(duì)象,retainCount為1丘侠。這是為了減少對(duì)上下文的依賴而引入的機(jī)制徒欣。
- nonatomic:非原子性訪問(wèn),不加同步蜗字, 多線程并發(fā)訪問(wèn)會(huì)提高性能打肝。注意,如果不加此屬性秽澳,則默認(rèn)是兩個(gè)訪問(wèn)方法都為原子型事務(wù)訪問(wèn)闯睹。
三十八、對(duì)于Run Loop的理解
- RunLoop担神,是多線程的法寶,即一個(gè)線程一次只能執(zhí)行一個(gè)任務(wù)始花,執(zhí)行完任務(wù)后就會(huì)退出線程妄讯。主線程執(zhí)行完即時(shí)任務(wù)時(shí)會(huì)繼續(xù)等待接收事件而不退出。非主線程通常來(lái)說(shuō)就是為了執(zhí)行某一任務(wù)的酷宵,執(zhí)行完畢就需要?dú)w還資源亥贸,因此默認(rèn)是不運(yùn)行RunLoop的;
- 每一個(gè)線程都有其對(duì)應(yīng)的RunLoop浇垦,只是默認(rèn)只有主線程的RunLoop是啟動(dòng)的炕置,其它子線程的RunLoop默認(rèn)是不啟動(dòng)的,若要啟動(dòng)則需要手動(dòng)啟動(dòng);
- 在一個(gè)單獨(dú)的線程中朴摊,如果需要在處理完某個(gè)任務(wù)后不退出默垄,繼續(xù)等待接收事件,則需要啟用RunLoop甚纲;
- NSRunLoop提供了一個(gè)添加NSTimer的方法口锭,可以指定Mode,如果要讓任何情況下都回調(diào)介杆,則需要設(shè)置Mode為Common模式鹃操;
- 實(shí)質(zhì)上,對(duì)于子線程的runloop默認(rèn)是不存在的春哨,因?yàn)樘O(píng)果采用了懶加載的方式荆隘。如果我們沒(méi)有手動(dòng)調(diào)用
[NSRunLoop currentRunLoop]
的話,就不會(huì)去查詢是否存在當(dāng)前線程的RunLoop赴背,也就不會(huì)去加載臭胜,更不會(huì)創(chuàng)建。
三十九癞尚、SQLite中常用的SQL語(yǔ)句
- 創(chuàng)建表:creat table 表名 (字段名 字段數(shù)據(jù)類(lèi)型 是否為主鍵, 字段名 字段數(shù)據(jù)類(lèi)型, 字段名 字段數(shù)據(jù)類(lèi)型...)耸三;
- 增: insert into 表名 (字段1, 字段2...) values (值1, 值2...);
- 刪: delete from 表名 where 字段 = 值浇揩;
四十仪壮、XIB與Storyboards的優(yōu)缺點(diǎn)
優(yōu)點(diǎn):
- XIB:在編譯前就提供了可視化界面,可以直接拖控件胳徽,也可以直接給控件添加約束积锅,更直觀一些,而且類(lèi)文件中就少了創(chuàng)建控件的代碼养盗,確實(shí)簡(jiǎn)化不少缚陷,通常每個(gè)XIB對(duì)應(yīng)一個(gè)類(lèi)。
- Storyboard:在編譯前提供了可視化界面往核,可拖控件箫爷,可加約束,在開(kāi)發(fā)時(shí)比較直觀聂儒,而且一個(gè)storyboard可以有很多的界面虎锚,每個(gè)界面對(duì)應(yīng)一個(gè)類(lèi)文件,通過(guò)storybard衩婚,可以直觀地看出整個(gè)App的結(jié)構(gòu)窜护。
缺點(diǎn):
- 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)困難。
四十一做祝、將字符串“2015-04-10”格式化日期轉(zhuǎn)為NSDate類(lèi)型
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);
四十二近尚、UIImageView添加圓角
- 最直接的方法就是使用如下屬性設(shè)置:
imgView.layer.cornerRadius = 10;
// 這一行代碼是很消耗性能的
imgView.clipsToBounds = YES;
這是離屏渲染(off-screen-rendering)蠕啄,消耗性能的
- 給UIImage添加生成圓角圖片的擴(kuò)展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;
}
感謝您的閱讀,本文轉(zhuǎn)載自Jack_lin的iOS,面試必看戈锻,最全梳理
如有侵權(quán)歼跟,請(qǐng)聯(lián)系本人。