![iOS开发:从零基础到精通](https://wfqqreader-1252317822.image.myqcloud.com/cover/796/26793796/b_26793796.jpg)
3.4 对象
3.4.1 创建对象
对象是类Class运行时的实例,它包含了自己的实例变量(属性中声明)的内存副本以及类方法的指针,在实际开发中可以采用分配内存地址alloc以及初始化init两个步骤来创建一个对象。
对象的创建分为两个阶段:内存空间分配和初始化。通常情况下,初始化总是紧跟在内存空间分配之后进行的,但是在创建对象的过程中,这两个操作的作用是不同的。
1.分配内存空间alloc
在为一个对象分配内存空间时,需要调用alloc或者allocWithZone:方法。
除了为对象在程序的内存区划定一块合适大小的内存空间之外,alloc方法还有以下几个重要作用:
- 将对象的引用计数(ReferenceCount)设置为1。其中,引用计数与对象的内存管理有关,在ARC模式下,当引用计数为0时,对象会被释放。
- 初始化对象的isa指针并指向对象的类。在实际开发过程中,会遇到对象类和类对象两个概念,其中,对象类是一个根据类定义编译得到的运行对象。另外,每一个对象都有一个isa指针标识其是哪个类的实例。
- 将类中定义的属性(实例变量)的值初始化为0或者nil。
如下方的示例代码,创建了一个MYClass类的对象,只执行了alloc操作,在内存中分配了内存空间,但未进行任何初始化操作。打印了这个对象的地址是存在的,但是其name属性的值为空。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T75_82821.jpg?sign=1738888752-PzQ5zk02J6Ct5MDJzgkoTUbcEPOKGpuS-0-8d07766b1618ad8becfee222bf4f43a3)
运行结果如图3-11所示。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-P75_9026.jpg?sign=1738888752-1rV1r90BABpuommqNTFc1lpo861l1d96-0-5c22c45c218b52dff3abb4ce52713879)
图3-11 运行结果
2.初始化init
初始化的过程将对象的实例变量设置为合理且有用的初始值,还可以分配和准备对象需要的其他全局资源,并在必要时加载诸如文件这样的资源。初始化方法一般都以init开头,可以设置多个初始化的方法,例如,NSString类提供了如下初始化方法:
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T75_9030.jpg?sign=1738888752-0itQcN7F2eMgonONMFq2wxI2amd83cpA-0-cc58355635abf39ddbe51dc6cd680e39)
以init方法为例,在对象调用init方法时,主要完成了以下工作:
- 调用父类的初始化方法[super init];。
- 如果父类返回的对象不为空,则可以对对象进行进一步的设置;例如,在一个自定义UIView类中,可以设置该类的backgroundColor属性。
- 如果父类返回的对象为nil,则直接返回nil。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T76_9178.jpg?sign=1738888752-5fDV2SvEQTGiPq2UvPTuJsIeFTVj6ilb-0-591aed2de43680ff47f74af391b0f344)
3.类方法
类方法是方法前面为+号的方法,类方法把创建对象过程中的两个步骤(内存空间分配+初始化)合并,直接返回被创建的对象。在实际开发过程中,类方法的使用非常普遍,例如,NSString类也提供了如下类方法:
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T76_9180.jpg?sign=1738888752-NaFS33iXGud4HTuvIqqYzIGVGXvCD2gt-0-d43872eab5885fa5bd59a321a6661213)
下方的示例代码中分别使用类方法和实例方法创建了NSString类型的对象,并打印出字符串的内容。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T76_9182.jpg?sign=1738888752-ISyBOSNjSd0luqKAkSug1xY7KlSjkyLd-0-0bd05300ea7c82c237658205d928b1a2)
运行结果如图3-12所示。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-P77_9285.jpg?sign=1738888752-MUGLTnfnUhtOHuZPKbMbApnlbw3gUSA9-0-4d3949a1f2cbb3b6b58ccdeb58af464c)
图3-12 运行结果
3.4.2 对象操作
针对对象的常见操作主要包括:判断对象的类型、判断对象是否响应消息、对象间的比较以及对象复制。
1.判断对象的类型
对象通过调用isKindOfClass:方法,可以判断对象的类型。isKindOfClass:方法是NSObject类的方法,将类型为Class的对象aClass作为参数传入,返回一个BOOL类型的返回值。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T77_9290.jpg?sign=1738888752-zAbfjt49kOzrQd1SnmD1LpQnuOxaOjcR-0-b77a5ffe9054ccd2f6a60f2b37c1ef7f)
例如,下面的代码用来判断对象str是否为NSString类型,如果是NSString类型,则打印一段日志。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T77_9292.jpg?sign=1738888752-NWU5w41FUEN3MNAKpvwrEwuMOyhmUSe0-0-1a9a413fbfc2dfed87846b617b861eb5)
运行结果如图3-13所示。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-P77_9294.jpg?sign=1738888752-iTfYLrwXHG2MpJZ5M4tUEtELJFCN1HKC-0-38597726e54a3b3d068942d514c1c539)
图3-13 运行结果
另外,isKindOfClass:方法还可以用于判断子类对象的类型,如下面的代码所示,NSMutableString是NSString的子类,代码执行后,isKindOfClass:方法会认定mutableStr对象也是属于NSString类型。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T77_9298.jpg?sign=1738888752-1im3Ozi46IbkZq1kcLsXsnmWezU7iTUE-0-b106f2b89b940a20568523aac8205835)
运行结果如图3-14所示。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-P78_9426.jpg?sign=1738888752-Un3rrg29MkaqTqYKT7iwKcTB4Pq2qxJa-0-bb3a12d931f49a86b0492e02f4c7029e)
图3-14 运行结果
2.判断对象是否响应消息
在Objective-C中,调用对象的方法需要向对象发送消息,这是Objective-C语言的重要特征。要判断一个对象是否响应一条消息,则可以调用respondsToSelector:方法。应用程序通常在验证一个对象响应一则消息后,才将消息发送给该对象。
这种机制常常用于代理中,先判断代理对象是否响应代理方法,如果响应,则代表代理对象中已经实现了代理方法,然后再通知代理对象执行代理方法。
在下方的示例代码中演示了respondsToSelector:方法的使用方法。
- 在自定义类MYClass.h文件中,添加一个name属性。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T78_9430.jpg?sign=1738888752-Gajl1oUXZOsjdSjRXmBDxAs6P53mUJKS-0-14c3fb4a0f31ebbc29b4efc6c17d7761)
- 在自定义类MYClass.m文件中,对属性进行懒加载(getter方法)。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T78_9432.jpg?sign=1738888752-l67OOyZYDgLTtRj7J9jf7bJVdWoZ2hY5-0-338d8fd4dd6c3f3f937b9f6983990370)
- 在main()中,判断自定义类是否实现了属性的getter方法。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T78_9434.jpg?sign=1738888752-r9jeoGxOHumVJkHR6aMGKoAuxW8mRUwd-0-fbd0b919efaac2634f42e817d3eb820f)
运行结果如图3-15所示。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-P79_9555.jpg?sign=1738888752-9dUwDenypECQe0GVnzRvPkx9meZnNgK9-0-0222649f2f1e57be627320fdcd5dc7c4)
图3-15 运行结果
3.对象间的比较
当需要对比两个对象是否相同时,可以使用isEqual:方法。如果相同,则该方法返回YES。该方法是在NSObject类中定义的,因此所有的对象都可以调用这个方法。另外,在最常用的Foundation框架中,也提供了isEqualToString:或者isEqualToDictionary:等方法,在实际开发中使用更加广泛一些。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T79_9559.jpg?sign=1738888752-wnL9vfNq01kqc1ZcWTtwmuQGFoicF2XY-0-3cf41425c6212fce2913f244dd3088b9)
下方的示例代码中,对字符串进行了比较操作,使用了isEqual:方法以及isEqualToString:方法。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T79_9561.jpg?sign=1738888752-aleUsuHmW9zis6z9WULjMVxp2a736XNH-0-cc0c11e95734bd016e3ec47f4e279372)
运行结果如图3-16所示。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-P79_9563.jpg?sign=1738888752-q0Y9iwRZqMl72Uk34IgWVrIYZKM3UCV5-0-90add8beebc4f1120d4693a75f6e4968)
图3-16 运行结果
4.对象复制
通过调用copy方法,可以创建对象的副本。调用copy方法,有个前提条件,即接收的对象的类必须遵守NSCopying协议。另外,在使用对象复制时,还需要考虑针对该对象是深复制(对象复制),还是浅复制(指针复制),有关深复制与浅复制后续会详细介绍。
下面的示例代码中,由于NSString类在定义中遵守了NSCopying协议,因此可以对NSString类型的字符串对象进行复制。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T80_82824.jpg?sign=1738888752-CMkUY7bBA8QFrtQmG1chfM4AgLxtzRlZ-0-0abf3177846c38139e85b9a4392e266f)
运行结果如图3-17所示。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-P80_9651.jpg?sign=1738888752-geUGj9hfJA69GEC7WZSU3XNPWcwQlY6R-0-192262cafeb407bc52233db9b3fa01db)
图3-17 运行结果