iOS开发学习笔记-创建和初始化对象

Objective-C中对象的创建和初始化
(Allocating and Initializing Objects)
(主要内容来自于Apple的电子书《The Objective-C Programming Language》的“Allocating and Initializing Objects”。电子书可以从iBooks商店下载。iOS Developer Library也有同名的文档,但是内容上是不同的。)

在Objective-C中创建对象分为两步:
1 开辟一个对象所需的内存,Allocating object
2 为对象的各个成员赋予初始值,Initializing object

开辟内存这个步骤很简单。一般来说,Objective-C中的所有类都继承于NSObject。NSObject定义了两个方法——alloc和allocWithZone:。子类不用重载和修改这两个方法。直接使用就能开辟创建一个自己子类对象所需的内存。

重要的工作在第二步。

初始化对象的方法一般以init开头,比如无参数的init方法,或者initWithFrame:方法。NSObject类定义了init方法。一般而言,子类需要根据自己需要,定义自己的初始化方法。

初始化方法返回的对象(返回值)
需要注意的是,初始化方法(init...)的返回值不一定和该方法的接收者(或者以C语言角度来说是调用者)同类型的对象。如果初始化失败,返回的对象则是nil。比如依靠一个文件来初始化对象,如果打开文件失败,那么返回的对象是nil。
下面的代码是危险的:
id aObject = [SomeClass alloc];
[aObject init]; //在这里返回值不一定就是aObject,
[aObject someOtherMessage]; //实际应该someOtherMessage的接收者应该是init的返回值,而不是aObject
正确的写法如下:
id aObject = [SomeClass alloc] init];
[aObject someOtherMessage];

实现初始化方法时需要注意的地方
~方法的名字应该以init开头
~方法的返回值类型应该是id
~在实现中需要调用designated initializer(什么是designated initiailizer后面会提到)。一个类有很多初始化方法,其中一个(或者一些)叫designated initializer(翻译成?“指定的初始化方法”?)。实现子类的designated initializer时,必须调用父类的designated initializer。实现子类的其他初始化方法时,需要直接或者间接地调用一下自己的designated initializer。
NSObject的designated initializer方法是init。
~在初始化方法里设置成员变量时不要使用accessor method(访问方法)。
~把初始化方法的返回值赋给self。
~返回self,或者如果初始化失败,返回nil。

初始化失败时的处理
如果失败返回nil, 另外如有必要对self调用release方法。
- (id) init {
  self = [super init]; //给self赋值; 调用super的designated initializer
  if (self) { //只有super的init返回的值不是nil才做下面的事情
    theDate = [ [NSDate alloc] init];
  }
  return self; //如果失败返回,self的值是nil,返回的nil
}
另一个例子:
- (id) iniWithImage:(NSImage *) aImage {
  if (aImage == nil) {
    [self release]; //如果传入的参数有问题,那么调用self的release方法
    return nil;
  }
  self = [super init_xxx: yyy];
  if (self) {
    image = [aImage retian];
  }
  return self;
}

子类需要确保所有从父类继承而来的初始化方法都能正确工作。
比如类A定义了init方法;子类B定义了initWithName方法。类B要保证init消息也能正确地初始化类B。一个简单的方法是类B的init调用类B的initWithName方法来实现自己:
- init {
  return [self initWithName:"default"];
}

The Designated Initializer
一个类的designated initializer确保所有继承而来的成员都被初始化(通过调用super的方法),同时也做了其他的大部分工作。这个类的其他初始化方法调用这个designated initializer。
一个类的designated initializer方法必须调用父类的designated initializer,而不是父类的其他初始化方法。如果不这么做可能会引起死循环。
(具体例子见电子书)

合并开辟内存和初始化内存这两个步骤(Combine allocation and initialization)
有些类提供了一些方法,在这些方法里实现了内存开辟和内存初始化这两个步骤。这些方法被称为convenience constructors(便利的构造函数)。一般形式是+className...。
比如NSArray提供了:
+ (id) array;
+ (id) arrayWithObjects:(id) firstObj, ...;
有时候这些方法很有用。比如,+ (id) arrayWithObjects:(id) firstObj, ...,只有知道了参数的个数才能知道应该分配多大的内存。所以不能将开辟内存和初始化内存这两个步骤分开。
再看下面的例子(singleton),如果对象已有就直接返回已有对象,没必要开辟内存:
+ (Soloist *) soloist {
  static Soloist *instance = nil; //note: static
  if (instance == nil) {
    instance = [self alloc] init];
  }
  return instance;
}
(返回类型是Soloist *,不是id,在这种情况下是合适的)

时间: 2024-10-13 20:29:27

iOS开发学习笔记-创建和初始化对象的相关文章

IOS开发学习笔记027-UITableView 使用模型对象

