iOS應用是非常注重用戶體驗的,不光是要求界面設計合理美觀,也要求各種UI的反應靈敏,我相信大家對那種一拖就卡卡卡的 TableView 應用沒什麼好印象。還記得12306麼,那個速度,相信大家都受不了。為了提高 iOS 的運行速度,下面我將拋磚引玉介紹一些我實踐過的用來提供iOS程序運行效率的方法,與大家分享,希望能得到更多的反饋和建議。
1,計算代碼運行時間:相信數據,不要太相信感覺。不過要注意模擬器和真機的差異。
最簡單的工具就是 NSDate,但精度不是太好。
NSDate* tmpStartData = [[NSDate date] retain];
//You code here...
double deltaTime = [[NSDate date] timeIntervalSinceDate:tmpStartData];
NSLog(@">>>>>>>>>>cost time = %f", deltaTime);
或者將運行代碼放到如下方法的 block 參數中,然後返回所運行的時間:
#import
CGFloat BNRTimeBlock (void (^block)(void)) {
mach_timebase_info_data_t info;
if (mach_timebase_info(&info) != KERN_SUCCESS) return -1.0;
uint64_t start = mach_absolute_time ();
block ();
uint64_t end = mach_absolute_time ();
uint64_t elapsed = end - start;
uint64_t nanos = elapsed * info.numer / info.denom;
return (CGFloat)nanos / NSEC_PER_SEC;
}
2,善用性能分析工具。
XCode 自帶了很多強大的分析工具,包括靜態 Analyze 工具,以及運行時 Profile 工具。
3,關於圖片
優先使用[UIImage imageNamed:@""];
與[[UIImage alloc] initWithContentsOfFile:] 和 [UIImage alloc [initWithData:]] 相比,[UIImage imageNamed:]有著更好的效率,這是因為 iOS 會自帶 cache 通過 [UIImage imageNamed:] 載入的圖像,但該方法有一個缺點,那就是只能載入應用程序 bundle 中的圖像,像網絡下載的圖像就無能無力了。我習慣的做法是自定義一個 ImageCache 類,自己來 cache 圖像。
盡量不要使用全屏大小的背景圖片;使用 gradient 圖片來取代硬編碼的 gradient;gradient 圖片應當盡可能窄,然後將之拉伸運用到實際場合中去。
4,對於結構復雜的 View,使用 drawRect 自繪而不是從 nib 中載入。
5,對於 TableView,重用 cell;減少 cell 初始化的工作量,延遲裝載;定制復雜 cell 時,使用 drawRect 自繪;Cache 盡可能多的東西,包括 cell 高度;盡可能讓 cell 不透明;避免使用圖像特性,比如 gradients。
6,在線程中使用 autoreleasepool。
7,將一些不太重要的任務放在 idle 時運行。
- (void)idleNotificationMethod {
// do something here
}
- (void)registerForIdleNotification
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(idleNotificationMethod)
name:@"IdleNotification"
object:nil];
NSNotification *notification = [NSNotification
notificationWithName:@"IdleNotification" object:nil];
[[NSNotificationQueue defaultQueue] enqueueNotification:notification
postingStyle:NSPostWhenIdle];
}
8,不要在 viewWillAppear 中做費時的操作。
viewWillAppear: 在 view 顯示之前被調用,出於效率考慮,在這個方法中不要處理復雜費時的事情;只應該在這個方法設置 view 的顯示屬性之類的簡單事情,比如背景色,字體等。要不然,用戶會明顯感覺到 view 顯示遲鈍。
9,使用多線程來延遲加載資源。比如常見的 TableViewCell 中的網絡圖像顯示,先使用一個默認圖像,然後開啟線程下載網絡圖像,當圖像下載完成之後,再替換默認圖像。
10,關於後台任務
系統進入 background 之後,一般只有10分鐘的運行時間,因此有很多值得注意的事項:
11,如果關鍵代碼使用 C/C++/asm 效率更高就使用 C/C++/asm。
12,如果一個方法在一個循環次數非常多的循環中使用,在進入循環前使用 methodForSelector 獲取該方法 IMP,然後在循環體中直接使用該 IMP。
13,關於內存釋放
在 didReceiveMemoryWarning 中釋放內存,比如cache 的圖像,view 等,並記得調用 [supper didReceiveMemoryWarning]。清理函數 didReceiveMemoryWarning, viewDidUnload 和 dealloc 都是在方法結尾處調用 supper 的方法。
14,提高 APP 加載速度
避免使用靜態初始化,包括靜態c++對象,加載時會運行的代碼,如+(void) load{} ,會造成在Main函數之前運行額外的代碼。
16,利用 cache 空間換時間。cache 是一種常見的空間換時間的提供性能的收到,可以用在相當多的場合。
盡量 cache 那些可重復利用的對象,比如 table cell,date/number formatters,正則表達式,sqlite語句等。
17,關於數據庫
緩存經常用到的 sqlite 語句;優化數據庫查詢語句,用sqlite3_trace和sqlite3_profile來查找性能差的語句;如果可能的話,緩存查詢結果緩。 在使用 sqlite_prepare會將SQL查詢編譯成字節碼,要使用bind,重用那些已經prepared的語句。