![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=1739330731-FUUGJApBKZMGefiWUyo3F1UfL7VhCUOy-0-105313f4f1cef3a507284950b27c6940)
运行结果如图3-11所示。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-P75_9026.jpg?sign=1739330731-EBwYgtAKMZphnrtLJWtFZLGjw4sCxmO6-0-0cd48a36ec8cbb1e79817247b3f18207)
图3-11 运行结果
2.初始化init
初始化的过程将对象的实例变量设置为合理且有用的初始值,还可以分配和准备对象需要的其他全局资源,并在必要时加载诸如文件这样的资源。初始化方法一般都以init开头,可以设置多个初始化的方法,例如,NSString类提供了如下初始化方法:
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T75_9030.jpg?sign=1739330731-kS1vClAQa1vqRuPloauUkMFL41SkNNlX-0-0e13a925b89b6963b496445317dc67f7)
以init方法为例,在对象调用init方法时,主要完成了以下工作:
- 调用父类的初始化方法[super init];。
- 如果父类返回的对象不为空,则可以对对象进行进一步的设置;例如,在一个自定义UIView类中,可以设置该类的backgroundColor属性。
- 如果父类返回的对象为nil,则直接返回nil。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T76_9178.jpg?sign=1739330731-A5MCNXLEiHgEuGCMue2oXnvfPwsLVdjT-0-075e449968868b1e6b9c9d9221199cfe)
3.类方法
类方法是方法前面为+号的方法,类方法把创建对象过程中的两个步骤(内存空间分配+初始化)合并,直接返回被创建的对象。在实际开发过程中,类方法的使用非常普遍,例如,NSString类也提供了如下类方法:
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T76_9180.jpg?sign=1739330731-mnELgSrU4vxJNP3iMLvWm4OlHplkBmMq-0-53a776d63fa00f30f87942a81249f0be)
下方的示例代码中分别使用类方法和实例方法创建了NSString类型的对象,并打印出字符串的内容。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T76_9182.jpg?sign=1739330731-spDKTRJWRI08agMGMacMTpWvacnLw42p-0-6b091dd127629cbab0b155fb8229b520)
运行结果如图3-12所示。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-P77_9285.jpg?sign=1739330731-C9Q6lUpZpId5ltUt7FCF53RWxUmmDs5Y-0-482cae82ed580204cae45234ade5e71f)
图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=1739330731-oz6uU9wQ4Y3ib3qS40CzxUZ8iyOXsvha-0-8caf4f554437d7efa7f7d145f0b69c11)
例如,下面的代码用来判断对象str是否为NSString类型,如果是NSString类型,则打印一段日志。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T77_9292.jpg?sign=1739330731-dXGOCKIBNmUGFIC2oWtIvOwtYNFZTsG4-0-cc0f5af27f519790e4c7ede7ff8a8a2b)
运行结果如图3-13所示。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-P77_9294.jpg?sign=1739330731-9wExEsiYKPl4upLeYkqpXzW9HjvJ6mgH-0-8ab1f75dab592c6dd5fd65b36bcadc87)
图3-13 运行结果
另外,isKindOfClass:方法还可以用于判断子类对象的类型,如下面的代码所示,NSMutableString是NSString的子类,代码执行后,isKindOfClass:方法会认定mutableStr对象也是属于NSString类型。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T77_9298.jpg?sign=1739330731-CIb1XT64tQGlWvGHjEaGd78sXmEyNLC5-0-9183755f10f140b6935327ef1cd1057f)
运行结果如图3-14所示。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-P78_9426.jpg?sign=1739330731-UlXwZzZQf8ulRNHS0xKQlYF4L9DWZnyb-0-1bb82ffa44c5abe6202cea3cd8fee6b8)
图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=1739330731-uxDsL2ipzbeTh37NHUve8S1lXrhYyyOn-0-6e361f802e5c2997e8accbda5b9ed2f1)
- 在自定义类MYClass.m文件中,对属性进行懒加载(getter方法)。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T78_9432.jpg?sign=1739330731-U0KtWN7US9rHYikk5zzBbS5WvlsmqZ6n-0-2d06f743d35d61c982da80fad2e9db7c)
- 在main()中,判断自定义类是否实现了属性的getter方法。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T78_9434.jpg?sign=1739330731-0SuaU1NYPrT6HWt5PEdcSVii4vrMvoXS-0-a698388291ece8cbe50c38b73b5722b7)
运行结果如图3-15所示。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-P79_9555.jpg?sign=1739330731-5cYFkVPZ1S0b3fub37fibWiB8GZZ9zEI-0-10cf2c30446065ace8088d0043f72f8e)
图3-15 运行结果
3.对象间的比较
当需要对比两个对象是否相同时,可以使用isEqual:方法。如果相同,则该方法返回YES。该方法是在NSObject类中定义的,因此所有的对象都可以调用这个方法。另外,在最常用的Foundation框架中,也提供了isEqualToString:或者isEqualToDictionary:等方法,在实际开发中使用更加广泛一些。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T79_9559.jpg?sign=1739330731-k6Gwa3KYnWRMrYowbFXEMdZGHNpyKk4b-0-65129bd30ff6ced300df702187dc2d5d)
下方的示例代码中,对字符串进行了比较操作,使用了isEqual:方法以及isEqualToString:方法。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T79_9561.jpg?sign=1739330731-fYvXhY6VFwgC1z30EGq21gGOkee3AELU-0-ad2ccc83e43ccc086565ef7ec9ab89d3)
运行结果如图3-16所示。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-P79_9563.jpg?sign=1739330731-9QYlmO3MUTNsAPuTBQ3dnLyejDvdfYt4-0-19cbd88af909ab97a698370ea71d75e7)
图3-16 运行结果
4.对象复制
通过调用copy方法,可以创建对象的副本。调用copy方法,有个前提条件,即接收的对象的类必须遵守NSCopying协议。另外,在使用对象复制时,还需要考虑针对该对象是深复制(对象复制),还是浅复制(指针复制),有关深复制与浅复制后续会详细介绍。
下面的示例代码中,由于NSString类在定义中遵守了NSCopying协议,因此可以对NSString类型的字符串对象进行复制。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T80_82824.jpg?sign=1739330731-HBRB8sXkF6BSZwR0EzPaucGHNWCUHrqG-0-e85da21db941d35dba19699b12e8d1b3)
运行结果如图3-17所示。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-P80_9651.jpg?sign=1739330731-Ur1sXUyBe6bPNZxtXVTvkqvL2cFvXrJU-0-aff2500f5bc73b98b1d1f91581de38bf)
图3-17 运行结果