1, 如何判斷兩個(gè)對(duì)象相等
先判斷是否為nil,然后比較對(duì)象的地址(用==),然后判斷兩個(gè)對(duì)象是否是同一個(gè)類(lèi)(用isKindOfClass),最后判斷自定義對(duì)象內(nèi)的某一個(gè)屬性值是否相等(eg:[self.name isEqualToString:person.name])
可參考文章自定義對(duì)象重復(fù)
2, Extension和Category區(qū)別
1、類(lèi)別原則上只能添加方法而不能添加屬性(能添加屬性的原因只是通過(guò)runtime解決無(wú)setter/getter方法的問(wèn)題而已,如果調(diào)用_成員變量,程序還是會(huì)報(bào)錯(cuò))。
2、類(lèi)擴(kuò)展不僅可以增加方法,還可以增加實(shí)例變量(或者屬性),只是該變量默認(rèn)是@private類(lèi)型的。(所以作用范圍只能在自身類(lèi),而不是子類(lèi)或者其它地方)
3、類(lèi)擴(kuò)展中聲明的方法沒(méi)被實(shí)現(xiàn),編譯器會(huì)報(bào)警告。但是類(lèi)別中的方法沒(méi)被實(shí)現(xiàn),編譯器是不會(huì)有任何警告的。這是因?yàn)轭?lèi)擴(kuò)展是在編譯階段被添加到類(lèi)中,而分類(lèi)是在運(yùn)行時(shí)添加到類(lèi)中。
4、類(lèi)擴(kuò)展不能像類(lèi)別那樣擁有獨(dú)立的實(shí)現(xiàn)部分(@implementation部分),和本類(lèi)共享一個(gè)實(shí)現(xiàn)。也就是說(shuō),類(lèi)擴(kuò)展所聲明的方法必須依托對(duì)應(yīng)宿主類(lèi)的實(shí)現(xiàn)部分來(lái)實(shí)現(xiàn)。
3, 常見(jiàn)集合對(duì)象的時(shí)間復(fù)雜度
NSArray / NSMutableArray
-
containsObject;indexOfObject;removeObject均會(huì)遍歷元素查看是否匹配,復(fù)雜度等于或小于 O(n) -
objectAtIndex;firstObject;lastObject;addObject;removeLastObject這些只針對(duì)棧頂,棧底的操作時(shí)間復(fù)雜度都是 O(1) -
indexOfObject:inSortedRange:options:usingComparator:使用的是二分查找,時(shí)間復(fù)雜度是O(log n)
NSSet / NSMutableSet (集合類(lèi)型是無(wú)序并且沒(méi)有重復(fù)元素的)
-
addObject;removeObject;containsObject都是按照 O(1) 來(lái)的。
需要注意的是將數(shù)組轉(zhuǎn)成Set 時(shí),會(huì)將重復(fù)元素合并為一個(gè),并且失去排序。
NSDictionary / NSMutableDictionary
- 添加和刪除元素都是 O(1)
可參考文章常見(jiàn)集合對(duì)象的時(shí)間復(fù)雜度
4, iOS中常用的定時(shí)器
- NSTimer
- 循環(huán)引用(解決方案,分類(lèi)里添加block,改變添加的target,用NSProxy作為中間代理類(lèi),不直接持有self)
- 計(jì)時(shí)不準(zhǔn)確,當(dāng)前runloop運(yùn)行狀態(tài)影響計(jì)時(shí)準(zhǔn)確性。
- 計(jì)時(shí)環(huán)境受runloop影響(runloopmode切換,runloop是否開(kāi)啟)
- CADisplayLink
- 循環(huán)引用,解決方案同NSTimer
- 由于依托于屏幕刷新頻率,若果CPU不堪重負(fù)而影響了屏幕刷新,那么我們的觸發(fā)事件也會(huì)受到相應(yīng)影響。
- selector觸發(fā)的時(shí)間間隔只能是duration的整倍數(shù),selector事件如果大于其觸發(fā)間隔就會(huì)造成掉幀現(xiàn)象。
- CADisplayLink使用場(chǎng)合相對(duì)專(zhuān)一,適合做UI的不停重繪
- CADisplayLink不能被繼承
- dispatch_source_t
- 循環(huán)引用:因?yàn)閐ispatch_source_set_event_handler回調(diào)是個(gè)block,在添加到source的鏈表上時(shí)會(huì)執(zhí)行copy并被source強(qiáng)引用,如果block里持有了self,self又持有了source的話(huà),就會(huì)引起循環(huán)引用。正確的方法是使用weak+strong或者提前調(diào)用dispatch_source_cancel取消timer。
- dispatch_resume和dispatch_suspend調(diào)用次數(shù)需要平衡,如果重復(fù)調(diào)用dispatch_resume則會(huì)崩潰,因?yàn)橹貜?fù)調(diào)用會(huì)讓dispatch_resume代碼里if分支不成立,從而執(zhí)行了DISPATCH_CLIENT_CRASH("Over-resume of an object")導(dǎo)致崩潰。
- source在suspend狀態(tài)下,如果直接設(shè)置source = nil或者重新創(chuàng)建source都會(huì)造成crash。正確的方式是在resume狀態(tài)下調(diào)用dispatch_source_cancel(source)釋放當(dāng)前的source。
- 盡量不使用dispatch_suspend,在dealloc方法中,在dispatch_resume狀態(tài)下直接使用dispatch_source_cancel來(lái)取消定時(shí)器。
- 使用懶加載創(chuàng)建定時(shí)器,并且記錄當(dāng)timer 處于dispatch_suspend的狀態(tài)。這些時(shí)候,只要在 調(diào)用dealloc 時(shí)判斷下,已經(jīng)調(diào)用過(guò) dispatch_suspend 則再調(diào)用下 dispatch_resume后再cancel,然后再釋放timer。
5, frame和bounds的區(qū)別
- 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),以0,0點(diǎn)為起點(diǎn))。
可參考文章frame和bounds的區(qū)別
6, 堆排序(最大堆,最小堆)
堆排序(Heapsort)是指利用堆這種數(shù)據(jù)結(jié)構(gòu)所設(shè)計(jì)的一種排序算法。 堆積是一個(gè)近似完全二叉樹(shù)的結(jié)構(gòu),并同時(shí)滿(mǎn)足堆積的性質(zhì):即子結(jié)點(diǎn)的鍵值或索引總是小于(或者大于)它的父節(jié)點(diǎn)。 堆排序可以說(shuō)是一種利用堆的概念來(lái)排序的選擇排序。
最大堆:當(dāng)父節(jié)點(diǎn)的鍵值總是大于或等于任何一個(gè)子節(jié)點(diǎn)的鍵值時(shí)為最大堆
最小堆:當(dāng)父節(jié)點(diǎn)的鍵值總是小于或等于任何一個(gè)子節(jié)點(diǎn)的鍵值時(shí)為最小堆
7, 無(wú)序的數(shù)組取前n個(gè)數(shù)
- 快速排序:在最理想的情況下,即劃分可以使得每次分到n/2 的兩個(gè)序列,復(fù)雜度為o(nlogn)。
- 堆排序:無(wú)論什么情況都是o(nlogn),當(dāng)然還有建堆的時(shí)間o(n),所以為n+nlogn