承接上文嗤攻,在2018年底毛嫉,面試了許多家大公司,如某大型視頻公司妇菱、電商平臺承粤、音頻公司、教育公司等闯团,具體名字就不一一列舉了辛臊。面試這些公司最大的感受就是,這些公司對基礎(chǔ)要求特別高房交,基礎(chǔ)扎實的能過一輪二輪彻舰,三輪四輪有時候真的看領(lǐng)導(dǎo)對你的眼緣,很多時候靠運氣的!所以刃唤,有了扎實的基礎(chǔ)就是成功的關(guān)鍵隔心。
推薦閱讀:iOS開發(fā)——BAT面試題合集(持續(xù)更新中)
承接上篇文章,分析一下各問題的答案尚胞,屬于個人理解硬霍,有問題歡迎指正。
OC基礎(chǔ)
- OC對象辐真,底層的結(jié)構(gòu)是怎樣的须尚,類與類別,category為什么不能添加屬性侍咱? 底層的實現(xiàn)原理耐床,如果類別重寫了類中的方法,調(diào)用順序是怎樣的楔脯?OC語言的動態(tài)特性撩轰,靜態(tài)編譯與動態(tài)類型識別,此處阿里曾考過昧廷?這些平時不注意的點有沒有注意過堪嫂?
分類一般用來動態(tài)的為已經(jīng)存在的類擴展新的方法。
分類中可以添加實例方法木柬、類方法皆串、屬性、協(xié)議眉枕。但是不能添加成員變量恶复。
添加屬性的話只會生成set、get方法的聲明不會實現(xiàn)也不會生成下劃線成員變量速挑。
系統(tǒng)是在運行時把分類中的信息整合到了原來的類中
系統(tǒng)是在運行時將分類中對應(yīng)的實例方法谤牡、類方法等插入到了原來類或元類的方法列表中,且是在列表的前邊姥宝!所以翅萤,方法調(diào)用時通過isa去對應(yīng)的類或元類的列表中查找對應(yīng)的方法時先查到的是分類中的方法!查到后就直接調(diào)用不在繼續(xù)查找腊满。這即是’覆蓋’的本質(zhì)套么!
這個是與編譯順序有關(guān),最后編譯的分類中對應(yīng)的信息會在整合在類或元類對應(yīng)列表的最前邊碳蛋。所以是調(diào)用最后編譯的分類中的方法胚泌!可以查看Build Phases ->Complie Source 中的編譯順序!
category沒有辦法去代替子類疮蹦,它不能像子類一樣通過super去調(diào)用父類的方法實現(xiàn)。如果category中重寫覆蓋了當(dāng)前類中的某個方法茸炒,那么這個當(dāng)前類中的原始方法實現(xiàn)愕乎,將永遠不會被執(zhí)行阵苇,這在某些方法里是致命的。(ps:這里提一下感论,+(void)load方法是一個特例绅项,它會在當(dāng)前類執(zhí)行完之后再在category中執(zhí)行。)
同時比肄,一個category也不能可靠的覆蓋另一個category中相同的類的相同的方法快耿。例如UIViewController+A與UIViewController+B,都重寫了viewDidLoad芳绩,后編譯的覆蓋前編譯的掀亥。
通過觀察頭文件我們可以發(fā)現(xiàn),Cocoa框架中的許多類都是通過category來實現(xiàn)功能的妥色,可能不經(jīng)意間你就覆蓋了這些方法中的其一搪花,有時候就會產(chǎn)生一些無法排查的異常原因。
category的誕生只是為了讓開發(fā)者更加方便的去拓展一個類嘹害,它的初衷并不是讓你去改變一個類撮竿。
結(jié)論:
要重寫方法,當(dāng)然我們首推通過子類重寫父類的方法笔呀,在一些不方便重寫的情況下幢踏,我們也可以在category中用runtime進行method swizzling(方法的偷梁換柱)來實現(xiàn)。
- OC的屬性许师,assign,copy,strong,retain,weak.這些屬性的應(yīng)用場景房蝉,以及經(jīng)常考的是可變字符串為什么不能用copy修飾枯跑?不可變字符串為什么不能用strong修飾惨驶,修飾了會怎樣?代理如果用assign會怎樣敛助?
可變字符串用copy粗卜,就會copy成不可變字符串
不可變字符串用strong修飾,如果不可變字符串指向可變字符串纳击,不可變字符串就會隨著外部可變字符串改變而改變续扔。
代理用assign,最后代理應(yīng)該置為nil,如果不置為nil,會造成野指針焕数。
- OC的內(nèi)存管理機制纱昧,從MRC到ARC內(nèi)存管理做了什么?autoreleasePool 什么情況下會用堡赔,autoreleasePool 的實現(xiàn)原理识脆?引用計數(shù)保存在哪里?了解其數(shù)據(jù)結(jié)構(gòu)嗎?
自動引用計數(shù)灼捂,不用手動釋放對象內(nèi)存离例,對象內(nèi)存自動釋放
autoreleasePool實現(xiàn)原理:一個線程的autoreleasepool就是一個指針棧。
棧中存放的指針指向加入需要release的對象或者POOL_SENTINEL(哨兵對象悉稠,用于分隔autoreleasepool)宫蛆。
棧中指向POOL_SENTINEL的指針就是autoreleasepool的一個標記。當(dāng)autoreleasepool進行出棧操作的猛,每一個比這個哨兵對象后進棧的對象都會release耀盗。
這個棧是由一個以page為節(jié)點雙向鏈表組成,page根據(jù)需求進行增減卦尊。
autoreleasepool對應(yīng)的線程存儲了指向最新page(也就是最新添加autorelease對象的page)的指針叛拷。
引用計數(shù)保存地方:散列表,數(shù)據(jù)結(jié)構(gòu)是散列表
- 各種原理性問題猫牡,如dictionary的實現(xiàn)原理胡诗,KVC的實現(xiàn)原理以及為什么要派生出子類,KVO的實現(xiàn)原理淌友,KVO為什么要移除觀察者煌恢,timer會造成循環(huán)引用嗎?怎么解決震庭?weak的實現(xiàn)原理瑰抵?
dictionary:使用hash表來實現(xiàn)key和value之間映射和存儲的。hash函數(shù)設(shè)計的好壞影響著數(shù)據(jù)的查找訪問效率器联。數(shù)據(jù)在hash表中分布的越均勻二汛,其訪問效率越高。而在Objective-C中拨拓,通常都是利用NSString來作為鍵值肴颊,其內(nèi)部使用的hash函數(shù)也是通過使用 NSString對象作為鍵值來保證數(shù)據(jù)的各個節(jié)點在hash表中均勻分布。
見NSDictionary中最常用的一個方法原型:
[objc] view
plain copy
(void)setObject:(id)anObject forKey:(id )aKey;?
從這個方法中可以知道渣磷, 要作為 Key 值婿着,必須遵循 NSCopying 協(xié)議豹芯。也就是說在NSDictionary內(nèi)部仙逻,會對 aKey 對象 copy 一份新的。而 anObject 對象在其內(nèi)部是作為強引用(retain或strong)粘捎。所以在MRC下形纺,向該方法發(fā)送消息之后丘侠,我們會向anObject發(fā)送 release 消息進行釋放。
既然知道了作為 key 值逐样,必須遵循 NSCopying 協(xié)議蜗字,說明除了 NSString 對象之外打肝,我們還可以使用其他類型對象來作為 NSDictionary 的 key值。不過這還不夠挪捕,作為 key 值闯睹,該類型還必須繼承于 NSObject 并且要重載一下兩個方法:
1 - (NSUInteger)hash;
(BOOL)isEqual:(id)object
KVC 底層實現(xiàn)原理:
當(dāng)一個對象調(diào)用setValue:forKey:
方法時,方法內(nèi)部會做以下操作: 1.判斷有沒有指定key的set方法,如果有set方法,就會調(diào)用set方法,給該屬性賦值 2.如果沒有set方法,判斷有沒有跟key值相同且?guī)в邢聞澗€的成員屬性(_key).如果有,直接給該成員屬性進行賦值 3.如果沒有成員屬性_key,判斷有沒有跟key相同名稱的屬性.如果有,直接給該屬性進行賦值 4.如果都沒有,就會調(diào)用 valueforUndefinedKey 和setValue:forUndefinedKey:方法
KVO 的底層實現(xiàn)原理:
(1)KVO 是基于 runtime 機制實現(xiàn)的
(2)當(dāng)一個對象(假設(shè)是person對象,對應(yīng)的類為 JLperson)的屬性值age發(fā)生改變時,系統(tǒng)會自動生成一個繼承自JLperson的類NSKVONotifying_JLPerson,在這個類的 setAge 方法里面調(diào)用 [super setAge:age]; [self willChangeValueForKey:@“age”]; [self didChangeValueForKey:@“age”];
三個方法,而后面兩個方法內(nèi)部會主動調(diào)用 -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context方法,在該方法中可以拿到屬性改變前后的值.
觀察者不會在 dealloc 的時候自動移除。因此最晚必須在觀察者 dealloc 時移除它
因為通知中心對觀察者有一個強引用担神,要及時移出去
CADisplayLink、NSTimer會對target產(chǎn)生強引用始花,如果target又對它們產(chǎn)生強引用妄讯,那么就會引發(fā)循環(huán)引用
weak原理:Runtime維護了一個Weak表,用于存儲指向某個對象的所有Weak指針酷宵。Weak表其實是一個哈希表亥贸,Key是所指對象的地址,Value是Weak指針的地址(這個地址的值是所指對象的地址)的數(shù)組浇垦。
一個對象A,里面有一個weak屬性B, 首先會有一個hash表, 鍵為A的地址, 值為一個數(shù)組, 這個數(shù)組里包含了B指針的地址, 當(dāng)銷毀的時候回根據(jù)B指針的地址獲取到B的指針, 然后置為nil
在對象被回收的時候炕置,經(jīng)過層層調(diào)用,會最終觸發(fā)下面的方法將所有Weak指針的值設(shè)為nil男韧。
簡單來說朴摊,這個方法首先根據(jù)對象地址獲取所以Weak指針地址的數(shù)組,然后遍歷這個數(shù)組把其中的數(shù)據(jù)設(shè)為nil此虑,最后把這個entry從Weak表中刪除甚纲。
1.初始化時:runtime會調(diào)用objc_initWeak函數(shù),初始化一個新的weak指針指向?qū)ο蟮牡刂贰?br>
2.添加引用時:objc_initWeak函數(shù)會調(diào)用 storeWeak() 函數(shù)朦前, storeWeak() 的作用是更新指針指向介杆,創(chuàng)建對應(yīng)的弱引用表。
3.釋放時,調(diào)用clearDeallocating函數(shù)韭寸。clearDeallocating函數(shù)首先根據(jù)對象地址獲取所有weak指針地址的數(shù)組春哨,然后遍歷這個數(shù)組把其中的數(shù)據(jù)設(shè)為nil,最后把這個entry從weak表中刪除恩伺,最后清理對象的記錄赴背。
- block的實現(xiàn)原理,__block的作用以及底層實現(xiàn)原理莫其,block的循環(huán)引用問題癞尚,下劃線修飾的變量會造成循環(huán)引用嗎?怎么處理乱陡?masonry鏈式編程怎么實現(xiàn)的浇揩?什么情況下不用__weak?(Masonry、AFNetWorking憨颠、動畫等)
block對象就是一個結(jié)構(gòu)體胳徽,里面有isa指針指向自己的類(global malloc stack)积锅,有desc結(jié)構(gòu)體描述block的信息,__forwarding指向自己或堆上自己的地址养盗,如果block對象截獲變量缚陷,這些變量也會出現(xiàn)在block結(jié)構(gòu)體中。最重要的block結(jié)構(gòu)體有一個函數(shù)指針往核,指向block代碼塊箫爷。block結(jié)構(gòu)體的構(gòu)造函數(shù)的參數(shù),包括函數(shù)指針聂儒,描述block的結(jié)構(gòu)體虎锚,自動截獲的變量(全局變量不用截獲),引用到的__block變量衩婚。(__block對象也會轉(zhuǎn)變成結(jié)構(gòu)體)
block代碼塊在編譯的時候會生成一個函數(shù)窜护,函數(shù)第一個參數(shù)是前面說到的block對象結(jié)構(gòu)體指針。執(zhí)行block非春,相當(dāng)于執(zhí)行block里面__forwarding里面的函數(shù)指針柱徙。
__block:Block不允許修改外部變量的值,這里所說的外部變量的值奇昙,指的是棧中指針的內(nèi)存地址护侮。__block 所起到的作用就是只要觀察到該變量被 block 所持有,就將“外部變量”在棧中的內(nèi)存地址放到了堆中储耐。進而在block內(nèi)部也可以修改外部變量的值概行。
block循環(huán)引用,指針相互指向弧岳,用__weak增加弱環(huán)
masonry鏈式編程:不會造成循環(huán)引用凳忙,constraintMaker只是局部變量,不會造成循環(huán)引用禽炬,鏈式編程:利用block, 代碼塊的返回類型是該類的實例變量,設(shè)置完相關(guān)的操作涧卵,并把實例對象返回。
AFNetworking是因為人家大神自己封裝了一個completionBlock腹尖,不管你傳進來是啥柳恐,都給你把循環(huán)引用打破。
- 平時有用到runtime嗎热幔?runtime干嘛的乐设,方法交換。runloop的理解绎巨。
1.交換兩個方法 Method Swizzling 2.獲取屬性列表以及成員變量 3.消息轉(zhuǎn)發(fā) 4.動態(tài)關(guān)聯(lián)屬性 5.字典轉(zhuǎn)模型應(yīng)用 6.isa swizzling
- 消息發(fā)送機制近尚,消息轉(zhuǎn)發(fā)的三步補救措施?objc向一個對象發(fā)送消息時场勤,發(fā)送消息的整個過程戈锻?objc中向一個nil對象發(fā)送消息將會發(fā)生什么歼跟?這個題目很重要,一題可能會否定一個人格遭。
消息發(fā)送 [object sendMassage]
1.通過obj的isa指針找到其所對應(yīng)的類哈街。
2.通過SEL先去類的cache列表中找這個方法,如果就去找方法的實現(xiàn)拒迅,不存在骚秦,進入第3步
3.去類的method列表中找,如果就去找方法的實現(xiàn)璧微,沒有找到骤竹,根據(jù)類中的superclass指針去父類中找,一直到NSObject. 4. 可以看到這個方法中的第二行代碼imp往毡,可以通過這個imp來查找這個方法的實現(xiàn),要是沒有找到靶溜,runtime給我們提供了三次機會讓我們的程序不會崩潰开瞭,也就是下面要提到的動態(tài)方法解析和消息轉(zhuǎn)發(fā)(消息重定向,消息轉(zhuǎn)發(fā))
動態(tài)方法解析:
runtime提供的第一次實現(xiàn)這個方法的機會罩息,要實現(xiàn)resolveInstanceMethod/resolveClassMethod方法嗤详,給未實現(xiàn)的方法在運行時添加實現(xiàn),返回no/不實現(xiàn)瓷炮,進入消息轉(zhuǎn)發(fā)葱色。
消息轉(zhuǎn)發(fā)一:消息重定向
消息重定向:返回一個實現(xiàn)了該方法的對象,要實現(xiàn)-(id)forwardingTargetForSelector:(SEL)aSelector函數(shù)娘香,如果返會nil/self苍狰,則進入下面的消息轉(zhuǎn)發(fā)二
消息轉(zhuǎn)發(fā)二:消息轉(zhuǎn)發(fā)
將未實現(xiàn)方法的相關(guān)信息打包成一個NSInvocation對象,然后交給一個類去實現(xiàn)烘绽。需要實現(xiàn)-(NSMethodSignature )methodSignatureForSelector:(SEL)aSelector和-(void)forwardInvocation:(NSInvocation )anInvocation方法
- 一個對象的本質(zhì)淋昭,一個對象的內(nèi)存布局,類對象與元類對象安接?
一個對象的本質(zhì)就是一個結(jié)構(gòu)體翔忽,里面有isa指針,指向class,結(jié)構(gòu)體是className_IMPL,里面有結(jié)構(gòu)體盏檐,最終指向NSObject
1.instance對象在內(nèi)存中存儲的信息包括:isa指針以及其他成員變量歇式,
2.類對象:
? 它們是同一個對象。每個類在內(nèi)存中有且只有一個class對象
? class對象在內(nèi)存中存儲的信息主要包括
? isa指針
? superclass指針
? 類的屬性信息(@property)胡野、類的對象方法信息(instance method)
? 類的協(xié)議信息(protocol)材失、類的成員變量信息(ivar)
- 元類對象:
? objectMetaClass是NSObject的meta-class對象(元類對象)
? 每個類在內(nèi)存中有且只有一個meta-class對象
? meta-class對象和class對象的內(nèi)存結(jié)構(gòu)是一樣的,但是用途不一樣硫豆,在內(nèi)存中存儲的信息主要包括
? isa指針
? superclass指針
? 類的類方法信息(class method)
? 如果是instance對象豺憔,返回class對象
? 如果是class對象额获,返回meta-class對象
? 如果是meta-class對象,返回NSObject(基類)的meta-class對象 - 深拷貝淺拷貝
對非容器類的淺拷貝就是拷貝對象的地址恭应,對象里面存的內(nèi)容仍然是一份抄邀,沒有新的內(nèi)存被分配。對非容器類的深拷貝就是重寫分配一塊內(nèi)存昼榛,然后把另一個對象的內(nèi)容原封不動的給我拿過來境肾。
對容器類的深拷貝是對容器中的每個元素都進行拷貝,容器類的淺拷貝是對容器里的內(nèi)容不進行拷貝胆屿,兩個容器的地址是不同的奥喻,但容器里的所裝的東西是一樣的,在一個容器中修改值非迹,則另一個淺拷貝的容器中的值也會變化环鲤。
iOS系統(tǒng)
main()之前的過程有哪些?
1)dyld開始將程序二進制文件初始化
2)交由ImageLoader讀取Image,其中包含了我們的類憎兽、方法等各種符號(Class冷离、Protocol、Selector纯命、IMP)
3)由于runtime向dyld綁定了回調(diào)西剥,當(dāng)Image加載到內(nèi)存后,dyld會通知runtime進行處理
4)runtime接手后調(diào)用map_images做解析和處理
5)接下來load_Images中調(diào)用call_load_methods亿汞,遍歷所有加載進來的Class瞭空,按繼承層次依次調(diào)用Class的+load和其他Category的+load方法
6)至此,所有的信息都被加載進了內(nèi)存中
7)最后dyld調(diào)用真正的main函數(shù)
注意:dyld會緩存上一次把信息加載到內(nèi)存的緩存疗我,所以咆畏,第二次比第一次啟動快一點。
dyld: 而動態(tài)庫在加載的時候都需要用dyld(位于/usr/lib/dyld)程序進行鏈接AF實現(xiàn)原理吴裤?SD實現(xiàn)原理鳖眼?
SDWebImage,里面有一個manager管理downloader以及緩存策略cache,downloader在后臺開辟線程,實現(xiàn)下載嚼摩,下載后的圖片解碼也在線程中钦讳,最后要回到主線程展示。緩存策略的話枕面,先緩存到內(nèi)存中愿卒,然后是硬盤中,
當(dāng)SDWebImageManager向SDImageCache要資源時潮秘,先搜索內(nèi)存層面的數(shù)據(jù)琼开,如果有直接返回,沒有的話去訪問磁盤枕荞,將圖片從磁盤讀取出來柜候,然后做Decoder搞动,將圖片對象放到內(nèi)存層面做備份,再返回調(diào)用層
通知所有的downloadDelegates下載完成渣刷,回調(diào)給需要的地方展示圖片鹦肿。將圖片保存到SDImageCache中,內(nèi)存緩存和硬盤緩存同時保存辅柴。寫文件到硬盤也在以單獨NSInvocationOperation完成箩溃,避免拖慢主線程。
1.首先將placeholderImage進行展示,SDWebImageManager根據(jù)URL開始處理圖片 2.SDImageCache從緩存中查找圖片圖片碌嘀,如果有sdImageCacheDelegate回調(diào)image:didFindImage:forkey:useInfo:到SDWebImageManager .到前端展示圖片
3.緩存中沒有涣旨,生成NSInvocationOperation添加到隊列中開始在硬盤中查找,如果找到會將圖片添加到內(nèi)存緩存中(如果空閑緩存不夠股冗,會先清理)然后SDImageCacheDelegate回調(diào)imageCache:didFindImage:forKey:userInfo:霹陡。進而回調(diào)展示圖片。
4.如果硬盤中沒有則共享或生成下載器SDWebImageDownLoader開始下載圖片止状,圖片下載有NSURLConnection來做
5.圖片解碼處理在一個NSOperationQueue完成烹棉,不會拖慢主線程UI。如果有需要對下載的圖片進行二次處理导俘,最好也在這里完成,效率會好很多剔蹋。
6.在主線程notifyDelegateOnMainThreadWithInfo: 宣告解碼完成旅薄,imageDecoder:didFinishDecodingImage:userInfo: 回調(diào)給SDWebImageDownloader。imageDownloader:didFinishWithImage: 回調(diào)給SDWebImageManager告知圖片下載完成
7.通知所有的downloadDelegates下載完成泣崩,回調(diào)給需要的地方展示圖片少梁。將圖片保存到SDImageCache中,內(nèi)存緩存和硬盤緩存同時保存矫付。寫文件到硬盤也在以單獨NSInvocationOperation完成凯沪,避免拖慢主線程。
8.SDImageCache在初始化的時候會注冊一些消息通知买优,在內(nèi)存警告或退到后臺的時候清理內(nèi)存圖片緩存妨马,應(yīng)用結(jié)束的時候清理過期圖片
系統(tǒng)級內(nèi)存警告如何處理
取消當(dāng)前正在進行的所有下載操作
清除緩存數(shù)據(jù)(面試)
刪除過期的文件數(shù)據(jù),計算當(dāng)前未過期的已經(jīng)下載的文件數(shù)據(jù)的大小杀赢,如果發(fā)現(xiàn)該數(shù)據(jù)大小大于我們設(shè)置的最大緩存數(shù)據(jù)大小烘跺,那么程序內(nèi)部會按照按文件數(shù)據(jù)緩存的時間從遠到近刪除,知道小于最大緩存數(shù)據(jù)為止脂崔。
說一下UITableViewCell的卡頓你是怎么優(yōu)化的滤淳?
設(shè)計一套緩存策略。
可以將數(shù)據(jù)緩存到本地磁盤砌左。
可以判斷一個資源是否已經(jīng)被緩存脖咐。如果已經(jīng)被緩存铺敌,在請求相同的資源,先到本地磁盤搜索屁擅。
可以判斷文件緩存什么時候過期偿凭。這里為了簡單起見這里,我們在請求url資源的時候煤蹭,給每次請求的文件設(shè)定一個過期的時間笔喉。
如果文件已經(jīng)被緩存,而且沒有過期硝皂,這將本地的數(shù)據(jù)返回常挚,否則重新請求url
如果文件下載不成功或者下載沒有完成,下次打開程序的時候稽物,移除這些沒有成功或者沒有下載完成的文件奄毡。
開辟線程,同時請求或者下載多個資源贝或。
5.有哪些鎖吼过?有什么用處?
同步鎖咪奖,遞歸鎖盗忱,讀寫鎖,互斥鎖羊赵,條件鎖
1?@synchronized
2?NSLock 對象鎖
3?NSRecursiveLock 遞歸鎖
4?NSConditionLock 條件鎖
5?pthread_mutex 互斥鎖(C語言)
6?dispatch_semaphore 信號量實現(xiàn)加鎖(GCD)
7? OSSpinLock (暫不建議使用)
- iOS啟動優(yōu)化和列表優(yōu)化點
? APP的啟動由dyld主導(dǎo)趟佃,將可執(zhí)行文件加載到內(nèi)存,順便加載所有依賴的動態(tài)庫
? 并由runtime負責(zé)加載成objc定義的結(jié)構(gòu)
? 所有初始化工作結(jié)束后昧捷,dyld就會調(diào)用main函數(shù)
? 接下來就是UIApplicationMain函數(shù)闲昭,AppDelegate的application:didFinishLaunchingWithOptions:方法
dyld
? 減少動態(tài)庫、合并一些動態(tài)庫(定期清理不必要的動態(tài)庫)
? 減少Objc類靡挥、分類的數(shù)量序矩、減少Selector數(shù)量(定期清理不必要的類、分類)
? 減少C++虛函數(shù)數(shù)量
? Swift盡量使用struct
runtime
? 用+initialize方法和dispatch_once取代所有的attribute((constructor))跋破、C++靜態(tài)構(gòu)造器簸淀、ObjC的+load。
main
? 在不影響用戶體驗的前提下毒返,盡可能將一些操作延遲啃擦,不要全部都放在finishLaunching方法中
? 按需加載
iOS與h5的交互
如何增加一條常駐線程?
AFN 的做法是使用一個 runloop 來保證線程不死~然而頻繁的創(chuàng)建線程并啟動runloop肯定會造成內(nèi)存泄露(runloop 無法停止.線程無法退出)
所以AFN就創(chuàng)建了一個單例線程,并且保證線程不退出饿悬。
- 說一下響應(yīng)鏈令蛉?
當(dāng)iOS程序中發(fā)生觸摸事件后,系統(tǒng)會將事件加入到UIApplication管理的一個任務(wù)隊列中
UIApplication將處于任務(wù)隊列最前端的事件向下分發(fā)。即UIWindow珠叔。
UIWindow將事件向下分發(fā)蝎宇,即UIView。
UIView首先看自己是否能處理事件祷安,觸摸點是否在自己身上姥芥。如果能,那么繼續(xù)尋找子視圖汇鞭。
遍歷子控件凉唐,重復(fù)以上兩步。
如果沒有找到霍骄,那么自己就是事件處理者台囱。如果
如果自己不能處理,那么不做任何處理读整。
其中 UIView不接受事件處理的情況主要有以下三種
1)alpha <0.01
2)userInteractionEnabled = NO
3.hidden = YES.
這個從父控件到子控件尋找處理事件最合適的view的過程簿训,如果父視圖不接受事件處理(上面三種情況),則子視圖也不能接收事件米间。事件只要觸摸了就會產(chǎn)生强品,關(guān)鍵在于是否有最合適的view來處理和接收事件,如果遍歷到最后都沒有最合適的view來接收事件屈糊,則該事件被廢棄的榛。
動畫分為哪幾類?如何終結(jié)一個動畫逻锐?什么是轉(zhuǎn)場動畫夫晌?什么情況下動畫會失敗谦去?
有沒有用過GCD?GCD的group會線程阻塞慷丽?下載一張圖片蹦哼,下載過程中UIImageView突然取消會怎樣鳄哭?NsOperation與GCD的不用應(yīng)用場景
CoreText實現(xiàn)富文本?
? CTLine 可以看做Core Text繪制中的一行的對象 通過它可以獲得當(dāng)前行的line ascent,line descent ,line leading,還可以獲得Line下的所有Glyph Runs
? CTRun 或者叫做 Glyph Run纲熏,是一組共享想相同attributes(屬性)的字形的集合體
一個CTFrame有幾個CTLine組成妆丘,有幾行文字就有幾行CTLine。一個CTLine有包含多個CTRun局劲,一個CTRun是所有屬性都相同的那部分富文本的繪制單元勺拣。所以CTRun是CTFrame的基本繪制單元。ViewController的生命周期鱼填?
按照執(zhí)行順序排列:
initWithCoder:通過nib文件初始化時觸發(fā)药有。
awakeFromNib:nib文件被加載的時候,會發(fā)生一個awakeFromNib的消息到nib文件中的每個對象。
loadView:開始加載視圖控制器自帶的view愤惰。
viewDidLoad:視圖控制器的view被加載完成苇经。
viewWillAppear:視圖控制器的view將要顯示在window上。
updateViewConstraints:視圖控制器的view開始更新AutoLayout約束宦言。
viewWillLayoutSubviews:視圖控制器的view將要更新內(nèi)容視圖的位置扇单。
viewDidLayoutSubviews:視圖控制器的view已經(jīng)更新視圖的位置。
viewDidAppear:視圖控制器的view已經(jīng)展示到window上奠旺。
viewWillDisappear:視圖控制器的view將要從window上消失蜘澜。
viewDidDisappear:視圖控制器的view已經(jīng)從window上消失。
- 設(shè)計一個檢測主線和卡頓的方案响疚。
我們啟動一個worker線程鄙信,worker線程每隔一小段時間(delta)ping以下主線程(發(fā)送一個NSNotification),如果主線程此時有空稽寒,必然能接收到這個通知扮碧,并pong以下(發(fā)送另一個NSNotification),如果worker線程超過delta時間沒有收到pong的回復(fù)杏糙,那么可以推測UI線程必然在處理其他任務(wù)了慎王,此時我們執(zhí)行第二步操作,暫停UI線程宏侍,并打印出當(dāng)前UI線程的函數(shù)調(diào)用棧赖淤。
iOS應(yīng)用安全,如何防止反編譯谅河?iOS平時的加密措施咱旱,密碼一般保存在哪里?
感覺項目中哪些地方做的比較好的绷耍?有哪些優(yōu)化點值得推薦的吐限?
項目的整體架構(gòu)是怎樣的,項目層級如何劃分褂始?有什么熟悉的架構(gòu)诸典?項目架構(gòu)如何做到細分?
平時如何采集性能數(shù)據(jù)的崎苗?
網(wǎng)絡(luò)請求有沒有做到深度優(yōu)化狐粱?
iOS網(wǎng)絡(luò)請求
- http與HTTPS,每次請求都要建立證書嗎胆数?
HTTPS協(xié)議是由SSL+HTTP協(xié)議構(gòu)建的可進行加密傳輸肌蜻、身份認證的網(wǎng)絡(luò)協(xié)議,要比http協(xié)議安全必尼。
HTTPS和HTTP的區(qū)別主要如下:
1蒋搜、https協(xié)議需要到ca申請證書,一般免費證書較少,因而需要一定費用豆挽。
2酸休、http是超文本傳輸協(xié)議,信息是明文傳輸祷杈,https則是具有安全性的ssl加密傳輸協(xié)議斑司。
3、http和https使用的是完全不同的連接方式但汞,用的端口也不一樣宿刮,前者是80,后者是443私蕾。
4僵缺、http的連接很簡單,是無狀態(tài)的踩叭;HTTPS協(xié)議是由SSL+HTTP協(xié)議構(gòu)建的可進行加密傳輸磕潮、身份認證的網(wǎng)絡(luò)協(xié)議,比http協(xié)議安全容贝。
客戶端在使用HTTPS方式與Web服務(wù)器通信時有以下幾個步驟:
∽愿(1)客戶使用https的URL訪問Web服務(wù)器,要求與Web服務(wù)器建立SSL連接斤富。
「喑薄(2)Web服務(wù)器收到客戶端請求后,會將網(wǎng)站的證書信息(證書中包含公鑰)傳送一份給客戶端满力。
』啦巍(3)客戶端的瀏覽器與Web服務(wù)器開始協(xié)商SSL連接的安全等級,也就是信息加密的等級油额。
〉住(4)客戶端的瀏覽器根據(jù)雙方同意的安全等級,建立會話密鑰潦嘶,然后利用網(wǎng)站的公鑰將會話密鑰加密涩嚣,并傳送給網(wǎng)站。
〕囊浴(5)Web服務(wù)器利用自己的私鑰解密出會話密鑰缓艳。
⌒DΑ(6)Web服務(wù)器利用會話密鑰加密與客戶端之間的通信
- get與post區(qū)別看峻,post請求能否用拼接參數(shù)的形式?get一定要拼接參數(shù)嗎衙吩?兩個最本質(zhì)的區(qū)別互妓?
post也可以用拼參方式;get也不一定非得拼參。
GET產(chǎn)生一個TCP數(shù)據(jù)包冯勉;POST產(chǎn)生兩個TCP數(shù)據(jù)包澈蚌。
對于GET方式的請求,瀏覽器會把http header和data一并發(fā)送出去灼狰,服務(wù)器響應(yīng)200(返回數(shù)據(jù))宛瞄;
而對于POST,瀏覽器先發(fā)送header交胚,服務(wù)器響應(yīng)100 continue份汗,瀏覽器再發(fā)送data,服務(wù)器響應(yīng)200 ok(返回數(shù)據(jù))蝴簇。
GET與POST都有自己的語義杯活,不能隨便混用。
據(jù)研究熬词,在網(wǎng)絡(luò)環(huán)境好的情況下旁钧,發(fā)一次包的時間和發(fā)兩次包的時間差別基本可以無視。而在網(wǎng)絡(luò)環(huán)境差的情況下互拾,兩次包的TCP在驗證數(shù)據(jù)包完整性上歪今,有非常大的優(yōu)點。
并不是所有瀏覽器都會在POST中發(fā)送兩次包颜矿,F(xiàn)irefox就只發(fā)送一次彤委。
- APNS整個請求過程
APNs(Apple Push Notification service)是遠程推送功能的核心,通過APNs客戶端和蘋果服務(wù)器建立一個長連接或衡,推送也是通過這個長連接發(fā)送到客戶端上
deviceToken是設(shè)備的一個標識符焦影,屬于你這款A(yù)PP裝在你這個設(shè)備上的標識符,即每個APP在每一個不同的設(shè)備上都有著不同的deviceToekn封断,通過注冊遠程推送服務(wù)斯辰,APNs會返回給你的APP的deviceToken。
1坡疼、首先是應(yīng)用程序注冊消息推送彬呻。
2、IOS跟APNS Server要deviceToken柄瑰。應(yīng)用程序接受deviceToken闸氮。
3、應(yīng)用程序?qū)eviceToken發(fā)送給PUSH服務(wù)端程序,保存deviceToken教沾。
4蒲跨、服務(wù)端程序向APNS服務(wù)發(fā)送消息。
5授翻、APNS服務(wù)將消息發(fā)送給iPhone應(yīng)用程序或悲。
無論是iPhone客戶端跟APNS,還是Provider和APNS都需要通過證書進行連接的孙咪。下面介紹一下所用到證書的制作。
服務(wù)器通過TLS驗證和APNs連接巡语,HTTPS中用的也是TLS協(xié)議翎蹈,即四步握手,首先初始化TLS連接男公,即provider(服務(wù)器)發(fā)送請求給APNs荤堪,APNs服務(wù)器返回APNs證書(即公鑰)給provider,然后服務(wù)端收到后生成provider證書后再返回給APNs枢赔,APNs收到后驗證后即可以建立TLS連接逞力,不過APNs用的不是HTTPS,而是HTTP2糠爬。
TCP與UDP的應(yīng)用區(qū)別
socket的應(yīng)用場景
本地大量頻繁的數(shù)據(jù)怎么處理寇荧?
數(shù)據(jù)庫
- 平時用的數(shù)據(jù)庫有哪幾種?如何聯(lián)表查詢执隧,數(shù)據(jù)如何保證讀取安全揩抡?
數(shù)據(jù)結(jié)構(gòu)與算法
算法建議系統(tǒng)的看,有本書值得推薦《劍指offer》,可以系統(tǒng)的學(xué)習(xí)镀琉。畢竟數(shù)據(jù)結(jié)構(gòu)與算法是基礎(chǔ)峦嗤,打好基礎(chǔ)才能萬丈大樓平地起!
二分查找法
反轉(zhuǎn)鏈表
兩組有序數(shù)據(jù)屋摔,查找第k個數(shù)
當(dāng)然烁设,經(jīng)典算法還有很多,此處就不一一列舉了钓试。
腳本
固有的iOS知識有時候并不能滿足開發(fā)需求了装黑,有時候需要腳本的編寫。推薦Python,因為Mac本身就支持Python弓熏。能夠利用Python處理一些事情恋谭,越來越成為一個程序員的基本要求。
1.自動化打包也越來越傾向于用腳本實現(xiàn)
能夠用腳本加載一些資源文件
在程序加載之前能夠用腳本處理一些事情
許多第三方包依賴于腳本
許多大公司挽鞠,XCode只是一個代碼編寫工具疚颊,代碼的編譯運行交給腳本處理,能夠用腳本處理許多事情
總結(jié)
本文總結(jié)了大部分問題的答案信认,很多都是日積月累總結(jié)的材义。如有不對的地方,歡迎大家指正嫁赏。
大家在準備面試的時候其掂,可以在本文基礎(chǔ)上,形成思維導(dǎo)圖橄教,每個知識點連成一片清寇,從而進行系統(tǒng)地學(xué)習(xí)。
喜歡的話點贊+1或關(guān)注多多支持哦 小編會經(jīng)常給小伙伴們更新關(guān)于IOS當(dāng)下熱點护蝶。
另外小編給大家推薦一個iOS技術(shù)交流群:638302184华烟!群內(nèi)提供數(shù)據(jù)結(jié)構(gòu)與算法、底層進階持灰、swift盔夜、逆向、整合面試題等免費資料
附上一份收集的各大廠面試題(附答案) ! 群文件直接獲取
各大廠面試題
文章來源網(wǎng)絡(luò) 如有侵權(quán)請聯(lián)系小編刪除