objective-c - 为什么在 Swift 中使用 NSArray 是可变的?

标签 objective-c swift nsarray

我有一个具有以下属性的 objective-c header

@property (nullable, nonatomic, strong) NSArray<CustomObject *> *customObjects;

如果我创建该类的快速扩展,我现在可以从 NSArray 中删除对象:

self.customObjects?.remove(at: 0)

如果我这样做了

print(type(of: self.customObjects))

我得到:

Array<CustomObject>

NSArrays 不是不可变的吗?每当我们编辑它时,Swift 是否会创建一个浅拷贝?

最佳答案

您的属性在 ObjC 中被(隐含地)声明为 readwrite。这意味着您可以更改属性编写一个新的 NSArray 实例来替换旧的(在这种情况下,新实例的常量可能是通过首先读取另一个 NSArray 实例派生的属性(property)的现有值(value)):

NSArray *currentObjects = self.customObjects;
// one of many ways to derive one immutable array from another:
NSArray *newArray = [currentObjects subarrayWithRange:NSMakeRange(1, currentObjects.count - 1)];
self.customObjects = newArray;

在 Swift 中,您的属性表现为 Swift.Array(即 Swift 标准库中的 Array 类型),这是一种值类型。每个赋值都在语义上创建一个副本。 (使用“写时复制”模式可以推迟执行复制的昂贵工作。引用类型的数组,如对象,复制引用而不是存储,因此它本质上是一个“浅拷贝”。)

变异操作也是这样做的:

let currentObjects1 = self.customObjects
currentObjects1.remove(0) // compile error
// currentObjects1 is a `let` constant so you can't mutate it

var currentObjects = self.customObjects
currentObjects.remove(0) // ok

print(self.customObjects.count - currentObjects.count) 
// this is 1, because currentObjects is a copy of customObjects
// we mutated the former but not the latter so their count is different

self.customObjects = currentObjects
// now we've replaced the original with the mutated copy just as in the ObjC example

当你在 Swift 中有一个 readwrite 属性,并且该属性的类型是像 Array 这样的值类型(或者是桥接到值类型的 ObjC 类型,像 NSArray),您可以直接在属性上使用变异方法。这是因为调用变异方法在语义上等同于读取(和复制)现有值、改变副本,然后写回更改后的副本。

// all equivalent
self.customObjects.remove(0)
self.customObjects = self.customObjects.dropFirst(1)
var objects = self.customObjects; objects.remove(0); self.customObjects = objects

顺便说一句:如果您正在为此处讨论的 ObjC 类设计 API,您可能会考虑将 customObjects 属性设置为非空 — 除非空数组和缺失数组之间存在有意义的语义差异,您的 Swift 客户端会发现区分两者很麻烦。

关于objective-c - 为什么在 Swift 中使用 NSArray 是可变的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55189050/

相关文章:

iphone - 为什么我的 NSArray intValue 没有按预期工作?

objective-c - 将自定义 NSArray 数据保存到 iPhone

objective-c - 如何在 OpenGL 中正确正交渲染纹理?

ios - 获取 CCCryptorStatus "-4310"

arrays - 将 id 内的数组字符串值与 Swift 3 中的索引匹配

objective-c - 如何从 NSMutableArray 分配整数

ios - 在 iOS 中滚动时保留 TableView 单元格中的按钮状态

ios - 使用两个以上的参数在 Objective-C 中执行动态类方法调用

ios - 快速转换

objective-c - 如何停止 enumerateObjectsUsingBlock Swift