使用data source protocols(数据源协议)来明显地将data从view上区分开来
使用已经存在的navigationitem对象
在头文件中仅暴露公有属性和方法
使用lldb来进行测试
使用NSZombieEnabled来发现内存泄露-----------------------------------------------------------------------------------------------------------------------
时刻铭记着views的生命周期
不断地提醒自己,在任何时候,你的view都可能被销毁
(1) 不要在init的方法中访问self.view
你永远不应该在你的controller的init方法中访问self.view。这么做总是会导致很多难于调试的bug,因为在收到一个内存警告之后init的逻辑将无法再次执行一遍。
考虑下面这个简单的例子:
- (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来访问并为其设置属性:
// UIViewController will automatically create the navigationItem object. self.navigationItem.rightBarButtonItem = doneButton;
NSObject
(1) 在头文件中仅暴露公有属性和方法
obj-c允许你在一个category interface(.m文件中)定义私有的属性。利用这个特性提供更好地访问限制吧。
这等价于通过@provate进行定义,并且能够带来一些额外的好处——对于代码的修改不需要重新编译并且不影响其他对象的内部结构。在一个大型项目中,这是大有裨益的。
示例:
ViewController.h
@interface ViewController : UIViewController @property (nonatomic, readonly, assign) NSInteger objectId; @endViewController.m
#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 @implementation ViewController @synthesize objectId; @synthesize objectLabel; ... @end
Debugging
(1)使用lldb来进行测试
lldb允许你检查类的属性,不需要在对象的实例上有明确地定义
(2)使用NSZombieEnabled来发现内存泄露
当NSZombieEnabled被使用,那些从内存中被释放的对象都将被保存为“zombies”。如果在未来的某个时间你企图再次访问这些已被释放的对象。这对于你去判断在什么地方发生内存泄露将会大有帮助。
(注:关于这两个debug的配置,请自行google)