当前位置:K88软件开发文章中心编程语言Objective-CObjective-C01 → 文章内容

减小字体 增大字体 作者:佚名  来源:网上搜集  发布时间:2019-1-10 11:12:17

由 
如此轻盈 
创建,
最后一次修改 
2016-08-12 类类名类名应加上 三 个大写字母作为前缀(两个字母的为 Apple 的类保留)。
虽然这个规范看起来难看,
但是这样做是为了减少 objective-c 没有命名空间所带来的问题。
一些开发者在定义 Model 对象时并不遵循这个规范(对于 Core Data 对象,
我们更应该遵循这个规范)。
我们建议在定义 Core Data 对象时严格遵循这个约定,
因为你最后可能把你的 Managed Object Model 和其他(第三方库)的 Managed Object Model 合并。
你可能注意到了,
这本书里的类的前缀(其实不仅仅是类)是ZOC。
另一个类的命名规范:当你创建一个子类的时候,
你应该把说明性的部分放在前缀和父类名的在中间。
举个例子:如果你有一个 ZOCNetworkClient 类,
子类的名字会是ZOCTwitterNetworkClient (注意 "
Twitter"
在 "
ZOC"
和 "
NetworkClient"
之间);
按照这个约定,
一个UIViewController 的子类会是 ZOCTimelineViewController.Initializer 和 dealloc 初始化推荐的代码组织方式:将 dealloc 方法放在实现文件的最前面(直接在 @synthesize 以及 @dynamic 之后),
init 应该放在 dealloc 之后。
如果有多个初始化方法,
designated initializer 应该放在第一个,
secondary initializer 在之后紧随,
这样逻辑性更好。
如今有了 ARC,
dealloc 方法几乎不需要实现,
不过把 init 和 dealloc 放在一起可以从视觉上强调它们是一对的。
通常,
在 init 方法中做的事情需要在 dealloc 方法中撤销。
init 方法应该是这样的结构:- (instancetype)init{ self = [super init];
// call the designated initializer if (self) { // Custom initialization {
return self;
{
为什么设置 self 为 [super init] 的返回值,
以及中间发生了什么呢?这是一个十分有趣的话题。
让我们后退一步:我们曾经写了类似 [[NSObject alloc] init] 的表达式,
alloc 和 init 区别慢慢褪去 。
一个 Objective-C 的特性叫 两步创建 。
这意味着申请分配内存和初始化是两个分离的操作。
alloc表示对象分配内存,
这个过程涉及分配足够的可用内存来保存对象,
写入isa指针,
初始化 retain 的计数,
并且初始化所有实例变量。
init 是表示初始化对象,
这意味着把对象放到了一个可用的状态。
这通常是指把对象的实例变量赋给了可用的值。
alloc 方法会返回一个合法的没有初始化的实例对象。
每一个发送到实例的信息会被翻译为名字是 self 的 alloc 返回的指针的参数返回的 objc_msgSend() 的调用。
这样之后 self 已经可以执行所有方法了。
为了完成两步创建,
第一个发送给新创建的实例的方法应该是约定俗成的 init 方法。
注意 NSObject 的 init 实现中,
仅仅是返回了 self。
关于 init 有一个另外的重要的约定:这个方法可以(并且应该)在不能成功完成初始化的时候返回 nil;初始化可能因为各种原因失败,
比如一个输入的格式错误,
或者未能成功初始化一个需要的对象。
这样我们就理解了为什么需要总是调用 self = [super init]。
如果你的超类没有成功初始化它自己,
你必须假设你在一个矛盾的状态,
并且在你的实现中不要处理你自己的初始化逻辑,
同时返回 nil。
如果你不是这样做,
你看你会得到一个不能用的对象,
并且它的行为是不可预测的,
最终可能会导致你的 app 发生 crash。
重新给 self 赋值同样可以被 init 利用为在被调用的时候返回不同的实例。
一个例子是 类簇 或者其他的返回相同的(不可变的)实例对象的 Cocoa 类。
Designated 和 Secondary InitializersObjective-C 有 designated 和 secondary 初始化方法的观念。
designated 初始化方法是提供所有的参数,
secondary 初始化方法是一个或多个,
并且提供一个或者更多的默认参数来调用 designated 初始化方法的初始化方法。
@implementation ZOCEvent- (instancetype)initWithTitle:(NSString *)title date:(NSDate *)date location:(CLLocation *)location{ self = [super init];
if (self) { _title = title;
_date = date;
_location = location;
{
return self;
{
- (instancetype)initWithTitle:(NSString *)title date:(NSDate *)date{ return [self initWithTitle:title date:date location:nil];
{
- (instancetype)initWithTitle:(NSString *)title{ return [self initWithTitle:title date:[NSDate date] location:nil];
{
@endinitWithTitle:date:location: 就是 designated 初始化方法,
另外的两个是 secondary 初始化方法。
因为它们仅仅是调用类实现的 designated 初始化方法Designated Initializer一个类应该又且只有一个 designated 初始化方法,
其他的初始化方法应该调用这个 designated 的初始化方法(虽然这个情况有一个例外)这个分歧没有要求那个初始化函数需要被调用。
在类继承中调用任何 designated 初始化方法都是合法的,
而且应该保证 所有的 designated initializer 在类继承中是是从祖先(通常是 NSObject)到你的类向下调用的。
实际上这意味着第一个执行的初始化代码是最远的祖先,
然后从顶向下的类继承,
所有类都有机会执行他们特定的初始化代码。
这样,
你在你做你的特定的初始化工作前,
所有你从超类继承的东西是不可用的状态。
即使它的状态不明确,
所有 Apple 的框架的 Framework 是保证遵守这个约定的,
而且你的类也应该这样做。
当定义一个新类的时候有三个不同的方式:不需要重载任何初始化函数重载 designated initializer定义一个新的 designated initializer第一个方案是最简单的:你不需要增加类的任何初始化逻辑,
只需要依照父类的designated initializer。
当你希望提供额外的初始化逻辑的时候你可以重载 designated initializer。
你只需要重载你的直接的超类的 designated initializer 并且确认你的实现调用了超类的方法。
你一个典型的例子是你创造UIViewController子类的时候重载initWithNibName:bundle:方法。
@implementation ZOCViewController- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil{ // call to the superclas

[1] [2] [3] [4] [5]  下一页