1.模型对象 继续优化上一个程序 上一次用到字典,但是坏处多多.这里将这些数据封装到类中. 这就是MVC中得模型,模型就是数据的显示结构 新建一个类,添加几个属性和一个类方法用于快速返回对象 1 #import <Foundation/Foundation.h> 2 3 @interface Province : NSObject 4 // UI控件用weak 5 // nsstring 用copy 6 7 8 @property (nonatomic,copy) NSString *head

IOS开发学习笔记(二)-语音识别(科大讯飞)

上次简单地讲解了如何利用科大讯飞完成语音合成,今天接着也把语音识别整理一下.当然,写代码前我们需要做的一些工作(如申请appid.导库),在上一篇语音合成的文章当中已经说过了,不了解的可以看看我上次的博文,那么这次直接从堆代码开始吧. 详细步骤: 1.导完类库之后,在工程里添加好用的头文件.在视图里只用了一个UITextField显示识别的内容,两个UIButton(一个开始监听语音,一个结束监听),然后引入类.添加代理,和语音合成的一样. MainViewController.h 1 #imp

IOS开发学习笔记--语音合成(科大讯飞)

      现在语音服务越来越热,我们平时使用的很多软件都带有语音合成和识别功能,用起来也很方便.说到语音服务,Google和微软都提供过API接口,不过笔者要介绍的是国内的智能语音技术提供商---科大讯飞.之前看过一个比较Google.微软和科大讯飞语音识别引擎的博文(http://fqctyj.blog.163.com/blog/static/70843455201361955322797/),有兴趣可以去看看.笔者接触语音服务的时间也不长,对语音服务也不是很了解,但是拆解过科大讯飞的Dem

iOS开发学习笔记:基础篇

iOS开发需要一台Mac电脑.Xcode以及iOS SDK.因为苹果设备都具有自己封闭的环境,所以iOS程序的开发必须在Mac设备上完成(当然,黑苹果应该也是可以的,但就需要花很多的精力去折腾基础环境),Xcode是一个集成开发环境,包括了编辑器.调试.模拟器等等一系列方便开发和部署的工具,iOS SDK则是开发应用所必需,不同的SDK分别对应不同的iOS版本或设备,通常我们需要下载多个iOS SDK以确保我们开发的程序能够在不同版本的iOS上正常运行. 创建新工程 Xcode提供了很多种工程模

IOS开发学习笔记-(3) 进度条、等待动画开始停止

一.创建对应空间视图  ,如下图: 二.编写对应的 .h 代码,如下 : #import <UIKit/UIKit.h> @interface ViewController : UIViewController @property (weak, nonatomic) IBOutlet UIActivityIndicatorView *activWaitNetWork; @property (weak, nonatomic) IBOutlet UIProgressView *pgrsDownLo

IOS开发学习笔记(1)-----UILabel 详解

1. [代码][C/C++]代码     //创建uilabelUILabel *label1 = [[UILabel alloc] initWithFrame:CGRectMake(20, 40, 280, 80)];//设置背景色label1.backgroundColor = [UIColor grayColor];//设置taglabel1.tag = 91;//设置标签文本label1.text = @"Hello world!";//设置标签文本字体和字体大小label1.

IOS开发学习笔记(2)-----UIButton 详解

1. [代码][C/C++]代码     //这里创建一个圆角矩形的按钮    UIButton *button1 = [UIButton buttonWithType:UIButtonTypeRoundedRect];    //    能够定义的button类型有以下6种,//    typedef enum {//        UIButtonTypeCustom = 0,          自定义风格//        UIButtonTypeRoundedRect,        

IOS开发学习笔记-(2)键盘控制,键盘类型设置,alert 对话框

一.关闭键盘,放弃第一响应者,处理思路有两种 ① 使用文本框的 Did End on Exit 绑定事件 ② UIControl on Touch 事件 都去操作 sender 的  resignFirstResponder #import <UIKit/UIKit.h> @interface ViewController : UIViewController @property (weak, nonatomic) IBOutlet UITextField *txtUserName; @pro

IOS开发学习笔记017-什么是IOS开发

应用程序开发流程 1.IOS开发需要思考的问题 用户是谁?不同应用程序的内容和用户体验大不相同,这取决于想要编写的是什么应用程序,它可能是儿童游戏,也可能是待办事项列表应用程序,又或者是测试自己学习成果的应用程序. 应用程序的用途是什么?赋予应用程序一个明确的用途十分重要.了解激发用户使用应用程序的动因是界定用途的一个出发点. 应用程序尝试解决什么问题?应用程序应该完美解决单个问题,而不是尝试解决多个截然不同的问题.如果发现应用程序尝试解决不相关的问题,那么最好考虑编写多个应用程序. 应用程序要