• 忘掉天地
  • 仿佛也想不起自己
bingliaolongBingliaolong  2023-09-26 23:07 Aet 隐藏边栏 |   抢沙发  16 
文章评分 3 次,平均分 5.0

可变不可变基础对象

  1. Objective-C中,有很多基础对象都有可变和不可变两种版本:
  2. 不可变:
    1. NSString: 代表不可变的文本字符串。
    2. NSArray: 代表不可变的对象数组。
    3. NSDictionary: 代表不可变的键值对集合。
    4. NSData: 代表不可变的字节缓冲区。
    5. NSSet: 代表不可变的无序对象集合。
    6. NSNumber: 这是一个特例,它只有不可变版本,用于包装基础数据类型如int, float, bool等。
    7. NSValue: 用于包装C语言的结构体,例如CGRect, CGPoint, CGSize等。只有不可变版本
    8. NSCharacterSet: 用于搜索和匹配字符集合。
    9. NSIndexSet: 是一个用于存储唯一整数的集合。
  3. 可变:
    1. NSMutableString: 代表可变的文本字符串。
    2. NSMutableArray: 代表可变的对象数组。
    3. NSMutableDictionary: 代表可变的键值对集合。
    4. NSMutableData: 代表可变的字节缓冲区。
    5. NSMutableSet: 代表可变的无序对象集合。
    6. NSMutableCharacterSet: 是NSCharacterSet的可变版本。
    7. NSMutableIndexSet: 是NSIndexSet的可变版本。
  4. NSString
    1. Objective-C中,NSString是不可变的,意味着你不能修改其实例所持有的字符串内容。
    2. 但你可以改变NSString的指针来指向一个新的NSString对象。
    3. ARC环境中,NSString指针指向的原来的对象会被自动释放,具体是:编译器会自动插入内存管理相关的代码,从而帮助你自动管理对象的生命周期。
    4. 关于ARC机制,见下文

类的继承

必须继承自NSObject

  1. Objective-C中,一个类不是必须要继承自NSObject,但在实际使用中,大多数情况下都建议继承自它,原因如下:
    1. 基础方法和功能: NSObject为派生类提供了一系列基础方法和功能,如-isEqual:, -hash, -description, 和-performSelector:等。
    2. 与Objective-C运行时交互: NSObject协议和类提供了与Objective-C运行时系统交互的基础能力。这使得其派生类能够使用Objective-C的动态特性,如动态方法解析、消息转发等。
    3. 内存管理: 如果你在非ARC (Automatic Reference Counting) 的环境下编写代码,NSObject提供了-retain, -release, 和-autorelease方法来帮助内存管理。
    4. 与Foundation框架协同工作: 很多Foundation框架的API预期它们与NSObject的子类一起使用。

子类重写父类方法

  1. 当子类重写(override)父类的方法时,可以认为它是“覆盖”了父类的那个方法。
  2. 具体地说,当你尝试调用那个方法的时候,运行时系统会先在子类中查找。如果子类有重写的版本,那么运行时系统会调用子类的方法而不是父类的。
  3. 需要注意的是,父类的方法并没有被真正“删除”或“替换”,它仍然存在于父类中,只是在子类的上下文中,子类的版本会被优先考虑。

定义

发消息

  1. Objective-C 术语中,一个对象通过调用另一个对象的方法来向该对象发送消息。
  2. 对象可以向自己发送消息

实例方法

  1. 方法名称前面的减号表示它是实例方法,可以在类的任何实例上调用。
  2. 这与类方法不同,类方法可以在类本身上调用。
  3. 实例方法是与类的实例关联的方法。要调用实例方法,您需要先创建该类的实例(对象),然后通过该实例调用方法。

类方法

  1. 类方法与类本身关联,而不是与类的任何特定实例关联。您不需要创建类的实例来调用类方法。
  2. 在接口定义中,类方法以加号 + 开头。

方法参数

类的实现

  1. 头文件

  1. 源文件

  1. 输出

其他

  1. 每个类的名称在应用程序中必须是唯一的,即使在包含的库或框架中也是如此。

ARC

ARC工作的简要概述:

  1. 引用计数:每个Objective-C对象都有一个关联的引用计数。当一个对象的引用计数变为0时,该对象会被销毁并释放其占用的内存。
  2. 增加引用计数
    1. 当你创建一个新对象(如通过allocnewcopymutableCopy方法),其引用计数默认为1
    2. 当你给某个对象发送retain消息(在非ARC环境下),或者在ARC环境下有新的强引用(strong reference)指向该对象时,该对象的引用计数增加。
  3. 减少引用计数
    1. 在非ARC环境下,发送releaseautorelease消息会减少对象的引用计数。
    2. ARC环境下,当一个强引用(strong reference)不再指向某对象时(例如,指向了其他对象或被设置为nil),编译器会自动为你插入代码来减少该对象的引用计数。
  4. 对象销毁:当对象的引用计数变为0,该对象的dealloc方法会被调用,然后对象占用的内存被释放。

