時刻銘記著views的生命周期
不要在init的方法中訪問self.view
使用data source protocols(數據源協議)來明顯地將data從view上區分開來
UIViewController
使用已經存在的navigationitem對象
NSObject
在頭文件中僅暴露公有屬性和方法
Debugging
使用lldb來進行測試
使用NSZombieEnabled來發現內存洩露
-----------------------------------------------------------------------------------------------------------------------
時刻銘記著views的生命周期
不斷地提醒自己,在任何時候,你的view都可能被銷毀
(1) 不要在init的方法中訪問self.view
你永遠不應該在你的controller的init方法中訪問self.view。這麼做總是會導致很多難於調試的bug,因為在收到一個內存警告之後init的邏輯將無法再次執行一遍。
考慮下面這個簡單的例子:
[csharp]
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
self.view.backgroundColor = [UIColor underPageBackgroundColor];
}
return self;
}
想象一下這個controller是一個navigation stack(注:iOS中使用棧的結構來管理那些navigationController相關的視圖對象)的根對象,與此同時一個內存警告發生了(收到內存警告如果沒有正確處理,iOS系統會銷毀一些視圖以釋放內存空間)。當我們返回到該控制器的時候,該視圖將不再以underPageBackgroundColor作為其背景色。這會給調試帶來麻煩,即便是對於那些有經驗的iOS工程師也是如此。
(2) 使用data source protocols(數據源協議)來明顯地將數據從視圖上區分開來
當你正在設計一個視圖來與數據集進行交互的時候,你總是應該通過一個data source protocol來獲取數據,而不是通過暴露訪問器(setter)的形式。視圖不是數據的容器,所以不應該讓它們承受這樣的“罪責”。正確的做法是,視圖應該被當做一個“失去存在感”的可擴展的組件,在任何時候都是。
作為一個一般性的通用法則,在視圖上的任何超出靜態展現的信息都應該通過data source或者delegate來獲取。
UILabel就是一個不需要datasource的視圖,它是個很好的示例。它所有的屬性通常都被設置一次,並且通常在視圖的生命周期內都不期待被改變。
而從另一方面來說,UITableView是一個需要data source來提取數據的好例子。讓我們想象一下當我們使用UITableView的時候不是通過一個datasource而是僅僅通過提供setter的情況將會是什麼樣子。
如果真是這樣設計的話,當開發者企圖使用table view對象來存儲他們的數據的時候,將會導致不可避免的濫用。當收到內存警告,table view 不可避免地被釋放時,數據也將一同消失(因為它通過setter存儲在tableview對象內部)。這意味著我們需要存儲的數據能夠在任何情況下北table view的多個實例在其生命周期內可以訪問。
UIViewController
view controller用來完成model與view之間的綁定
(1)使用已存在的navigation item對象
每一個UIViewController的實例都有一個navigationItem屬性,它應該被用來指定左/右導航按鈕以及標題視圖。你不應該創建一個UINavigationItem 對象,因為在你訪問self.navigationItem的時候UIViewController的基類實現將自動幫你創建一個。簡單地使用self.navigationItem來訪問並為其設置屬性:
[plain] view plaincopyprint?
// UIViewController will automatically create the navigationItem object.
self.navigationItem.rightBarButtonItem = doneButton;
NSObject
(1) 在頭文件中僅暴露公有屬性和方法
obj-c允許你在一個category interface(.m文件中)定義私有的屬性。利用這個特性提供更好地訪問限制吧。
這等價於通過@provate進行定義,並且能夠帶來一些額外的好處——對於代碼的修改不需要重新編譯並且不影響其他對象的內部結構。在一個大型項目中,這是大有裨益的。
示例:
ViewController.h
[plain] view plaincopyprint?
@interface ViewController : UIViewController
@property (nonatomic, readonly, assign) NSInteger objectId;
@end
ViewController.m
[plain] view plaincopyprint?
#import "ViewController.h"
@interface ViewController()
@property (nonatomic, readwrite, assign) NSInteger objectId;
// Notice that this property doesn't need to be in the .h. Objective-C will create this
// property on the fly!
@property (nonatomic, readwrite, retain) UILabel* objectLabel;
@end www.2cto.com
@implementation ViewController
@synthesize objectId;
@synthesize objectLabel;
...
@end
Debugging
(1)使用lldb來進行測試
lldb允許你檢查類的屬性,不需要在對象的實例上有明確地定義
(2)使用NSZombieEnabled來發現內存洩露
當NSZombieEnabled被使用,那些從內存中被釋放的對象都將被保存為“zombies”。如果在未來的某個時間你企圖再次訪問這些已被釋放的對象。這對於你去判斷在什麼地方發生內存洩露將會大有幫助。
(注:關於這兩個debug的配置,請自行google)