关于iOS应用设计的一些最佳实践

原文地址http://blog.csdn.net/yanghua_kobe/article/details/7962553
  • 时刻铭记着views的生命周期
不要在init的方法中访问self.view

使用data source protocols(数据源协议)来明显地将dataview上区分开来

  • UIViewController

      使用已经存在的navigationitem对象

  • NSObject

      在头文件中仅暴露公有属性和方法

  • Debugging

      使用lldb来进行测试

      使用NSZombieEnabled来发现内存泄露

-----------------------------------------------------------------------------------------------------------------------

时刻铭记着views的生命周期

不断地提醒自己,在任何时候,你的view都可能被销毁

(1) 不要在init的方法中访问self.view

你永远不应该在你的controller的init方法中访问self.view。这么做总是会导致很多难于调试的bug,因为在收到一个内存警告之后init的逻辑将无法再次执行一遍。

考虑下面这个简单的例子:

[csharp]  view plain copy print ?
  1. - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {  
  2.   if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {  
  3.     self.view.backgroundColor = [UIColor underPageBackgroundColor];  
  4.   }  
  5.   return self;  
  6. }  

想象一下这个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 plain copy print ?
  1. // UIViewController will automatically create the navigationItem object.  
  2. self.navigationItem.rightBarButtonItem = doneButton;  

NSObject

(1) 在头文件中仅暴露公有属性和方法

obj-c允许你在一个category interface(.m文件中)定义私有的属性。利用这个特性提供更好地访问限制吧。

这等价于通过@provate进行定义,并且能够带来一些额外的好处——对于代码的修改不需要重新编译并且不影响其他对象的内部结构。在一个大型项目中,这是大有裨益的。

示例:

ViewController.h

[plain]  view plain copy print ?
  1. @interface ViewController : UIViewController  
  2. @property (nonatomic, readonly, assign) NSInteger objectId;  
  3. @end  
ViewController.m
[plain]  view plain copy print ?
  1. #import "ViewController.h"  
  2.   
  3. @interface ViewController()  
  4. @property (nonatomic, readwrite, assign) NSInteger objectId;  
  5. // Notice that this property doesn't need to be in the .h. Objective-C will create this  
  6. // property on the fly!  
  7. @property (nonatomic, readwrite, retain) UILabel* objectLabel;  
  8. @end  
  9.   
  10. @implementation ViewController  
  11. @synthesize objectId;  
  12. @synthesize objectLabel;  
  13.   
  14. ...  
  15.   
  16. @end  

Debugging

(1)使用lldb来进行测试

lldb允许你检查类的属性,不需要在对象的实例上有明确地定义

(2)使用NSZombieEnabled来发现内存泄露

当NSZombieEnabled被使用,那些从内存中被释放的对象都将被保存为“zombies”。如果在未来的某个时间你企图再次访问这些已被释放的对象。这对于你去判断在什么地方发生内存泄露将会大有帮助。

(注:关于这两个debug的配置,请自行google)

你可能感兴趣的:(ios,ios,ios,Objective-C,Objective-C,Objective-C,Objective-C,protocols,debugging)