属性修饰符

  1. ARC背后的机制实际上相对复杂,涉及到多个属性修饰符(如strong, weak, assign, copy等)和其他细节
  2. strong (默认的修饰符)
    1. 这意味着属性持有对象的一个强引用。当对象的引用计数为0时,对象会被销毁。
    2. 当你设置一个新的对象到这样的属性上时,新对象的引用计数增加。
    3. 当属性不再持有该对象或被设置为nil时,原对象的引用计数减少。
    4. 常用于对象关联的大多数情况。
  3. weak
    1. 属性持有对象的一个弱引用,不增加对象的引用计数。
    2. 弱引用用于避免引用循环。当对象被销毁时,所有指向它的弱引用都自动变为nil
    3. 常见的用途是委托(delegates)和IBOutletsInterface Builder outlets)。
  4. assign
    1. 通常用于基本数据类型(如int, float等)。
    2. 对于对象类型,它持有对象的一个非保持引用。这意味着即使对象被销毁,该引用也不会自动置为nil(这可能会导致“悬挂指针”问题)。
    3. 使用assign对于对象类型并不是推荐的做法,除非你非常确信对象的生命周期。
  5. copy
    1. 当对象被设置到属性上时,属性会持有该对象的一个复制版本。
    2. 对于字符串属性,通常建议使用copy修饰符,因为这样可以确保该属性持有一个不可变的版本,即使外部赋给它一个可变字符串。
    3. 对于其他需要保持不可变状态的对象(如NSArrayNSDictionary),也可以使用此修饰符。
  6. unsafe_unretained
    1. 类似于assign,但适用于所有对象类型。
    2. 它持有对象的一个非保持引用,即使对象被销毁,该引用也不会自动置为nil
    3. 使用此修饰符有风险,因为可能导致访问已被释放的内存的问题。
  7. readonly
    1. 此修饰符表示属性只可读,不能通过属性来修改它的值。
    2. 它不是直接与内存管理相关的,但是常与上述修饰符一起使用。
  8. readwrite (默认的修饰符)
    1. 此修饰符表示属性是可读可写的。
    2. 同样,它不是直接与内存管理相关的,但是常与上述修饰符一起使用。

使用ARC

  1. Xcode中,打开你的项目。
  2. 选择你的项目目标在Targets列表中。
  3. Build Settings选项卡中,搜索“Automatic Reference Counting”。
  4. 设置“Objective-C Automatic Reference Counting”为“YES”。

关闭ARC

  1. 设置“Objective-C Automatic Reference Counting”为“NO”。

特定文件禁用ARC

  1. 选择你的项目目标。
  2. 选择Build Phases选项卡。
  3. Compile Sources部分,找到你想禁用ARC的文件。
  4. 为该文件添加-fno-objc-arc编译器标志。

使用ARC需要注意:

  1. 不要在你的代码中使用retain, release, 和autorelease
  2. 使用新的ARC属性修饰符,如strong, weak, unsafe_unretained, 和copy
  3. 注意循环引用,特别是使用闭包(block)时。使用weak引用可以避免大多数循环引用。

ARC和autoreleasepool

  1. Autorelease pools 提供了一种延迟释放对象的机制,允许对象在稍后的时间点被释放。
  2. 在非 ARC 环境下,你可能会使用 autorelease 方法来避免立即释放一个对象。这个对象随后会在autoreleasepool中被释放。
  3. ARC 环境下,虽然你不会显式地调用 autorelease,但ARC仍然可能在内部使用它。因此,autoreleasepool仍然是有用的,特别是在大量创建临时对象的循环中。

autorelease

  1. 在非ARC环境中,autorelease是一个常见的内存管理方法,它允许你将对象的所有权交给最近的autorelease pool,该对象在稍后的时间点被释放。
  2. 这意味着对象在当前方法或作用域结束后不会立即被销毁,而是在外部的autorelease pool被释放时销毁。

autoreleasepool

  1. 在非ARC环境下,当你发送一个autorelease消息给一个对象,那个对象会被添加到当前活跃的(最近创建的)autorelease pool中。
  2. 然后,当该autorelease pooldrain或释放时,所有在该pool中的对象都会接收到一个release消息。
  3. ARC环境下,你实际上不能(也不需要)显式地发送autorelease消息给一个对象。ARC会为你自动插入这些消息,以确保内存被正确地管理。
    1. 也是需要放到autoreleasepool中,但是不需要发什么消息。
    2. 原理就是ARC保证了在编译器自动插入一些代码从而能正确释放对象。

关于ARC的理解

  1. 编译期与运行期:在编译期间,ARC会通过静态分析来确定何时自动插入retainreleaseautorelease调用。然后,当程序在运行时执行到这些插入的代码时,才会实际执行相应的内存管理操作。
  2. 例如NSString对象:如果一个NSString指针变量(比如,一个属性)从一个NSString对象切换到另一个,那么确实如此:当新对象被赋值给该指针时,新对象会被retain(增加引用计数),而原对象会被release(减少引用计数)。如果原对象的引用计数变为0,那么它将被立即释放。
  3. 不是"优化",而是"管理":虽然可以将ARC看作是某种优化,但更准确地说,它是一种内存管理机制。它确实优化了编写内存管理代码的过程,但其主要目的是确保对象在不再需要时被正确释放,并且在需要时持续存在。

本文为原创文章,版权归所有,欢迎分享本文,转载请保留出处!

bingliaolong
Bingliaolong 关注:0    粉丝:0 最后编辑于:2023-10-01
Everything will be better.

发表评论

表情 格式 链接 私密 签到
扫一扫二维码分享