Objective-C代码规范
if语句
命名
通用的约定
推荐使用长的、描述性的方法和常量
常量使用驼峰式的命名规范,有时为了清晰,加上所在的类名
Initializer 和 dealloc 初始化
推荐的代码组织方式:将 dealloc
方法放在实现文件的最前面(直接在 @synthesize
以及 @dynamic
之后),init
应该放在 dealloc
之后。如果有多个初始化方法, designated initializer 应该放在第一个,secondary initializer 在之后紧随,这样逻辑性更好。
如今有了 ARC,dealloc 方法几乎不需要实现,不过把 init 和 dealloc 放在一起可以从视觉上强调它们是一对的。通常,在 init 方法中做的事情需要在 dealloc 方法中撤销。
alloc
、 init
分别是申请内存和初始化,Objective-C的特性两步创建
-
alloc
表示对象分配内存,这个过程涉及分配足够的可用内存来保存对象,写入isa
指针,初始化 retain 的计数,并且初始化所有实例变量。 -
init
是表示初始化对象,这意味着把对象放到了一个可用的状态。这通常是指把对象的实例变量赋给了可用的值。
Objective-C 有 designated 和 secondary 初始化方法的观念。
designated 初始化方法是提供所有的参数,secondary 初始化方法是一个或多个,并且提供一个或者更多的默认参数来调用 designated 初始化方法的初始化方法。
Designated Initializer 一个类应该又且只有一个 designated 初始化方法,其他的初始化方法应该调用这个 designated 的初始化方法(虽然这个情况有一个例外)
在类继承中调用任何 designated 初始化方法都是合法的,而且应该保证 所有的 designated initializer 在类继承中是是从祖先(通常是
NSObject
)到你的类向下调用的。实际上这意味着第一个执行的初始化代码是最远的祖先,然后从顶向下的类继承,所有类都有机会执行他们特定的初始化代码。这样,你在你做你的特定的初始化工作前,所有你从超类继承的东西是不可用的状态。即使它的状态不明确,所有 Apple 的框架的 Framework 是保证遵守这个约定的,而且你的类也应该这样做。
当定义一个新类的时候有三个不同的方式:
- 不需要重载任何初始化函数
- 重载 designated initializer
- 定义一个新的 designated initializer
- 定义你的 designated initializer,确保调用了直接超类的 designated initializer
- 重载直接超类的 designated initializer。调用你的新的 designated initializer.
- 为新的 designated initializer 写文档
上述的一个推论是:你应该永远不从 designated initializer 里面调用一个 secondary initializer (如果secondary initializer 遵守约定,它会调用 designated initializer)。如果这样,调用很可能会调用一个子类重写的 init 方法并且陷入无限递归之中
可以使用
__attribute__
来标示初始化模式
类簇 (class cluster)[抽象工厂]
an architecture that groups a number of private, concrete subclasses under a public, abstract superclass. (一个在共有的抽象超类下设置一组私有子类的架构)这个模式非常有用,因为它减少了构造器调用中的复杂性,只需要知道接口如何与对象通信,而不需要知道怎么实现。
Class clusters 在 Apple 的Framework 中广泛使用:一些明显的例子比如
NSNumber
可以返回不同哦给你的子类,取决于 数字类型如何提供 (Integer, Float, etc...) 或者 NSArray
返回不同的最优存储策略的子类。The beauty of this pattern is that the caller can be completely unaware of the concrete subclass; in fact it can be used when designing a library to be able to swap the underlaying returned class without leaking any implementation detail as long as is respectful of the contract established in the abstract class.
这个模式的精妙的地方在于,调用者可以完全不管子类,事实上,这可以用在设计一个库,可以用来交换实际的返回的类,而不用去管相关的细节,因为它们都遵从抽象超类的方法。
我们的经验是使用类簇可以帮助移除很多条件语句。
@implementation ZOCKintsugiPhotoViewController- (id)initWithPhotos:(NSArray *)photos
{
if ([self isMemberOfClass:ZOCKintsugiPhotoViewController.class]) {
self = nil;
if ([UIDevice isPad]) {
self = [[ZOCKintsugiPhotoViewController_iPad alloc] initWithPhotos:photos];
}
else {
self = [[ZOCKintsugiPhotoViewController_iPhone alloc] initWithPhotos:photos];
}
return self;
}
return [super initWithNibName:nil bundle:nil];
}@end
属性定义
推荐按照下面的格式来定义属性
@property (nonatomic, readwrite, copy) NSString *name;
属性的参数应该按照下面的顺序排列: 原子性,读写 和 内存管理。 这样做你的属性更容易修改正确,并且更好阅读。
你必须使用
nonatomic
,除非特别需要的情况。在iOS中,atomic
带来的锁特别影响性能。属性可以存储一个代码块。为了让它存活到定义的块的结束,必须使用
copy
(block 最早在栈里面创建,使用 copy
让 block 拷贝到堆里面去)为了完成一个共有的 getter 和一个私有的 setter,你应该声明公开的属性为
readonly
并且在类扩展总重新定义通用的属性为 readwrite
的。@interface MyClass : NSObject
@property (nonatomic, readonly) NSObject *object
@end@implementation MyClass ()
@property (nonatomic, readwrite, strong) NSObject *object
@end
如果
BOOL
属性的名字是描述性的,这个属性可以省略 "is" ,但是特定要在 get 访问器中指定名字,如:@property (assign, getter=isEditable) BOOL editable;
文字和例子是引用 Cocoa Naming Guidelines.
为了避免
@synthesize
的使用,在实现文件中,Xcode已经自动帮你添加了。私有属性 【Objective-C代码规范】私有属性应该在类实现文件的类拓展(class extensions,没有名字的 categories 中)中。有名字的 categories(如果
ZOCPrivate
)不应该使用,除非拓展另外的类。推荐阅读
- 机器学习算法|基于Open-cv 的停车场停车位识别个人笔记附所有代码(下)
- 探索类|快速使用 Jacoco 代码覆盖率统计
- DGL|基于注意力机制的图神经网络GAT的一些理解以及DGL官方代码的一些理解
- Java|你见过哪些实用到爆的 Java 代码技巧()
- SSM框架基于JavaWeb在线投票系统的设计与实现源码+论文+ppt+代码讲解视频+安装视频(包安装)
- 性能优化|Android 项目架构系列之代码的混淆
- SAP|SAP UI5 表格控件的支持复选(Multi-Select)以及如何用代码一次选中多个表格行项目试读版
- SpringBoot网上书城的设计与实现源码+论文二稿+ppt+开题报告+中期检查+代码讲解视频(包安装)
- 职业技能|远程代码托管平台--GitHub、Gitee的使用
- 基于图的 Affinity Propagation 聚类计算公式详解和代码示例