花絮:
從上一篇文章的發(fā)表到這篇文章的發(fā)表已經(jīng)有很長一段時間了,一直在摸索適合自己的學(xué)習(xí)方式屁魏,到現(xiàn)在還是沒有找到適合自己的怎茫,嘗試如下:
1.每天上班都是活躍在各大
iOS開發(fā)群
,碰到別人的問題蝗锥,自己不懂的都悄悄記下來跃洛,自己去百度,也能學(xué)到一些東西终议,但是不能系統(tǒng)的學(xué)習(xí).
2.下班都是看看別人寫好的博客汇竭,也能學(xué)到一些技術(shù),但是這樣只能依賴于別人穴张。
3.周六日自己在看別人源碼细燎,試著去學(xué)習(xí)別人寫框架的邏輯。
4.還試著看了寫官方文檔皂甘,但是礙于本人的英語水平的差距玻驻,無法去理解文檔上面的思想。
5.試著去學(xué)習(xí)了PHP偿枕,雖說現(xiàn)在可以寫后臺和Api接口璧瞬,但是關(guān)于PHP如何運行,一竅不通渐夸。
友情鏈接:
- CALyer解讀--總有一個點會讓你想起它
- iOS11和iPhone X的適配
- iOS開發(fā)個人開發(fā)賬號的證書詳細(xì)使用及介紹
- 自定義XIB View里面添加其他自定義Xib View
重點:希望大家分享下自己的學(xué)習(xí)方式和心得嗤锉,七秒感激不盡!!!
不久前看到一篇2017年5月iOS招人心得(附面試題)上面的面試題,很不錯墓塌,自己就想結(jié)合自己所學(xué)的知識來回答一下瘟忱,總結(jié)一下自己知識
1.為什么說Objective-C是一門動態(tài)的語言奥额?
1.object-c類的類型和數(shù)據(jù)變量的類型都是在運行是確定的,而不是在編譯時確定酷誓。例如:多態(tài)特性披坏,我們可以使用父類指針來指向子類對象,并且可以用來調(diào)用子類的方法盐数。運行時(runtime)特性,我們可以動態(tài)的添加方法棒拂,或者替換方法。
2.講一下MVC和MVVM玫氢,MVP帚屉?
MVC:簡單來說就是,邏輯漾峡、試圖攻旦、數(shù)據(jù)進(jìn)行分層,實現(xiàn)解耦生逸。
MVVM:是Model-View-ViewMode模式的簡稱牢屋。由視圖(View)、視圖模型(ViewModel)槽袄、模型(Model)三部分組成.比MVC更加釋放控制器臃腫烙无,將一部分邏輯(耗時,公共方法遍尺,網(wǎng)絡(luò)請求等)和數(shù)據(jù)的處理等操作從控制器里面搬運到ViewModel
中
MVVM的特點:
- 低耦合截酷。View可以獨立于Model變化和修改,一個ViewModel可以綁定到不同的View上乾戏,當(dāng)View變化的時候Model可以不變迂苛,當(dāng)Model變化的時候View也可以不變。
- 可重用性鼓择∪茫可以把一些視圖的邏輯放在ViewModel里面,讓很多View重用這段視圖邏輯呐能。
- 獨立開發(fā)念搬。開發(fā)人員可以專注與業(yè)務(wù)邏輯和數(shù)據(jù)的開發(fā)(ViewModel)。設(shè)計人員可以專注于界面(View)的設(shè)計催跪。
- 可測試性∫囊埃可以針對ViewModel來對界面(View)進(jìn)行測試
MVP:本小編沒有接觸懊蒸,希望可以得到大家的幫助∶跎Γ可以在下面留言骑丸。
3.為什么代理要用weak?代理的delegate和dataSource有什么區(qū)別?block和代理的區(qū)別?
代理是使用weak來修飾的通危。1.使用weak是為了避免循環(huán)引用铸豁。2.當(dāng)使用weak修飾的屬性,當(dāng)對象釋放的時候菊碟,系統(tǒng)會對屬性賦值
nil
,object-c有個特性就是對nil
對象發(fā)送消息也就是調(diào)用方法节芥,不會cash。
delegate:傳遞的是事件(even)逆害,代理可以讓A對象通知B對象头镊,我(A)發(fā)生的變化,前提B遵循了A的代理魄幕,并且實現(xiàn)了A的代理方法相艇。
dataSource: 傳遞的是數(shù)據(jù)。如果A對象聲明了數(shù)據(jù)源纯陨,當(dāng)我們創(chuàng)建A對象的時候坛芽,我們就該實現(xiàn)數(shù)據(jù)源,來告訴A翼抠,他所需要的一些數(shù)據(jù)咙轩。例如:tableView數(shù)據(jù)源方法,需要告訴它机久,我要實現(xiàn)幾組cell臭墨,每組cell多少行cell,實現(xiàn)的cell什么樣式膘盖,什么內(nèi)容
同樣delegate
和dataSource
,都是可以使用require
和optional
來修飾的胧弛。
代理和Block的區(qū)別
相同點:代理和Block大多是我們都可以用來做倒序傳值的。我們都得注意避免循環(huán)引用侠畔。不然我們?nèi)ナ褂么磉€是Block的時候结缚,都需要判斷它們是否實現(xiàn)
不同點:代理使用weak修飾,代理必須先聲明方法软棺。當(dāng)我們調(diào)用代理的時候要判斷是否已經(jīng)實現(xiàn)红竭。
block:使用的是copy來修飾,block保存的是一段代碼喘落,其實也就是一個函數(shù)茵宪。并且可以自動捕捉自動變量,如果想修改此自動變量瘦棋,還必須使用__block
修飾稀火。
4.屬性的實質(zhì)是什么?包括哪幾個部分赌朋?屬性默認(rèn)的關(guān)鍵字都有哪些凰狞?@dynamic關(guān)鍵字和@synthesize關(guān)鍵字是用來做什么的篇裁?
屬性是描述類的特征,也就是具備什么特性赡若。三個部分达布,帶下劃線的成員變量,get逾冬、setter方法黍聂。
默認(rèn)關(guān)鍵字:readwrite,assign, atomic; -- 是針對基本類型(NSInteger, BOOL, NSUInteger, int, 等)
但是針對引用類型, 默認(rèn):strong, readwrite, atomic (例如:NSString, NSArray, NSDictory等)
@dynamic :修飾的屬性粉渠,其getter和setter方法編譯器是不會自動幫你生成分冈。必須自己是實現(xiàn)的。
@synthesize:修飾的屬性霸株,其getter和setter方法編譯器是會自動幫你生成雕沉,不必自己實現(xiàn)。且指定與屬性相對應(yīng)的成員變量去件。
5.屬性的默認(rèn)關(guān)鍵字是什么坡椒?
默認(rèn)關(guān)鍵字,基本數(shù)據(jù): atomic,readwrite,assign
普通的 OC 對象: atomic,readwrite,strong
6.NSString為什么要用copy關(guān)鍵字尤溜,如果用strong會有什么問題倔叼?(注意:這里沒有說用strong就一定不行。使用copy和strong是看情況而定的
眾所周知宫莱,我們知道丈攒,可變類型(NSMutableArray,NSMutableString等)是不可邊類型(NSString,NSArray等)的子類,因為多態(tài)的原因授霸,我們可以使用不可邊類型去接受可變類型巡验。
1.當(dāng)我們使用strong修飾A不可邊類型的時候,并且使用B可變類型給A賦值碘耳,再去修改可變類型B值的時候显设,A所指向的值也會發(fā)生改變。引文strong只是讓創(chuàng)建的對象引用計數(shù)器+1辛辨,并返回當(dāng)前對象的內(nèi)容地址捕捂,當(dāng)我們修改B指向的內(nèi)容的時候,A指向的內(nèi)容也同樣發(fā)生了改變斗搞,因為他們指向的內(nèi)存地址是相同的,是一份內(nèi)容指攒。
2.當(dāng)我們使用copy修飾A不可邊類型的時候,并且使用B可變類型給A賦值僻焚,再去修改可變類型B值的時候允悦,A所指向的值不會發(fā)生改變。因為當(dāng)時用copy的修飾的時候溅呢,會拷貝一份內(nèi)容出來澡屡,并且返回指針給A,當(dāng)我們修改B指向的內(nèi)容的時候咐旧,A指向的內(nèi)容是沒有發(fā)生改變的驶鹉。因為A指向的內(nèi)存地址和B指向的內(nèi)存地址是不相同的,是兩份內(nèi)容
3.copy修飾不可邊類型(NSString,NSArray等)的時候铣墨,且使用不可邊類型進(jìn)行賦值室埋,表示淺拷貝,只拷貝一份指針伊约,和strong修飾一樣姚淆,當(dāng)修飾的是可變類型(NSMutableArray,NSMutableString等)的時候,且使用可邊類型進(jìn)行賦值屡律,表示深拷貝腌逢,直接拷貝新一份內(nèi)容,到內(nèi)存中超埋。表示兩份內(nèi)容搏讶。
7.如何令自己所寫的對象具有拷貝功能?
如果想讓自己的類具備
copy
方法,并返回不可邊類型霍殴,必須遵循nscopying
協(xié)議媒惕,并且實現(xiàn)
- (id)copyWithZone:(NSZone *)zone
如果讓自己的類具備mutableCopy
方法,并且放回可變類型来庭,必須遵守NSMutableCopying
妒蔚,并實現(xiàn)- (id)mutableCopyWithZone:(nullable NSZone *)zone
注意:再此說的copy對應(yīng)不可邊類型
和mutableCopy對應(yīng)不可邊類型
方法,都是遵從系統(tǒng)規(guī)則而已月弛。如果你想實現(xiàn)自己的規(guī)則肴盏,也是可以的。
8.可變集合類 和 不可變集合類的 copy 和 mutablecopy有什么區(qū)別尊搬?如果是集合是內(nèi)容復(fù)制的話叁鉴,集合里面的元素也是內(nèi)容復(fù)制么?
可變使用copy表示深拷貝佛寿,不可變集合類使用copy的時候是淺拷貝幌墓。
可變集合類、不可邊類型使用mutablecopy表示深拷貝
當(dāng)是淺拷貝的時候冀泻,容器的內(nèi)容是沒有復(fù)制的常侣。如果是深拷貝的話,容器的內(nèi)容都會收到一條copy消息弹渔,拷貝出新的內(nèi)容胳施,從新組成新的容器返回。
9.為什么IBOutlet修飾的UIView也適用weak關(guān)鍵字肢专?
在xib或者Sb拖控件時舞肆,其實控件就加載到了父控件的subviews數(shù)組里面焦辅,進(jìn)行了強引用,即使使用了weak椿胯,也不造成對象的釋放筷登。
10.nonatomic和atomic的區(qū)別?atomic是絕對的線程安全么哩盲?為什么前方?如果不是,那應(yīng)該如何實現(xiàn)廉油?
nonatomic:表示非原子惠险,不安全,但是效率高抒线。
atomic:表示原子行班巩,安全,但是效率低嘶炭。
atomic:不能絕對保證線程的安全趣竣,當(dāng)多線程同時訪問的時候,會造成線程不安全旱物∫B疲可以使用線程鎖來保證線程的安全。
11.UICollectionView自定義layout如何實現(xiàn)宵呛?
實現(xiàn)一個自定義layout的常規(guī)做法是繼承UICollectionViewLayout類单匣,然后重載下列方法:
-(CGSize)collectionViewContentSize
返回collectionView的內(nèi)容的尺寸
-(NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
返回rect中的所有的元素的布局屬性
返回的是包含UICollectionViewLayoutAttributes的NSArray
UICollectionViewLayoutAttributes可以是cell,追加視圖或裝飾視 圖的信息宝穗,通過不同的UICollectionViewLayoutAttributes初始化方法可以得到不同類型的UICollectionViewLayoutAttributes:
layoutAttributesForCellWithIndexPath:
layoutAttributesForSupplementaryViewOfKind:withIndexPath:
layoutAttributesForDecorationViewOfKind:withIndexPath:
-(UICollectionViewLayoutAttributes )layoutAttributesForItemAtIndexPath:(NSIndexPath )indexPath
返回對應(yīng)于indexPath的位置的cell的布局屬性
-(UICollectionViewLayoutAttributes )layoutAttributesForSupplementaryViewOfKind:(NSString )kind atIndexPath:(NSIndexPath *)indexPath
返回對應(yīng)于indexPath的位置的追加視圖的布局屬性户秤,如果沒有追加視圖可不重載
-(UICollectionViewLayoutAttributes * )layoutAttributesForDecorationViewOfKind:(NSString)decorationViewKind atIndexPath:(NSIndexPath )indexPath
返回對應(yīng)于indexPath的位置的裝飾視圖的布局屬性,如果沒有裝飾視圖可不重載
-(BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
當(dāng)邊界發(fā)生改變時逮矛,是否應(yīng)該刷新布局鸡号。如果YES則在邊界變化(一般是scroll到其他地方)時,將重新計算需要的布局信息须鼎。
12.用StoryBoard開發(fā)界面有什么弊端鲸伴?如何避免?
使用簡單邏輯頁面的跳轉(zhuǎn)是可以使用sb的晋控,開發(fā)比較塊汞窗。
但是SB對于邏輯項目比較復(fù)雜的時候,開發(fā)起來比較慢赡译。不適合多人合作開發(fā)仲吏;也不利于版本的梗系和后期的維護(hù)。使用sb在項目變異編譯的時候,也都會直接加載到內(nèi)存中裹唆,造成內(nèi)存的浪費誓斥。
可以使用xib來代替,編輯復(fù)雜邏輯界面時候可以使用純碼編寫许帐。
13.進(jìn)程和線程的區(qū)別岖食?同步異步的區(qū)別?并行和并發(fā)的區(qū)別舞吭?
進(jìn)程:是具有一定獨立功能的程序關(guān)于某個數(shù)據(jù)集合上的一次運行活動,進(jìn)程是系統(tǒng)進(jìn)行資源分配和調(diào)度的一個獨立單位.
線程:是進(jìn)程的一個實體,是CPU調(diào)度和分派的基本單位,它是比進(jìn)程更小的能獨立運行的基本單位.線程自己基本上不擁有系統(tǒng)資源,只擁有一點在運行中必不可少的資源(如程序計數(shù)器,一組寄存器和棧),但是它可與同屬一個進(jìn)程的其他的線程共享進(jìn)程所擁有的全部資源.
同步:阻塞當(dāng)前線程操作,不能開辟線程析珊。
異步:不阻礙線程繼續(xù)操作羡鸥,可以開辟線程來執(zhí)行任務(wù)。
并發(fā):當(dāng)有多個線程在操作時,如果系統(tǒng)只有一個CPU,則它根本不可能真正同時進(jìn)行一個以上的線程忠寻,它只能把CPU運行時間劃分成若干個時間段,再將時間 段分配給各個線程執(zhí)行惧浴,在一個時間段的線程代碼運行時,其它線程處于掛起狀奕剃。.這種方式我們稱之為并發(fā)(Concurrent)衷旅。
并行:當(dāng)系統(tǒng)有一個以上CPU時,則線程的操作有可能非并發(fā)。當(dāng)一個CPU執(zhí)行一個線程時纵朋,另一個CPU可以執(zhí)行另一個線程柿顶,兩個線程互不搶占CPU資源,可以同時進(jìn)行操软,這種方式我們稱之為并行(Parallel)嘁锯。
區(qū)別:并發(fā)和并行是即相似又有區(qū)別的兩個概念,并行是指兩個或者多個事件在同一時刻發(fā)生聂薪;而并發(fā)是指兩個或多個事件在同一時間間隔內(nèi)發(fā)生。在多道程序環(huán)境下,并發(fā)性是指在一段時間內(nèi)宏觀上有多個程序在同時運行都弹,但在單處理機系統(tǒng)中仙蚜,每一時刻卻僅能有一道程序執(zhí)行,故微觀上這些程序只能是分時地交替執(zhí)行翔悠。倘若在計算機系統(tǒng)中有多個處理機业崖,則這些可以并發(fā)執(zhí)行的程序便可被分配到多個處理機上,實現(xiàn)并行執(zhí)行蓄愁,即利用每個處理機來處理一個可并發(fā)執(zhí)行的程序腻要,這樣,多個程序便可以同時執(zhí)行涝登。
14.線程間通信雄家?
當(dāng)使用dispath-async函數(shù)開辟線程執(zhí)行任務(wù)的完成時,我們需要使用dispatch_async(dispatch_get_main_queue(), ^{ });函數(shù)會到主線程內(nèi)刷新UI。并完成通信
15.GCD的一些常用的函數(shù)趟济?(group乱投,barrier,信號量顷编,線程同步)
我們使用隊列組來開辟線程時戚炫,隊列組中的隊列任務(wù)是并發(fā),當(dāng)所有的隊列組中的所有任務(wù)完成時候媳纬,才可以調(diào)用隊列組完成任務(wù)双肤。
/**創(chuàng)建自己的隊列*/
dispatch_queue_t dispatchQueue = dispatch_queue_create("ted.queue.next", DISPATCH_QUEUE_CONCURRENT);
/**創(chuàng)建一個隊列組*/
dispatch_group_t dispatchGroup = dispatch_group_create();
/**將隊列任務(wù)添加到隊列組中*/
dispatch_group_async(dispatchGroup, dispatchQueue, ^(){
NSLog(@"dispatch-1");
});
/**將隊列任務(wù)添加到隊列組中*/
dispatch_group_async(dispatchGroup, dispatchQueue, ^(){
NSLog(@"dspatch-2");
});
/**隊列組完成調(diào)用函數(shù)*/
dispatch_group_notify(dispatchGroup, dispatch_get_main_queue(), ^(){
NSLog(@"end");
})
barrier:表示柵欄,當(dāng)在并發(fā)隊列里面使用柵欄時候钮惠,柵欄之前的并發(fā)任務(wù)開始并發(fā)執(zhí)行茅糜,執(zhí)行完畢后,執(zhí)行柵欄內(nèi)的任務(wù)素挽,等柵欄任務(wù)執(zhí)行完畢后蔑赘,再并發(fā)執(zhí)行柵欄后的任務(wù)。
dispatch_queue_t concurrentQueue = dispatch_queue_create("my.concurrent.queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(concurrentQueue, ^(){
NSLog(@"dispatch-1");
});
dispatch_async(concurrentQueue, ^(){
NSLog(@"dispatch-2");
});
dispatch_barrier_async(concurrentQueue, ^(){
NSLog(@"dispatch-barrier");
});
dispatch_async(concurrentQueue, ^(){
NSLog(@"dispatch-3");
});
dispatch_async(concurrentQueue, ^(){
NSLog(@"dispatch-4");
});
信號量:Semaphore是通過‘計數(shù)’的方式來標(biāo)識線程是否是等待或繼續(xù)執(zhí)行的预明。信號量
dispatch_semaphore_create(int) // 創(chuàng)建一個信號缩赛,并初始化信號的計數(shù)大小
/* 等待信號,并且判斷信號量撰糠,如果信號量計數(shù)大于等于你創(chuàng)建時候的信號量的計數(shù)酥馍,就可以通過,繼續(xù)執(zhí)行阅酪,并且將你傳入的信號計數(shù)減1物喷,
* 如果傳入的信號計數(shù)小于你創(chuàng)建的計數(shù),就表示等待遮斥,等待信號計數(shù)的變化
* 如果等待的時間超過你傳入的時間峦失,也會繼續(xù)下面操作
* 第一個參數(shù):semaphore 表示信號量
* 第二個參數(shù):表示等待的時間
* 返回int 如果傳入的信號計數(shù)大于等于你創(chuàng)建信號的計數(shù)時候,返回0. 反之术吗,返回的不等于0
*/
int result = dispatch_semaphore_wait(dispatch_semaphore_t semaphore,time outTime);// 表示等待尉辑,也是阻礙線程
// 表示將信號技術(shù)+1
dispatch_semaphore_signl(dispatch_semaphore_t semaphore);
實現(xiàn)線程的同步的方法:串行隊列,分組较屿,信號量隧魄。也是可以使用并發(fā)隊列。
//加入隊列
dispatch_async(concurrentQueue, ^{
//1.先去網(wǎng)上下載圖片
dispatch_sync(concurrentQueue, ^{
});
//2.在主線程展示到界面里
dispatch_sync(dispatch_get_main_queue(), ^{
});
});
16.如何使用隊列來避免資源搶奪隘蝎?
當(dāng)我們使用多線程來訪問同一個數(shù)據(jù)的時候购啄,就有可能造成數(shù)據(jù)的不準(zhǔn)確性。這個時候我么可以使用線程鎖的來來綁定嘱么。也是可以使用串行隊列來完成狮含。如:fmdb就是使用FMDatabaseQueue,來解決多線程搶奪資源。
17.數(shù)據(jù)持久化的幾個方案(fmdb用沒用過)
持久化方案:
plist,存儲字典几迄,數(shù)組比較好用
preference:偏好設(shè)置蔚龙,實質(zhì)也是plist
NSKeyedArchiver:歸檔,可以存儲對象
sqlite:數(shù)據(jù)庫映胁,經(jīng)常使用第三方來操作木羹,也就是fmdb
coreData:也是數(shù)據(jù)庫儲存,蘋果官方的
18.說一下appdelegate的幾個方法解孙?從后臺到前臺調(diào)用了哪些方法坑填?第一次啟動調(diào)用了哪些方法?從前臺到后臺調(diào)用了哪些方法弛姜?
19.NSCache優(yōu)于NSDictionary的幾點脐瑰?
1.nscache 是可以自動釋放內(nèi)存的。
2.nscache是線程安全的娱据,我們可以在不同的線程中添加,刪除和查詢緩存中的對象盅惜。
3.一個緩存對象不會拷貝key對象中剩。
20.知不知道Designated Initializer?使用它的時候有什么需要注意的問題抒寂?
個人理解:初始化函數(shù)结啼,如果你想自定義初始化函數(shù)時,也是必須要初始化父類屈芜,以來保證可以繼承父類的一些方法或者屬性郊愧。
Designated Initializer
21.實現(xiàn)description方法能取到什么效果?
description是nsobject的一個實例的方法井佑,返回的是一個nsstring属铁。當(dāng)我們使用nslog打印的時候,打印出來的一般都是對象的內(nèi)存地址躬翁,如果我們實現(xiàn)description方法時焦蘑,我們就可以使用nslog打印對象的時候,我們可以把它里面的屬性值和內(nèi)存地址一起打印出來.打印什么盒发,就是看你寫什么了例嘱。
-(NSString *)description{
NSString * string = [NSString stringWithFormat:@"<Person:內(nèi)存地址:%p name = %@ age = %ld>",self,self.name,self.age];
return string;
}
22.objc使用什么機制管理對象內(nèi)存?
使用內(nèi)存管理計數(shù)器宁舰,來管理內(nèi)存的拼卵。當(dāng)內(nèi)存管理計數(shù)器為0的時候,對象就會被釋放蛮艰。
中級
Block
1.block的實質(zhì)是什么腋腮?一共有幾種block?都是什么情況下生成的?
block:本質(zhì)就是一個object-c對象.
block:存儲位置低葫,可能分為3個地方:代碼去详羡,堆區(qū)、棧區(qū)(ARC情況下會自動拷貝到堆區(qū)嘿悬,因此ARC下只能有兩個地方:代碼去实柠、堆區(qū))
代碼區(qū):不訪問棧區(qū)的變量(如局部變量),且不訪問堆區(qū)的變量(alloc創(chuàng)建的對象)善涨,此時block存放在代碼去窒盐。
堆區(qū):訪問了處于棧區(qū)的變量,或者堆區(qū)的變量钢拧,此時block存放在堆區(qū)蟹漓。–需要注意實際是放在棧區(qū),在ARC情況下會自動拷貝到堆區(qū)源内,如果不是ARC則存放在棧區(qū)葡粒,所在函數(shù)執(zhí)行完畢就回釋放,想再外面調(diào)用需要用copy指向它膜钓,這樣就拷貝到了堆區(qū)嗽交,strong屬性不會拷貝、會造成野指針錯區(qū)颂斜。
2.為什么在默認(rèn)情況下無法修改被block捕獲的變量夫壁? __block都做了什么?
默認(rèn)情況下沃疮,block里面的變量盒让,拷貝進(jìn)去的是變量的值,而不是指向變量的內(nèi)存的指針司蔬。
當(dāng)使用__block
修飾后的變量邑茄,拷貝到block
里面的就是指向變量的指針,所以我們就可以修改變量的值俊啼。
3.模擬一下循環(huán)引用的一個情況撩扒?block實現(xiàn)界面反向傳值如何實現(xiàn)?
Person *p = [[Person alloc]init];
[p setPersonBlock:^(NSString *str) {
p.name = str;
}];
Runtime
1.objc在向一個對象發(fā)送消息時吨些,發(fā)生了什么搓谆?
根據(jù)對象的
isa
指針找到類對象id
,在查詢類對象里面的methodLists
方法函數(shù)列表豪墅,如果沒有在好到泉手,在沿著superClass
,尋找父類,再在父類methodLists
方法列表里面查詢偶器,最終找到SEL
,根據(jù)id
和SEL
確認(rèn)IMP
(指針函數(shù)),在發(fā)送消息斩萌;
3.什么時候會報unrecognized selector錯誤缝裤?iOS有哪些機制來避免走到這一步?
當(dāng)發(fā)送消息的時候颊郎,我們會根據(jù)類里面的
methodLists
列表去查詢我們要動用的SEL
,當(dāng)查詢不到的時候憋飞,我們會一直沿著父類查詢,當(dāng)最終查詢不到的時候我們會報unrecognized selector錯誤
當(dāng)系統(tǒng)查詢不到方法的時候姆吭,會調(diào)用+(BOOL)resolveInstanceMethod:(SEL)sel
動態(tài)解釋的方法來給我一次機會來添加榛做,調(diào)用不到的方法∧诶辏或者我們可以再次使用-(id)forwardingTargetForSelector:(SEL)aSelector
重定向的方法來告訴系統(tǒng)检眯,該調(diào)用什么方法,一來保證不會崩潰昆淡。
4.能否向編譯后得到的類中增加實例變量锰瘸?能否向運行時創(chuàng)建的類中添加實例變量?為什么昂灵?
1.不能向編譯后得到的類增加實例變量
2.能向運行時創(chuàng)建的類中添加實例變量
解釋:
1.編譯后的類已經(jīng)注冊在runtime中,類結(jié)構(gòu)體中的objc_ivar_list實例變量的鏈表和instance_size實例變量的內(nèi)存大小已經(jīng)確定,runtime會調(diào)用class_setvarlayout或class_setWeaklvarLayout來處理strong weak引用.所以不能向存在的類中添加實例變量
2.運行時創(chuàng)建的類是可以添加實例變量,調(diào)用class_addIvar函數(shù).但是的在調(diào)用objc_allocateClassPair之后,objc_registerClassPair之前,原因同上.
5.runtime如何實現(xiàn)weak變量的自動置nil避凝?
runtime 對注冊的類, 會進(jìn)行布局眨补,對于 weak 對象會放入一個 hash 表中管削。 用 weak 指向的對象內(nèi)存地址作為 key,當(dāng)此對象的引用計數(shù)為0的時候會 dealloc渤涌,假如 weak 指向的對象內(nèi)存地址是a佩谣,那么就會以a為鍵把还, 在這個 weak 表中搜索实蓬,找到所有以a為鍵的 weak 對象,從而設(shè)置為 nil吊履。
6.給類添加一個屬性后安皱,在類結(jié)構(gòu)體里哪些元素會發(fā)生變化?
instance_size :實例的內(nèi)存大小
objc_ivar_list *ivars:屬性列表
RunLoop
1.runloop是來做什么的艇炎?runloop和線程有什么關(guān)系酌伊?主線程默認(rèn)開啟了runloop么?子線程呢缀踪?
runloop:字面意思就是跑圈居砖,其實也就是一個循環(huán)跑圈,用來處理線程里面的事件和消息驴娃。
runloop和線程的關(guān)系:每個線程如果想繼續(xù)運行奏候,不被釋放,就必須有一個runloop來不停的跑圈唇敞,以來處理線程里面的各個事件和消息蔗草。
主線程默認(rèn)是開啟一個runloop咒彤。也就是這個runloop才能保證我們程序正常的運行。子線程是默認(rèn)沒有開始runloop的
2.runloop的mode是用來做什么的咒精?有幾種mode镶柱?
model:是runloop里面的模式,不同的模式下的runloop處理的事件和消息有一定的差別模叙。
系統(tǒng)默認(rèn)注冊了5個Mode:
(1)kCFRunLoopDefaultMode: App的默認(rèn) Mode歇拆,通常主線程是在這個 Mode 下運行的。
(2)UITrackingRunLoopMode: 界面跟蹤 Mode向楼,用于 ScrollView 追蹤觸摸滑動查吊,保證界面滑動時不受其他 Mode 影響。
(3)UIInitializationRunLoopMode: 在剛啟動 App 時第進(jìn)入的第一個 Mode湖蜕,啟動完成后就不再使用逻卖。
(4)GSEventReceiveRunLoopMode: 接受系統(tǒng)事件的內(nèi)部 Mode,通常用不到昭抒。
(5)kCFRunLoopCommonModes: 這是一個占位的 Mode评也,沒有實際作用。
注意iOS 對以上5中model進(jìn)行了封裝
NSDefaultRunLoopMode;
NSRunLoopCommonModes
3.為什么把NSTimer對象以NSDefaultRunLoopMode(kCFRunLoopDefaultMode)添加到主運行循環(huán)以后灭返,滑動scrollview的時候NSTimer卻不動了盗迟?
nstime對象是在
NSDefaultRunLoopMode
下面調(diào)用消息的,但是當(dāng)我們滑動scrollview的時候熙含,NSDefaultRunLoopMode
模式就自動切換到UITrackingRunLoopMode
模式下面罚缕,卻不可以繼續(xù)響應(yīng)nstime發(fā)送的消息。所以如果想在滑動scrollview的情況下面還調(diào)用nstime的消息怎静,我們可以把nsrunloop的模式更改為NSRunLoopCommonModes
4.蘋果是如何實現(xiàn)Autorelease Pool的邮弹?
Autorelease Pool作用:緩存池,可以避免我們經(jīng)常寫relase的一種方式蚓聘。其實就是延遲release腌乡,將創(chuàng)建的對象,添加到最近的autoreleasePool中夜牡,等到autoreleasePool作用域結(jié)束的時候与纽,會將里面所有的對象的引用計數(shù)器-1.
autorelease
類結(jié)構(gòu)
1.isa指針?(對象的isa塘装,類對象的isa急迂,元類的isa都要說)
在oc中,類也是對象蹦肴,所屬元類僚碎。所以經(jīng)常說:
萬物皆對象
對象的isa指針指向所屬的類
類的isa指針指向了所屬的元類
元類的isa指向了根元類,根元類指向了自己冗尤。
2.類方法和實例方法有什么區(qū)別听盖?
調(diào)用的方式不同胀溺,類方法必須使用類調(diào)用,在方法里面不能調(diào)用屬性皆看,類方法里面也必須調(diào)用類方法仓坞。存儲在元類結(jié)構(gòu)體里面的
methodLists
里面
實例方法必須使用實例對象調(diào)用,可以在實例方法里面使用屬性腰吟,實例方法也必須調(diào)用實例方法无埃。存儲在類結(jié)構(gòu)體里面的methodLists
里面
3.介紹一下分類,能用分類做什么毛雇?內(nèi)部是如何實現(xiàn)的嫉称?它為什么會覆蓋掉原來的方法?
category:我們可以給類或者系統(tǒng)類添加實例方法方法灵疮。我們添加的實例方法织阅,會被動態(tài)的添加到類結(jié)構(gòu)里面的
methodList
列表里面。categort
4.運行時能增加成員變量么震捣?能增加屬性么荔棉?如果能,如何增加蒿赢?如果不能润樱,為什么?
可以添加屬性的羡棵,但必須我們實現(xiàn)它的
getter
和setter
方法壹若。但是沒有添加帶下滑線同名的成員變量
但是我們使用runtime
我們就可以實現(xiàn)添加成員變量方法如下
- (void)setName:(NSString *)name {
/**
* 為某個類關(guān)聯(lián)某個對象
*
* @param object#> 要關(guān)聯(lián)的對象 description#>
* @param key#> 要關(guān)聯(lián)的屬性key description#>
* @param value#> 你要關(guān)聯(lián)的屬性 description#>
* @param policy#> 添加的成員變量的修飾符 description#>
*/
objc_setAssociatedObject(self, @selector(name), name, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (NSString *)name {
/**
* 獲取到某個類的某個關(guān)聯(lián)對象
*
* @param object#> 關(guān)聯(lián)的對象 description#>
* @param key#> 屬性的key值 description#>
*/
return objc_getAssociatedObject(self, @selector(name));
}
5.objc中向一個nil對象發(fā)送消息將會發(fā)生什么?(返回值是對象皂冰,是標(biāo)量店展,結(jié)構(gòu)體)
? 如果一個方法返回值是一個對象,那么發(fā)送給nil的消息將返回0(nil)灼擂。例如:Person * motherInlaw = [ aPerson spouse] mother]; 如果spouse對象為nil壁查,那么發(fā)送給nil的消息mother也將返回nil觉至。
? 如果方法返回值為指針類型剔应,其指針大小為小于或者等于sizeof(void*),float语御,double峻贮,long double 或者long long的整型標(biāo)量,發(fā)送給nil的消息將返回0应闯。
? 如果方法返回值為結(jié)構(gòu)體纤控,正如在《Mac OS X ABI 函數(shù)調(diào)用指南》,發(fā)送給nil的消息將返回0碉纺。結(jié)構(gòu)體中各個字段的值將都是0船万。其他的結(jié)構(gòu)體數(shù)據(jù)類型將不是用0填充的刻撒。
? 如果方法的返回值不是上述提到的幾種情況,那么發(fā)送給nil的消息的返回值將是未定義的耿导。
高級
1.UITableview的優(yōu)化方法(緩存高度声怔,異步繪制,減少層級舱呻,hide醋火,避免離屏渲染)
緩存高度:當(dāng)我們創(chuàng)建frame模型的時候,計算出來cell的高度的時候箱吕,我們可以將cell的高度緩存到字典里面芥驳,以cell的
indexpath
和Identifier
作為為key。
NSString *key = [[HeightCache shareHeightCache] makeKeyWithIdentifier:@"YwywProductGradeCell" indexPath:indexPath];
if ([[HeightCache shareHeightCache] existInCacheByKey:key]) {
return [[HeightCache shareHeightCache] heightFromCacheWithKey:key];
}else{
YwywProductGradeModelFrame *modelFrame = self.gradeArray[indexPath.row];
[[HeightCache shareHeightCache] cacheHieght:modelFrame.cellHight key:key];
return modelFrame.cellHight;
}
異步繪制茬高、減少層級:目前還不是很清楚
hide:個人理解應(yīng)該是hidden
吧兆旬,把可能會用到的控件都創(chuàng)建出來,根據(jù)不同的情況去隱藏或者顯示出來怎栽。
避免離屏渲染:只要不是同時使用邊框/邊框顏色以及圓角的時候
爵憎,都可以使用layer直接設(shè)置。不會造成離屏渲染婚瓜。
2.有沒有用過運行時宝鼓,用它都能做什么?(交換方法巴刻,創(chuàng)建類愚铡,給新創(chuàng)建的類增加方法,改變isa指針)
交換方式:一般寫在類的+(void)load方法里面
/** 獲取原始setBackgroundColor方法 */
Method originalM = class_getInstanceMethod([self class], @selector(setBackgroundColor:));
/** 獲取自定義的pb_setBackgroundColor方法 */
Method exchangeM = class_getInstanceMethod([self class], @selector(pb_setBackgroundColor:));
/** 交換方法 */
method_exchangeImplementations(originalM, exchangeM);
創(chuàng)建類:
Class MyClass = objc_allocateClassPair([NSObject class], "Person", 0);
添加方法
/**參數(shù)一胡陪、類名參數(shù)
二沥寥、SEL 添加的方法名字參數(shù)
三、IMP指針 (IMP就是Implementation的縮寫柠座,它是指向一個方法實現(xiàn)的指針邑雅,每一個方法都有一個對應(yīng)的IMP)
參數(shù)四、其中types參數(shù)為"i@:@“妈经,按順序分別表示:具體類型可參照[官方文檔](https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html)i 返回值類型int淮野,若是v則表示void@ 參數(shù)id(self): SEL(_cmd)@ id(str)
V@:表示返回值是void 帶有SEL參數(shù) (An object (whether statically typed or typed id))
*/
class_addMethod(Person, @selector(addMethodForMyClass:), (IMP)addMethodForMyClass, "V@:");
添加實例變量
/**參數(shù)一、類名參數(shù)
二吹泡、屬性名稱參數(shù)
三骤星、開辟字節(jié)長度參數(shù)
四、對其方式參數(shù)
五爆哑、參數(shù)類型 “@” 官方解釋 An object (whether statically typed or typed id) (對象 靜態(tài)類型或者id類型) 具體類型可參照[官方文檔](https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html)return: BOOL 是否添加成功
*/
BOOL isSuccess = class_addIvar(Person, "name", sizeof(NSString *), 0, "@");
isSuccess?NSLog(@"添加變量成功"):NSLog(@"添加變量失敗");
3.看過哪些第三方框架的源碼洞难?都是如何實現(xiàn)的?(如果沒有揭朝,問一下多圖下載的設(shè)計)
4.SDWebImage的緩存策略队贱?
sd加載一張圖片的時候色冀,會先在內(nèi)存里面查找是否有這張圖片,如果沒有會根據(jù)圖片的md5(url)后的名稱去沙盒里面去尋找柱嫌,是否有這張圖片呐伞,如果沒有會開辟線程去下載,下載完畢后加載到imageview上面慎式,并md(url)為名稱緩存到沙盒里面伶氢。
5.AFN為什么添加一條常駐線程?
AFN 目的:就是開辟線程請求網(wǎng)絡(luò)數(shù)據(jù)瘪吏。如果沒有常住線程的話癣防,就會每次請求網(wǎng)絡(luò)就去開辟線程,完成之后銷毀開辟線程掌眠,這樣就造成資源的浪費蕾盯,開辟一條常住線程,就可以避免這種浪費蓝丙,我們可以在每次的網(wǎng)絡(luò)請求都添加到這條線程级遭。
6.KVO的使用?實現(xiàn)原理渺尘?(為什么要創(chuàng)建子類來實現(xiàn))
kvo:鍵值觀察挫鸽,根據(jù)鍵對應(yīng)的值的變化,來調(diào)用方法鸥跟。
注冊觀察者:addObserver:forKeyPath:options:context:
實現(xiàn)觀察者:observeValueForKeyPath:ofObject:change:context:
移除觀察者:removeObserver:forKeyPath:(對象銷毀丢郊,必須移除觀察者)
注意
使用kvo監(jiān)聽A對象的時候,監(jiān)聽的本質(zhì)不是這個A對象医咨,而是系統(tǒng)創(chuàng)建的一個中間對象NSKVONotifying_A
并繼承A對象枫匾,并且A對象的isa指針指向的也不是A的類,而是這個NSKVONotifying_A
對象
kvo詳解
kvo詳解2
7.KVC的使用拟淮?實現(xiàn)原理干茉?(KVC拿到key以后,是如何賦值的很泊?知不知道集合操作符角虫,能不能訪問私有屬性,能不能直接訪問_ivar)
kvc:鍵值賦值撑蚌,使用最多的即使字典轉(zhuǎn)模型上遥。利用runtime獲取對象的所有成員變量搏屑, 在根據(jù)kvc鍵值賦值争涌,進(jìn)行字典轉(zhuǎn)模型
setValue: forKey: 只查找本類里面的屬性
setValue: forKeyPath:會查找本類里面屬性,沒有會繼續(xù)查找父類里面屬性辣恋。
kvc詳解
項目
1.有已經(jīng)上線的項目么亮垫?
2.項目里哪個部分是你完成的模软?(找一個亮點問一下如何實現(xiàn)的)
3.開發(fā)過程中遇到過什么困難,是如何解決的饮潦?
學(xué)習(xí)
4.遇到一個問題完全不能理解的時候燃异,是如何幫助自己理解的?舉個例子继蜡?
5.有看書的習(xí)慣么回俐?最近看的一本是什么書?有什么心得稀并?
6.有沒有使用一些筆記軟件仅颇?會在多平臺同步以及多渠道采集么?(如果沒有碘举,問一下是如何復(fù)習(xí)知識的)
7.有沒有使用清單類忘瓦,日歷類的軟件?(如果沒有引颈,問一下是如何安排耕皮,計劃任務(wù)的)
8.平常看博客么蝙场?有沒有自己寫過凌停?(如果寫,有哪些收獲售滤?如果沒有寫苦锨,問一下不寫的原因)
以上就是全部的面試題,后面的面試題趴泌,就該根據(jù)個人的情況來回答了舟舒。
以上的面試回答,有的是根據(jù)自己的知識儲備回答嗜憔,有的也是小編百度的秃励。
以上的回答也不知道對與錯,歡迎大家發(fā)表自己的看法吉捶。
重要事情說三遍