一.去除masory布局警告,排除NSTimer,block以及通知等循環(huán)引用問題。
二.加入預(yù)加載功能
三.上拉下拉取消請(qǐng)求
四.啟動(dòng)時(shí)間優(yōu)化
本地啟動(dòng)時(shí)間過長(zhǎng),經(jīng)過分析有兩個(gè)方面因素.一.開頻廣告來自網(wǎng)絡(luò)請(qǐng)求,受網(wǎng)速影響,二.didFinishLaunchingWithOptions初始化內(nèi)容過多,沒有分類都揉在一起,導(dǎo)致didFinishLaunchingWithOptions耗時(shí)過長(zhǎng)。新建一個(gè)工具類專門負(fù)責(zé)初始化工作。將初始化的內(nèi)容根據(jù)需要程度分成三類:
?* 第一類: 比如日志 / 統(tǒng)計(jì)等需要第一時(shí)間啟動(dòng)的, 仍然放在 didFinishLaunchingWithOptions 中.
?* 第二類: 比如用戶數(shù)據(jù)需要在廣告顯示完成以后使用, 所以需要伴隨廣告頁啟動(dòng), 只需要將啟動(dòng)代碼放到 startupEventsOnADTimeWithAppDelegate 方法里.
?* 第三類: 比如直播和分享等業(yè)務(wù), 肯定是用戶能看到真正的主界面以后才需要啟動(dòng), 所以推遲到主界面加載完成以后啟動(dòng), 只需要將代碼放到 startupEventsOnDidAppearAppContent 方法里.
?調(diào)用時(shí)機(jī)
?第一類,必須第一時(shí)間啟動(dòng),仍然把它留在 didFinishLaunchingWithOptions 里啟動(dòng)。
?第二類,這些功能在用戶進(jìn)入 APP 主體的之前是必須要加載完的,我把他放到廣告頁面的viewDidAppear啟動(dòng)。
?第三類,由于啟動(dòng)時(shí)間不是必須的,所以我們可以放在第一個(gè)界面的 viewDidAppear 方法里,這里完全不會(huì)影響到啟動(dòng)時(shí)間。
效果很明顯,快了3-5秒。
五.引入MLeaksFinder和fps工具類檢測(cè)內(nèi)存泄漏和fps
檢測(cè)出fps過低,手機(jī)卡的時(shí)候平均在40,手機(jī)正常在58,后面重點(diǎn)優(yōu)化fps相關(guān)
1.tableViewCell高度的緩存
原來的做法:在model中新增cellheight,懶加載cellheight,cellheight沒有就重新計(jì)算。這樣的做法會(huì)導(dǎo)致新加載的數(shù)據(jù)沒有緩存高度,下拉刷新或者重新進(jìn)入頁面也沒有緩存高度
? ? 新的做法:在model中新增cellheight,新建高度緩存工具類,內(nèi)部使用NSCache存在本地,最大存儲(chǔ)數(shù)設(shè)置的500,對(duì)外提供單例,根據(jù)新聞的id去存儲(chǔ)高度,在model中判斷是否緩存cell高度,沒有就重新計(jì)算,并存儲(chǔ)起來,這樣做規(guī)避了新數(shù)據(jù)或者重新加載的新聞沒有緩存高度,而且新聞id是唯一的,同一個(gè)新聞可能出現(xiàn)在很多頻道下(如推薦和頭條),這樣也就省的再去計(jì)算了。
2.tableView按需加載(效果不明顯,放棄了)
用戶在快速滑動(dòng)的過程中,cell不斷的重用和放入重用池中,label的繪制可以忽略,圖片加載要看下的。其實(shí)SDWebImage默認(rèn)就是滑動(dòng)中不加載圖片(設(shè)置請(qǐng)求的等級(jí)low),在cell重用時(shí)會(huì)取消之前同一個(gè)cell上的請(qǐng)求,但是不停的請(qǐng)求和請(qǐng)求取消的狀態(tài),還是需要優(yōu)化下的,雖然效果不大??傊?,按需加載優(yōu)化的重心就是快速滑動(dòng)的過程中,不要請(qǐng)求滿天飛。
我的做法是在蘋果官方demo的基礎(chǔ)上加上SDWebImage。官方demo是LazyTableImages。
在model中新增picCanload屬性記錄是否可以加載,重寫set方法,不能加載的,在原來的url上拼接我自己定義的字符串

