1.為什么說Objective-C是一門動(dòng)態(tài)的語言?
1.object-c類的類型和數(shù)據(jù)變量的類型都是在運(yùn)行是確定的诽里,而不是在編譯時(shí)確定谤狡。例如:多態(tài)特性卧檐,我們可以使用父類對(duì)象來指向子類對(duì)象,并且可以用來調(diào)用子類的方法捕仔。運(yùn)行時(shí)(runtime)特性,我們可以動(dòng)態(tài)的添加方法榜跌,或者替換方法盅粪。
2.講一下MVC和MVVM,MVP础浮?
MVC:簡單來說就是霸旗,邏輯戚揭、試圖、數(shù)據(jù)進(jìn)行分層精居,實(shí)現(xiàn)解耦靴姿。
MVVM:是Model-View-ViewMode模式的簡稱磁滚。由視圖(View)、視圖模型(ViewModel)维雇、模型(Model)三部分組成.比MVC更加釋放控制器臃腫,將一部分邏輯(耗時(shí)逸贾,公共方法津滞,網(wǎng)絡(luò)請(qǐng)求等)和數(shù)據(jù)的處理等操作從控制器里面搬運(yùn)到ViewModel中
MVVM的特點(diǎn):
低耦合。View可以獨(dú)立于Model變化和修改触徐,一個(gè)ViewModel可以綁定到不同的View上,當(dāng)View變化的時(shí)候Model可以不變嗜诀,當(dāng)Model變化的時(shí)候View也可以不變隆敢。
可重用性崔慧』淌遥可以把一些視圖的邏輯放在ViewModel里面,讓很多View重用這段視圖邏輯悼泌。
獨(dú)立開發(fā)夹界。開發(fā)人員可以專注與業(yè)務(wù)邏輯和數(shù)據(jù)的開發(fā)(ViewModel)可柿。設(shè)計(jì)人員可以專注于界面(View)的設(shè)計(jì)。
可測試性营密∑捞可以針對(duì)ViewModel來對(duì)界面(View)進(jìn)行測試
MVP:本小編沒有接觸,希望可以得到大家的幫助被去。可以在下面留言。
3.為什么代理要用weak踪央?代理的delegate和dataSource有什么區(qū)別瓢阴?block和代理的區(qū)別?
代理是使用weak來修飾的。1.使用weak是為了避免循環(huán)引用液斜。2.當(dāng)使用weak修飾的屬性少漆,當(dāng)對(duì)象釋放的時(shí)候硼被,系統(tǒng)會(huì)對(duì)屬性賦值nil,object-c有個(gè)特性就是對(duì)nil對(duì)象發(fā)送消息也就是調(diào)用方法嚷硫,不會(huì)cash。
delegate:表示代理脆贵,代理可以讓A對(duì)象通知B對(duì)象起暮,我(A)發(fā)生的變化鞋怀,前提B遵循了A的代理,并且實(shí)現(xiàn)了A的代理方法焙矛。
dataSource:表示數(shù)據(jù)源残腌,如果A對(duì)象聲明了數(shù)據(jù)源,當(dāng)我們創(chuàng)建A對(duì)象的時(shí)候蟆盹,我們就該實(shí)現(xiàn)數(shù)據(jù)源,來告訴A峰档,他所需要的一些數(shù)據(jù)讥巡。例如:tableView數(shù)據(jù)源方法舔哪,需要告訴它,我要實(shí)現(xiàn)幾組cell抬驴,每組cell多少行cell布持,實(shí)現(xiàn)的cell什么樣式陕悬,什么內(nèi)容
同樣delegate和??dataSource,都是可以使用require和optional來修飾的。
代理和Block的區(qū)別
相同點(diǎn):代理和Block大多是我們都可以用來做倒序傳值的芙委。我們都得注意避免循環(huán)引用灌侣。
不同點(diǎn):代理使用weak修飾裂问,代理必須先聲明方法。當(dāng)我們調(diào)用代理的時(shí)候要判斷是否已經(jīng)實(shí)現(xiàn)痊乾。
block:使用的是copy來修飾哪审,block保存的是一段代碼虑瀑,其實(shí)也就是一個(gè)函數(shù)滴须。當(dāng)我們調(diào)用block的時(shí)候要判斷是否已經(jīng)實(shí)現(xiàn)扔水。
4.屬性的實(shí)質(zhì)是什么魔市?包括哪幾個(gè)部分赵哲?屬性默認(rèn)的關(guān)鍵字都有哪些誓竿?@dynamic關(guān)鍵字和@synthesize關(guān)鍵字是用來做什么的筷屡?
屬性是描述類的特征簸喂,也就是具備什么特性。三個(gè)部分扼倘,帶下劃線的成員變量再菊,get颜曾、setter方法。
默認(rèn)關(guān)鍵字:readwrite稠诲,assign, atomic;
@dynamic :修飾的屬性臀叙,其getter和setter方法編譯器是不會(huì)自動(dòng)幫你生成价卤。必須自己是實(shí)現(xiàn)的。
@synthesize:修飾的屬性稳其,其getter和setter方法編譯器是會(huì)自動(dòng)幫你生成。不必自己實(shí)現(xiàn)煤傍,可以指定與屬性相對(duì)應(yīng)的成員變量嘱蛋。
5.屬性的默認(rèn)關(guān)鍵字是什么洒敏?
默認(rèn)關(guān)鍵字:readwrite,assign, atomic;
6.NSString為什么要用copy關(guān)鍵字郭毕,如果用strong會(huì)有什么問題函荣?(注意:這里沒有說用strong就一定不行傻挂。使用copy和strong是看情況而定的
眾所周知,我們知道兽肤,可變類型(NSMutableArray,NSMutableString等)是不可邊類型(NSString,NSArray等)的子類资铡,因?yàn)槎鄳B(tài)的原因幢码,我們可以使用賦值指向子類對(duì)象,也就是我們可以使用不可邊類型去接受可變類型宛官。
1.當(dāng)我們使用strong修飾A不可邊類型的時(shí)候底洗,并且使用B可變類型給A賦值咕娄,再去修改可變類型B值的時(shí)候,A所指向的值也會(huì)發(fā)生改變费变。引文strong只是讓創(chuàng)建的對(duì)象引用計(jì)數(shù)器+1挚歧,并返回當(dāng)前對(duì)象的內(nèi)容地址,當(dāng)我們修改B指向的內(nèi)容的時(shí)候在张,A指向的內(nèi)容也同樣發(fā)生了改變矮慕,因?yàn)樗麄冎赶虻膬?nèi)存地址是相同的,是一份內(nèi)容痴鳄。
2.當(dāng)我們使用copy修飾A不可邊類型的時(shí)候,并且使用B可變類型給A賦值螺句,再去修改可變類型B值的時(shí)候槽华,A所指向的值不會(huì)發(fā)生改變猫态。因?yàn)楫?dāng)時(shí)用copy的修飾的時(shí)候亲雪,會(huì)拷貝一份內(nèi)容出來疚膊,并且返回指針給A,當(dāng)我們修改B指向的內(nèi)容的時(shí)候灌砖,A指向的內(nèi)容是沒有發(fā)生改變的基显。因?yàn)锳指向的內(nèi)存地址和B指向的內(nèi)存地址是不相同的善炫,是兩份內(nèi)容
3.copy修飾不可邊類型(NSString,NSArray等)的時(shí)候,且使用不可邊類型進(jìn)行賦值宪萄,表示淺拷貝榨惰,只拷貝一份指針,和strong修飾一樣聊记,當(dāng)修飾的是可變類型(NSMutableArray,NSMutableString等)的時(shí)候排监,表示深拷貝杰捂,直接拷貝新一份內(nèi)容,到內(nèi)存中挨队。表示兩份內(nèi)容盛垦。
7.如何令自己所寫的對(duì)象具有拷貝功能?
必須遵循nscopying協(xié)議瓤漏,如果想實(shí)現(xiàn)可變和不可邊拷貝時(shí),必須同時(shí)遵循nscoping和nsmutablecoping協(xié)議蝶俱。并且實(shí)現(xiàn)
- (id)copyWithZone:(NSZone *)zone;
8.可變集合類 和 不可變集合類的 copy 和 mutablecopy有什么區(qū)別榨呆?如果是集合是內(nèi)容復(fù)制的話庸队,集合里面的元素也是內(nèi)容復(fù)制么?
可變使用copy表示深拷貝浅侨,不可變集合類使用copy的時(shí)候是淺拷貝如输。
可變集合類使用mutablecopy表示深拷貝,不可變集合類使用copy的時(shí)候是淺拷貝澳化。
關(guān)于容器實(shí)現(xiàn)copy 或 metableCopy 缎谷,容器內(nèi)元素默認(rèn)都是 指針拷貝,不是內(nèi)容復(fù)制灶似。
9.為什么IBOutlet修飾的UIView也適用weak關(guān)鍵字?
在xib或者Sb拖控件時(shí)希痴,其實(shí)控件就加載到了父控件的subviews數(shù)組里面砌创,進(jìn)行了強(qiáng)引用鲫懒,即使使用了weak,也不造成對(duì)象的釋放甲献。
10.nonatomic和atomic的區(qū)別颂翼?atomic是絕對(duì)的線程安全么疚鲤?為什么缘挑?如果不是,那應(yīng)該如何實(shí)現(xiàn)诲宇?
nonatomic:表示非原子姑蓝,不安全吕粗,但是效率高。
atomic:表示原子行宙暇,安全占贫,但是效率定。
atomic:不能絕對(duì)保證線程的安全瞳收,當(dāng)多線程同時(shí)訪問的時(shí)候厢汹,會(huì)造成線程不安全】咏常可以使用線程鎖來保證線程的安全。
11.UICollectionView自定義layout如何實(shí)現(xiàn)夹纫?
實(shí)現(xiàn)一個(gè)自定義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
返回對(duì)應(yīng)于indexPath的位置的cell的布局屬性
-(UICollectionViewLayoutAttributes )layoutAttributesForSupplementaryViewOfKind:(NSString )kind atIndexPath:(NSIndexPath *)indexPath
返回對(duì)應(yīng)于indexPath的位置的追加視圖的布局屬性锄开,如果沒有追加視圖可不重載
-(UICollectionViewLayoutAttributes * )layoutAttributesForDecorationViewOfKind:(NSString)decorationViewKind atIndexPath:(NSIndexPath )indexPath
返回對(duì)應(yīng)于indexPath的位置的裝飾視圖的布局屬性萍悴,如果沒有裝飾視圖可不重載
-(BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
當(dāng)邊界發(fā)生改變時(shí)癣诱,是否應(yīng)該刷新布局袜香。如果YES則在邊界變化(一般是scroll到其他地方)時(shí),將重新計(jì)算需要的布局信息实抡。
12.用StoryBoard開發(fā)界面有什么弊端?如何避免艺蝴?
使用簡單邏輯頁面的跳轉(zhuǎn)是可以使用sb的鸟废,開發(fā)比較塊。
但是SB對(duì)于邏輯項(xiàng)目比較復(fù)雜的時(shí)候缩擂,開發(fā)起來比較慢胯盯。不適合多人合作開發(fā)计露;也不利于版本的梗系和后期的維護(hù)。使用sb在項(xiàng)目變異編譯的時(shí)候叉趣,也都會(huì)直接加載到內(nèi)存中疗杉,造成內(nèi)存的浪費(fèi)蚕礼。
可以使用xib來代替,編輯復(fù)雜邏輯界面時(shí)候可以使用純碼編寫朝聋。
13.進(jìn)程和線程的區(qū)別囤躁?同步異步的區(qū)別割以?并行和并發(fā)的區(qū)別应媚?
進(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è)實(shí)體,是CPU調(diào)度和分派的基本單位,它是比進(jìn)程更小的能獨(dú)立運(yùn)行的基本單位.線程自己基本上不擁有系統(tǒng)資源,只擁有一點(diǎn)在運(yùn)行中必不可少的資源(如程序計(jì)數(shù)器,一組寄存器和棧),但是它可與同屬一個(gè)進(jìn)程的其他的線程共享進(jìn)程所擁有的全部資源.
同步:阻塞當(dāng)前線程操作中姜,不能開辟線程跟伏。
異步:不阻礙線程繼續(xù)操作受扳,可以開辟線程來執(zhí)行任務(wù)兔跌。
并發(fā):當(dāng)有多個(gè)線程在操作時(shí),如果系統(tǒng)只有一個(gè)CPU,則它根本不可能真正同時(shí)進(jìn)行一個(gè)以上的線程坟桅,它只能把CPU運(yùn)行時(shí)間劃分成若干個(gè)時(shí)間段,再將時(shí)間 段分配給各個(gè)線程執(zhí)行,在一個(gè)時(shí)間段的線程代碼運(yùn)行時(shí)赖舟,其它線程處于掛起狀夸楣。.這種方式我們稱之為并發(fā)(Concurrent)豫喧。
并行:當(dāng)系統(tǒng)有一個(gè)以上CPU時(shí),則線程的操作有可能非并發(fā)。當(dāng)一個(gè)CPU執(zhí)行一個(gè)線程時(shí)劲腿,另一個(gè)CPU可以執(zhí)行另一個(gè)線程鸟妙,兩個(gè)線程互不搶占CPU資源重父,可以同時(shí)進(jìn)行,這種方式我們稱之為并行(Parallel)矿辽。
區(qū)別:并發(fā)和并行是即相似又有區(qū)別的兩個(gè)概念郭厌,并行是指兩個(gè)或者多個(gè)事件在同一時(shí)刻發(fā)生折柠;而并發(fā)是指兩個(gè)或多個(gè)事件在同一時(shí)間間隔內(nèi)發(fā)生。在多道程序環(huán)境下前塔,并發(fā)性是指在一段時(shí)間內(nèi)宏觀上有多個(gè)程序在同時(shí)運(yùn)行,但在單處理機(jī)系統(tǒng)中食零,每一時(shí)刻卻僅能有一道程序執(zhí)行寂屏,故微觀上這些程序只能是分時(shí)地交替執(zhí)行。倘若在計(jì)算機(jī)系統(tǒng)中有多個(gè)處理機(jī)冈爹,則這些可以并發(fā)執(zhí)行的程序便可被分配到多個(gè)處理機(jī)上频伤,實(shí)現(xiàn)并行執(zhí)行芝此,即利用每個(gè)處理機(jī)來處理一個(gè)可并發(fā)執(zhí)行的程序,這樣岸更,多個(gè)程序便可以同時(shí)執(zhí)行膊升。
14.線程間通信评肆?
當(dāng)使用dispath-async函數(shù)開辟線程執(zhí)行任務(wù)的完成時(shí)溺蕉,我們需要使用dispatch_async(dispatch_get_main_queue(), ^{ });函數(shù)會(huì)到主線程內(nèi)刷新UI硼砰。并完成通信
15.GCD的一些常用的函數(shù)?(group则剃,barrier管怠,信號(hào)量,線程同步)
我們使用隊(duì)列組來開辟線程時(shí)渤弛,隊(duì)列組中的隊(duì)列任務(wù)是并發(fā),當(dāng)所有的隊(duì)列組中的所有任務(wù)完成時(shí)候鹿驼,才可以調(diào)用隊(duì)列組完成任務(wù)畜晰。
/**創(chuàng)建自己的隊(duì)列*/
dispatch_queue_t dispatchQueue = dispatch_queue_create("ted.queue.next", DISPATCH_QUEUE_CONCURRENT);
/**創(chuàng)建一個(gè)隊(duì)列組*/
dispatch_group_t dispatchGroup = dispatch_group_create();
/**將隊(duì)列任務(wù)添加到隊(duì)列組中*/
dispatch_group_async(dispatchGroup, dispatchQueue, ^(){
? ? NSLog(@"dispatch-1");
});
? /**將隊(duì)列任務(wù)添加到隊(duì)列組中*/
dispatch_group_async(dispatchGroup, dispatchQueue, ^(){
? ? NSLog(@"dspatch-2");
});
? /**隊(duì)列組完成調(diào)用函數(shù)*/
dispatch_group_notify(dispatchGroup, dispatch_get_main_queue(), ^(){
? ? NSLog(@"end");
})
barrier:表示柵欄瑞筐,當(dāng)在并發(fā)隊(duì)列里面使用柵欄時(shí)候聚假,柵欄之前的并發(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");
});
信號(hào)量:Semaphore是通過‘計(jì)數(shù)’的方式來標(biāo)識(shí)線程是否是等待或繼續(xù)執(zhí)行的尔店。信號(hào)量
dispatch_semaphore_create(int) // 創(chuàng)建一個(gè)信號(hào)主慰,并初始化信號(hào)的計(jì)數(shù)大小
/* 等待信號(hào)共螺,并且判斷信號(hào)量,如果信號(hào)量計(jì)數(shù)大于等于你創(chuàng)建時(shí)候的信號(hào)量的計(jì)數(shù)沙庐,就可以通過佳吞,繼續(xù)執(zhí)行,并且將你傳入的信號(hào)計(jì)數(shù)減1铸抑,
* 如果傳入的信號(hào)計(jì)數(shù)小于你創(chuàng)建的計(jì)數(shù)鹊汛,就表示等待,等待信號(hào)計(jì)數(shù)的變化
*? 如果等待的時(shí)間超過你傳入的時(shí)間刁憋,也會(huì)繼續(xù)下面操作
*? 第一個(gè)參數(shù):semaphore 表示信號(hào)量
*? 第二個(gè)參數(shù):表示等待的時(shí)間
*? ? 返回int 如果傳入的信號(hào)計(jì)數(shù)大于等于你創(chuàng)建信號(hào)的計(jì)數(shù)時(shí)候至耻,返回0.? 反之,返回的不等于0
*/
int result = dispatch_semaphore_wait(dispatch_semaphore_t? semaphore,time outTime);// 表示等待走触,也是阻礙線程
// 表示將信號(hào)技術(shù)+1
dispatch_semaphore_signl(dispatch_semaphore_t semaphore);
實(shí)現(xiàn)線程的同步的方法:串行隊(duì)列疤苹,分組,信號(hào)量兜辞。也是可以使用并發(fā)隊(duì)列逸吵。
? //加入隊(duì)列
dispatch_async(concurrentQueue, ^{
? ? //1.先去網(wǎng)上下載圖片
? ? dispatch_sync(concurrentQueue, ^{
? ? });
? ? //2.在主線程展示到界面里
? ? dispatch_sync(dispatch_get_main_queue(), ^{
? ? });
});
16.如何使用隊(duì)列來避免資源搶奪缝裁?
當(dāng)我們使用多線程來訪問同一個(gè)數(shù)據(jù)的時(shí)候,就有可能造成數(shù)據(jù)的不準(zhǔn)確性韩脑。這個(gè)時(shí)候我么可以使用線程鎖的來來綁定段多。也是可以使用串行隊(duì)列來完成壮吩。如:fmdb就是使用FMDatabaseQueue,來解決多線程搶奪資源觉啊。
17.數(shù)據(jù)持久化的幾個(gè)方案(fmdb用沒用過)
持久化方案:
plist,存儲(chǔ)字典沈贝,數(shù)組比較好用
preference:偏好設(shè)置,實(shí)質(zhì)也是plist
NSKeyedArchiver:歸檔辑莫,可以存儲(chǔ)對(duì)象
sqlite:數(shù)據(jù)庫罩引,經(jīng)常使用第三方來操作,也就是fmdb
coreData:也是數(shù)據(jù)庫儲(chǔ)存绅你,蘋果官方的
18.說一下appdelegate的幾個(gè)方法昭躺?從后臺(tái)到前臺(tái)調(diào)用了哪些方法领炫?第一次啟動(dòng)調(diào)用了哪些方法张咳?從前臺(tái)到后臺(tái)調(diào)用了哪些方法?
1029210 (1).gif
19.NSCache優(yōu)于NSDictionary的幾點(diǎn)葱峡?
1.nscache 是可以自動(dòng)釋放內(nèi)存的砰奕。
2.nscache是線程安全的提鸟,我們可以在不同的線程中添加,刪除和查詢緩存中的對(duì)象胸哥。
3.一個(gè)緩存對(duì)象不會(huì)拷貝key對(duì)象赡鲜。
20.知不知道Designated Initializer银酬?使用它的時(shí)候有什么需要注意的問題?
個(gè)人理解:初始化函數(shù)哮内,如果你想自定義初始化函數(shù)時(shí),也是必須要初始化父類纹因,以來保證可以繼承父類的一些方法或者屬性琳拨。
21.實(shí)現(xiàn)description方法能取到什么效果狱庇?
description是nsobject的一個(gè)實(shí)例的方法,返回的是一個(gè)nsstring颜启。當(dāng)我們使用nslog打印的時(shí)候浪讳,打印出來的一般都是對(duì)象的內(nèi)存地址,如果我們實(shí)現(xiàn)description方法時(shí)口猜,我們就可以使用nslog打印對(duì)象的時(shí)候透揣,我們可以把它里面的屬性值和內(nèi)存地址一起打印出來.打印什么辐真,就是看你寫什么了。
-(NSString *)description{?
? ? ? NSString * string = [NSString stringWithFormat:@"",self,self.name,self.age];?
? ? ? return string;? ? ?
}?
22.objc使用什么機(jī)制管理對(duì)象內(nèi)存恨闪?
使用內(nèi)存管理計(jì)數(shù)器放坏,來管理內(nèi)存的。當(dāng)內(nèi)存管理計(jì)數(shù)器為0的時(shí)候钧敞,對(duì)象就會(huì)被釋放溉苛。
中級(jí)
Block
1.block的實(shí)質(zhì)是什么弄诲?一共有幾種block娇唯?都是什么情況下生成的塔插?
block:本質(zhì)就是一個(gè)object-c對(duì)象
block:存儲(chǔ)位置拓哟,可能分為3個(gè)地方:代碼去,堆區(qū)流纹、棧區(qū)(ARC情況下會(huì)自動(dòng)拷貝到堆區(qū)漱凝,因此ARC下只能有兩個(gè)地方:代碼去较雕、堆區(qū))
代碼區(qū):不訪問棧區(qū)的變量(如局部變量)挚币,且不訪問堆區(qū)的變量(alloc創(chuàng)建的對(duì)象),此時(shí)block存放在代碼去慎玖。
堆區(qū):訪問了處于棧區(qū)的變量笛粘,或者堆區(qū)的變量,此時(shí)block存放在堆區(qū)润努。–需要注意實(shí)際是放在棧區(qū)示括,在ARC情況下會(huì)自動(dòng)拷貝到堆區(qū),如果不是ARC則存放在棧區(qū)鳍侣,所在函數(shù)執(zhí)行完畢就回釋放吼拥,想再外面調(diào)用需要用copy指向它,這樣就拷貝到了堆區(qū)惑折,strong屬性不會(huì)拷貝、會(huì)造成野指針錯(cuò)區(qū)矗积。
2.為什么在默認(rèn)情況下無法修改被block捕獲的變量棘捣? __block都做了什么休建?
默認(rèn)情況下,block里面的變量茵烈,拷貝進(jìn)去的是變量的值砌些,而不是指向變量的內(nèi)存的指針。
當(dāng)使用__block修飾后的變量仑荐,拷貝到block里面的就是指向變量的指針粘招,所以我們就可以修改變量的值偎球。
3.模擬一下循環(huán)引用的一個(gè)情況?block實(shí)現(xiàn)界面反向傳值如何實(shí)現(xiàn)袍冷?
Person *p = [[Person alloc]init];
[p setPersonBlock:^(NSString *str) {
? ? p.name = str;
}];
Runtime
1.objc在向一個(gè)對(duì)象發(fā)送消息時(shí)猫牡,發(fā)生了什么?
根據(jù)對(duì)象的isa指針找到類對(duì)象id乃戈,在查詢類對(duì)象里面的methodLists方法函數(shù)列表症虑,如果沒有在好到归薛,在沿著superClass,尋找父類匪蝙,再在父類methodLists方法列表里面查詢逛球,最終找到SEL,根據(jù)id和SEL確認(rèn)IMP(指針函數(shù)),在發(fā)送消息苫昌;
3.什么時(shí)候會(huì)報(bào)unrecognized selector錯(cuò)誤?iOS有哪些機(jī)制來避免走到這一步奥务?
當(dāng)發(fā)送消息的時(shí)候氯葬,我們會(huì)根據(jù)類里面的methodLists列表去查詢我們要?jiǎng)佑玫腟EL,當(dāng)查詢不到的時(shí)候婉陷,我們會(huì)一直沿著父類查詢,當(dāng)最終查詢不到的時(shí)候我們會(huì)報(bào)unrecognized selector錯(cuò)誤
當(dāng)系統(tǒng)查詢不到方法的時(shí)候闯睹,會(huì)調(diào)用+(BOOL)resolveInstanceMethod:(SEL)sel動(dòng)態(tài)解釋的方法來給我一次機(jī)會(huì)來添加肝集,調(diào)用不到的方法蛛壳⊙眉觯或者我們可以再次使用-(id)forwardingTargetForSelector:(SEL)aSelector重定向的方法來告訴系統(tǒng),該調(diào)用什么方法砌函,一來保證不會(huì)崩潰溜族。
4.能否向編譯后得到的類中增加實(shí)例變量?能否向運(yùn)行時(shí)創(chuàng)建的類中添加實(shí)例變量仍劈?為什么寡壮?
1.不能向編譯后得到的類增加實(shí)例變量
2.能向運(yùn)行時(shí)創(chuàng)建的類中添加實(shí)例變量
解釋:
1.編譯后的類已經(jīng)注冊(cè)在runtime中,類結(jié)構(gòu)體中的objc_ivar_list實(shí)例變量的鏈表和instance_size實(shí)例變量的內(nèi)存大小已經(jīng)確定,runtime會(huì)調(diào)用class_setvarlayout或class_setWeaklvarLayout來處理strong weak引用.所以不能向存在的類中添加實(shí)例變量
2.運(yùn)行時(shí)創(chuàng)建的類是可以添加實(shí)例變量,調(diào)用class_addIvar函數(shù).但是的在調(diào)用objc_allocateClassPair之后,objc_registerClassPair之前,原因同上.
5.runtime如何實(shí)現(xiàn)weak變量的自動(dòng)置nil?
runtime 對(duì)注冊(cè)的類这溅, 會(huì)進(jìn)行布局,對(duì)于 weak 對(duì)象會(huì)放入一個(gè) hash 表中臭胜。 用 weak 指向的對(duì)象內(nèi)存地址作為 key癞尚,當(dāng)此對(duì)象的引用計(jì)數(shù)為0的時(shí)候會(huì) dealloc否纬,假如 weak 指向的對(duì)象內(nèi)存地址是a,那么就會(huì)以a為鍵睛驳, 在這個(gè) weak 表中搜索膜廊,找到所有以a為鍵的 weak 對(duì)象,從而設(shè)置為 nil蹬跃。
6.給類添加一個(gè)屬性后铆铆,在類結(jié)構(gòu)體里哪些元素會(huì)發(fā)生變化?
instance_size :實(shí)例的內(nèi)存大小
objc_ivar_list *ivars:屬性列表
RunLoop
1.runloop是來做什么的翁都?runloop和線程有什么關(guān)系柄慰?主線程默認(rèn)開啟了runloop么税娜?子線程呢?
runloop:字面意思就是跑圈概行,其實(shí)也就是一個(gè)循環(huán)跑圈谤绳,用來處理線程里面的事件和消息袒哥。
runloop和線程的關(guān)系:每個(gè)線程如果想繼續(xù)運(yùn)行堡称,不被釋放艺演,就必須有一個(gè)runloop來不停的跑圈,以來處理線程里面的各個(gè)事件和消息晓殊。
主線程默認(rèn)是開啟一個(gè)runloop巫俺。也就是這個(gè)runloop才能保證我們程序正常的運(yùn)行肿男。子線程是默認(rèn)沒有開始runloop的
2.runloop的mode是用來做什么的?有幾種mode嘹承?
model:是runloop里面的模式如庭,不同的模式下的runloop處理的事件和消息有一定的差別。
系統(tǒng)默認(rèn)注冊(cè)了5個(gè)Mode:
(1)kCFRunLoopDefaultMode: App的默認(rèn) Mode骤竹,通常主線程是在這個(gè) Mode 下運(yùn)行的哟楷。
(2)UITrackingRunLoopMode: 界面跟蹤 Mode,用于 ScrollView 追蹤觸摸滑動(dòng),保證界面滑動(dòng)時(shí)不受其他 Mode 影響惩阶。
(3)UIInitializationRunLoopMode: 在剛啟動(dòng) App 時(shí)第進(jìn)入的第一個(gè) Mode扣汪,啟動(dòng)完成后就不再使用。
(4)GSEventReceiveRunLoopMode: 接受系統(tǒng)事件的內(nèi)部 Mode冬筒,通常用不到。
(5)kCFRunLoopCommonModes: 這是一個(gè)占位的 Mode舞痰,沒有實(shí)際作用。
注意iOS 對(duì)以上5中model進(jìn)行了封裝
NSDefaultRunLoopMode;
NSRunLoopCommonModes
3.為什么把NSTimer對(duì)象以NSDefaultRunLoopMode(kCFRunLoopDefaultMode)添加到主運(yùn)行循環(huán)以后玷禽,滑動(dòng)scrollview的時(shí)候NSTimer卻不動(dòng)了矢赁?
nstime對(duì)象是在?NSDefaultRunLoopMode下面調(diào)用消息的贬丛,但是當(dāng)我們滑動(dòng)scrollview的時(shí)候,NSDefaultRunLoopMode模式就自動(dòng)切換到UITrackingRunLoopMode模式下面蜒蕾,卻不可以繼續(xù)響應(yīng)nstime發(fā)送的消息焕阿。所以如果想在滑動(dòng)scrollview的情況下面還調(diào)用nstime的消息,我們可以把nsrunloop的模式更改為NSRunLoopCommonModes
4.蘋果是如何實(shí)現(xiàn)Autorelease Pool的撤摸?
Autorelease Pool作用:緩存池准夷,可以避免我們經(jīng)常寫relase的一種方式莺掠。其實(shí)就是延遲release,將創(chuàng)建的對(duì)象楔绞,添加到最近的autoreleasePool中唇兑,等到autoreleasePool作用域結(jié)束的時(shí)候,會(huì)將里面所有的對(duì)象的引用計(jì)數(shù)器-1.
類結(jié)構(gòu)
1.isa指針蔫耽?(對(duì)象的isa留夜,類對(duì)象的isa图甜,元類的isa都要說)
在oc中黑毅,類也是對(duì)象博肋,所屬元類蜂厅。所以經(jīng)常說:萬物皆對(duì)象
對(duì)象的isa指針指向所屬的類
類的isa指針指向了所屬的元類
元類的isa指向了根元類,根元類指向了自己病游。
AC17D0A0-CB2A-4C23-8430-4BC7A99571CE.png
2.類方法和實(shí)例方法有什么區(qū)別稠通?
調(diào)用的方式不同,類方法必須使用類調(diào)用滋尉,在方法里面不能調(diào)用屬性狮惜,類方法里面也必須調(diào)用類方法碌识。存儲(chǔ)在元類結(jié)構(gòu)體里面的methodLists里面
實(shí)例方法必須使用實(shí)例對(duì)象調(diào)用,可以在實(shí)例方法里面使用屬性开泽,實(shí)例方法也必須調(diào)用實(shí)例方法魁瞪。存儲(chǔ)在類結(jié)構(gòu)體里面的methodLists里面
3.介紹一下分類,能用分類做什么众旗?內(nèi)部是如何實(shí)現(xiàn)的趟畏?它為什么會(huì)覆蓋掉原來的方法赋秀?
category:我們可以給類或者系統(tǒng)類添加實(shí)例方法方法。我們添加的實(shí)例方法猎莲,會(huì)被動(dòng)態(tài)的添加到類結(jié)構(gòu)里面的methodList列表里面。categort
4.運(yùn)行時(shí)能增加成員變量么樟遣?能增加屬性么豹悬?如果能液荸,如何增加?如果不能伤柄,為什么文搂?
可以添加屬性的,但必須我們實(shí)現(xiàn)它的getter和setter方法笔喉。但是沒有添加帶下滑線同名的成員變量
但是我們使用runtime我們就可以實(shí)現(xiàn)添加成員變量方法如下
- (void)setName:(NSString *)name {
/**
*? 為某個(gè)類關(guān)聯(lián)某個(gè)對(duì)象
*
*? @param object#> 要關(guān)聯(lián)的對(duì)象 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 {
/**
*? 獲取到某個(gè)類的某個(gè)關(guān)聯(lián)對(duì)象
*
*? @param object#> 關(guān)聯(lián)的對(duì)象 description#>
*? @param key#>? ? 屬性的key值 description#>
*/
return objc_getAssociatedObject(self, @selector(name));
}
5.objc中向一個(gè)nil對(duì)象發(fā)送消息將會(huì)發(fā)生什么然遏?(返回值是對(duì)象吧彪,是標(biāo)量,結(jié)構(gòu)體)
? 如果一個(gè)方法返回值是一個(gè)對(duì)象秧倾,那么發(fā)送給nil的消息將返回0(nil)傀缩。例如:Person * motherInlaw = [ aPerson spouse] mother]; 如果spouse對(duì)象為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)體中各個(gè)字段的值將都是0。其他的結(jié)構(gòu)體數(shù)據(jù)類型將不是用0填充的夫啊。
? 如果方法的返回值不是上述提到的幾種情況撇眯,那么發(fā)送給nil的消息的返回值將是未定義的虱咧。
高級(jí)
1.UITableview的優(yōu)化方法(緩存高度,異步繪制玄坦,減少層級(jí)绘沉,hide,避免離屏渲染)
緩存高度:當(dāng)我們創(chuàng)建frame模型的時(shí)候择懂,計(jì)算出來cell的高度的時(shí)候另玖,我們可以將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;
}
異步繪制盈魁、減少層級(jí):目前還不是很清楚
hide:個(gè)人理解應(yīng)該是hidden吧窃诉,把可能會(huì)用到的控件都創(chuàng)建出來,根據(jù)不同的情況去隱藏或者顯示出來珊膜。
避免離屏渲染:只要不是同時(shí)使用邊框/邊框顏色以及圓角的時(shí)候车柠,都可以使用layer直接設(shè)置塑猖。不會(huì)造成離屏渲染。
2.有沒有用過運(yùn)行時(shí)塑陵,用它都能做什么蜡励?(交換方法,創(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的縮寫,它是指向一個(gè)方法實(shí)現(xiàn)的指針漫蛔,每一個(gè)方法都有一個(gè)對(duì)應(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ù)
? 二赘阀、屬性名稱參數(shù)
? 三脑奠、開辟字節(jié)長度參數(shù)
? 四、對(duì)其方式參數(shù)
? 五轰豆、參數(shù)類型 “@” 官方解釋 An object (whether statically typed or typed id) (對(duì)象 靜態(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.看過哪些第三方框架的源碼齿诞?都是如何實(shí)現(xiàn)的?(如果沒有雨席,問一下多圖下載的設(shè)計(jì))
4.SDWebImage的緩存策略吠式?
sd加載一張圖片的時(shí)候,會(huì)先在內(nèi)存里面查找是否有這張圖片糙置,如果沒有會(huì)根據(jù)圖片的md5(url)后的名稱去沙盒里面去尋找是目,是否有這張圖片,如果沒有會(huì)開辟線程去下載揉抵,下載完畢后加載到imageview上面嗤疯,并md(url)為名稱緩存到沙盒里面。
5.AFN為什么添加一條常駐線程戏罢?
AFN 目的:就是開辟線程請(qǐng)求網(wǎng)絡(luò)數(shù)據(jù)。如果沒有常住線程的話龟糕,就會(huì)每次請(qǐng)求網(wǎng)絡(luò)就去開辟線程,完成之后銷毀開辟線程我擂,這樣就造成資源的浪費(fèi)催首,開辟一條常住線程,就可以避免這種浪費(fèi),我們可以在每次的網(wǎng)絡(luò)請(qǐng)求都添加到這條線程备籽。
6.KVO的使用?實(shí)現(xiàn)原理霉猛?(為什么要?jiǎng)?chuàng)建子類來實(shí)現(xiàn))
kvo:鍵值觀察珠闰,根據(jù)鍵對(duì)應(yīng)的值的變化,來調(diào)用方法坛悉。
注冊(cè)觀察者:addObserver:forKeyPath:options:context:
實(shí)現(xiàn)觀察者:observeValueForKeyPath:ofObject:change:context:
移除觀察者:removeObserver:forKeyPath:(對(duì)象銷毀裸影,必須移除觀察者)
注意
使用kvo監(jiān)聽A對(duì)象的時(shí)候军熏,監(jiān)聽的本質(zhì)不是這個(gè)A對(duì)象,而是系統(tǒng)創(chuàng)建的一個(gè)中間對(duì)象NSKVONotifying_A并繼承A對(duì)象均践,并且A對(duì)象的isa指針指向的也不是A的類摩幔,而是這個(gè)NSKVONotifying_A對(duì)象
7.KVC的使用?實(shí)現(xiàn)原理葫慎?(KVC拿到key以后,是如何賦值的偷办?知不知道集合操作符,能不能訪問私有屬性柄沮,能不能直接訪問_ivar)
kvc:鍵值賦值废岂,使用最多的即使字典轉(zhuǎn)模型。利用runtime獲取對(duì)象的所有成員變量拯欧, 在根據(jù)kvc鍵值賦值财骨,進(jìn)行字典轉(zhuǎn)模型
setValue: forKey: 只查找本類里面的屬性
setValue: forKeyPath:會(huì)查找本類里面屬性,沒有會(huì)繼續(xù)查找父類里面屬性该贾。
項(xiàng)目
1.有已經(jīng)上線的項(xiàng)目么捌臊?
2.項(xiàng)目里哪個(gè)部分是你完成的?(找一個(gè)亮點(diǎn)問一下如何實(shí)現(xiàn)的)
3.開發(fā)過程中遇到過什么困難逞力,是如何解決的矾端?
學(xué)習(xí)
4.遇到一個(gè)問題完全不能理解的時(shí)候,是如何幫助自己理解的砚亭?舉個(gè)例子殴玛?
5.有看書的習(xí)慣么?最近看的一本是什么書寻仗?有什么心得凡壤?
6.有沒有使用一些筆記軟件耙替?會(huì)在多平臺(tái)同步以及多渠道采集么曹体?(如果沒有,問一下是如何復(fù)習(xí)知識(shí)的)
7.有沒有使用清單類铜幽,日歷類的軟件串稀?(如果沒有,問一下是如何安排到忽,計(jì)劃任務(wù)的)
8.平澄⒊辏看博客么?有沒有自己寫過?(如果寫滓走,有哪些收獲?如果沒有寫比吭,問一下不寫的原因)
以上就是全部的面試題姨涡,后面的面試題,就該根據(jù)個(gè)人的情況來回答了赏表。
以上的面試回答匈仗,有的是根據(jù)自己的知識(shí)儲(chǔ)備回答,有的也是小編百度的间狂。
以上的回答也不知道對(duì)與錯(cuò)火架,歡迎大家發(fā)表自己的看法