iOS开发:从零基础到精通
上QQ阅读APP看书,第一时间看更新

3.4 对象

3.4.1 创建对象

对象是类Class运行时的实例,它包含了自己的实例变量(属性中声明)的内存副本以及类方法的指针,在实际开发中可以采用分配内存地址alloc以及初始化init两个步骤来创建一个对象。

对象的创建分为两个阶段:内存空间分配和初始化。通常情况下,初始化总是紧跟在内存空间分配之后进行的,但是在创建对象的过程中,这两个操作的作用是不同的。

1.分配内存空间alloc

在为一个对象分配内存空间时,需要调用alloc或者allocWithZone:方法。

除了为对象在程序的内存区划定一块合适大小的内存空间之外,alloc方法还有以下几个重要作用:

  • 将对象的引用计数(ReferenceCount)设置为1。其中,引用计数与对象的内存管理有关,在ARC模式下,当引用计数为0时,对象会被释放。
  • 初始化对象的isa指针并指向对象的类。在实际开发过程中,会遇到对象类和类对象两个概念,其中,对象类是一个根据类定义编译得到的运行对象。另外,每一个对象都有一个isa指针标识其是哪个类的实例。
  • 将类中定义的属性(实例变量)的值初始化为0或者nil。

如下方的示例代码,创建了一个MYClass类的对象,只执行了alloc操作,在内存中分配了内存空间,但未进行任何初始化操作。打印了这个对象的地址是存在的,但是其name属性的值为空。

运行结果如图3-11所示。

图3-11 运行结果

2.初始化init

初始化的过程将对象的实例变量设置为合理且有用的初始值,还可以分配和准备对象需要的其他全局资源,并在必要时加载诸如文件这样的资源。初始化方法一般都以init开头,可以设置多个初始化的方法,例如,NSString类提供了如下初始化方法:

以init方法为例,在对象调用init方法时,主要完成了以下工作:

  • 调用父类的初始化方法[super init];。
  • 如果父类返回的对象不为空,则可以对对象进行进一步的设置;例如,在一个自定义UIView类中,可以设置该类的backgroundColor属性。
  • 如果父类返回的对象为nil,则直接返回nil。

3.类方法

类方法是方法前面为+号的方法,类方法把创建对象过程中的两个步骤(内存空间分配+初始化)合并,直接返回被创建的对象。在实际开发过程中,类方法的使用非常普遍,例如,NSString类也提供了如下类方法:

下方的示例代码中分别使用类方法和实例方法创建了NSString类型的对象,并打印出字符串的内容。

运行结果如图3-12所示。

图3-12 运行结果

3.4.2 对象操作

针对对象的常见操作主要包括:判断对象的类型、判断对象是否响应消息、对象间的比较以及对象复制。

1.判断对象的类型

对象通过调用isKindOfClass:方法,可以判断对象的类型。isKindOfClass:方法是NSObject类的方法,将类型为Class的对象aClass作为参数传入,返回一个BOOL类型的返回值。

例如,下面的代码用来判断对象str是否为NSString类型,如果是NSString类型,则打印一段日志。

运行结果如图3-13所示。

图3-13 运行结果

另外,isKindOfClass:方法还可以用于判断子类对象的类型,如下面的代码所示,NSMutableString是NSString的子类,代码执行后,isKindOfClass:方法会认定mutableStr对象也是属于NSString类型。

运行结果如图3-14所示。

图3-14 运行结果

2.判断对象是否响应消息

在Objective-C中,调用对象的方法需要向对象发送消息,这是Objective-C语言的重要特征。要判断一个对象是否响应一条消息,则可以调用respondsToSelector:方法。应用程序通常在验证一个对象响应一则消息后,才将消息发送给该对象。

这种机制常常用于代理中,先判断代理对象是否响应代理方法,如果响应,则代表代理对象中已经实现了代理方法,然后再通知代理对象执行代理方法。

在下方的示例代码中演示了respondsToSelector:方法的使用方法。

  • 在自定义类MYClass.h文件中,添加一个name属性。
  • 在自定义类MYClass.m文件中,对属性进行懒加载(getter方法)。
  • 在main()中,判断自定义类是否实现了属性的getter方法。

运行结果如图3-15所示。

图3-15 运行结果

3.对象间的比较

当需要对比两个对象是否相同时,可以使用isEqual:方法。如果相同,则该方法返回YES。该方法是在NSObject类中定义的,因此所有的对象都可以调用这个方法。另外,在最常用的Foundation框架中,也提供了isEqualToString:或者isEqualToDictionary:等方法,在实际开发中使用更加广泛一些。

下方的示例代码中,对字符串进行了比较操作,使用了isEqual:方法以及isEqualToString:方法。

运行结果如图3-16所示。

图3-16 运行结果

4.对象复制

通过调用copy方法,可以创建对象的副本。调用copy方法,有个前提条件,即接收的对象的类必须遵守NSCopying协议。另外,在使用对象复制时,还需要考虑针对该对象是深复制(对象复制),还是浅复制(指针复制),有关深复制与浅复制后续会详细介绍。

下面的示例代码中,由于NSString类在定义中遵守了NSCopying协议,因此可以对NSString类型的字符串对象进行复制。

运行结果如图3-17所示。

图3-17 运行结果