在SDWebImage的方法中加個(gè)判斷,帶有拼接字符串的url不加載,這里還可以判斷是否有緩存,sd有緩存的話可以加載

在cellForRowAtIndexPath加上判斷,設(shè)置能否加載

滑動(dòng)結(jié)束刷新請(qǐng)求

效果其實(shí)不明顯,沒有集成到項(xiàng)目中,單純記錄下吧
六.新增:首頁點(diǎn)擊當(dāng)前子頻道,頻道內(nèi)容刷新。
思路:點(diǎn)擊子頻道必進(jìn)點(diǎn)擊事件方法,一個(gè)頻道就是一個(gè)控制器,所以是一對(duì)多,所以準(zhǔn)備用通知。ok,坑就開始埋下了。
(后面用到的newsViewController是RecommendVC的子類,vc是RecommendVC實(shí)例)



第一個(gè)坑:post通知,父類的newsViewController和子類RecommendVC都能接收到,顯然不行,一個(gè)對(duì)象父類子類都會(huì)接受到通知。后面想到用類名,代碼改成這樣



發(fā)現(xiàn)RecommendVC收不到通知。
第一次:認(rèn)為是object的問題,把監(jiān)聽addObserver的參數(shù)obj設(shè)置成nil,能收到了。再把a(bǔ)dd中的object改回成@“RecommendVC”,把post中的object改成@“RecommendVC”同樣能收到,確認(rèn)了objec對(duì)象是能用來區(qū)分同一個(gè)通知。
第二次:網(wǎng)上查object參數(shù)發(fā)現(xiàn),post的參數(shù)object和add的參數(shù)object要是同一個(gè)實(shí)例,改post的object為NSStringFromClass([vc class]),改add的object為NSStringFromClass([self class]),依然收不到。打印了self和vc是同一個(gè)對(duì)象,怎么NSStringFromClass([vc class])和NSStringFromClass([self class])就不是一個(gè)對(duì)象了呢。模擬了個(gè)demo單獨(dú)研究,demo中NSStringFromClass([vc class])和NSStringFromClass([self class])就是一個(gè)對(duì)象。問題轉(zhuǎn)化成NSStringFromClass的研究,終端編譯了NSStringFromClass的源碼,未公開,網(wǎng)上頁沒找到結(jié)果。
第三次:寫了demo研究NSStringFromClass發(fā)現(xiàn),類名長(zhǎng)度較長(zhǎng)時(shí),NSStringFromClass([vc class])和NSStringFromClass([self class])不是一個(gè)對(duì)象,類名長(zhǎng)度較短時(shí),NSStringFromClass([vc class])和NSStringFromClass([self class])是一個(gè)對(duì)象。想起以前網(wǎng)上看的NSString字符串長(zhǎng)度小于10的話,蘋果是特殊處理的,沒有指針,作為基本類型處理。
七.加入安全數(shù)組分類,替換數(shù)組的增刪改查
- (void)safeRemoveObject:(id)obj {
? ? if(obj ==nil) {
? ? ? ? DLog(@"%s call -removeObject:, but argument obj is nil", __FUNCTION__);
? ? ? ? return;
? ? }
? ? if([self respondsToSelector:@selector(removeObject:)]) {
?? ? ? ? [self removeObject:obj];
? ? }else{
? ? ? ? DLog(@"%s 找不到removeObject方法",__FUNCTION__);
? ? }
}