如何将 NSMutableArray 转换为 NSArray?

Posted

技术标签:

【中文标题】如何将 NSMutableArray 转换为 NSArray?【英文标题】:How do I convert NSMutableArray to NSArray? 【发布时间】:2010-12-18 15:26:27 【问题描述】:

如何在objective-c 中将 NSMutableArray 转换为 NSArray?

【问题讨论】:

只是NSArray *array = [mutableArray copy]; NSArray *array = mutableArray; 铍:完全正确。 vladof81:当然不是。 【参考方案1】:
NSArray *array = [mutableArray copy];

Copy 制作不可变副本。这非常有用,因为 Apple 可以进行各种优化。例如将copy 发送到不可变数组只保留对象并返回self

如果您不使用垃圾回收或 ARC,请记住 -copy 保留对象。

【讨论】:

这个答案很好,但是我如何从文档中得知 copy 创建的是普通的 NSArray 而不是 NSMutableArray? @Yar: 你看看the documentation of NSCopying 它在那里声明:copyWithZone 如果“不可变与可变”的考虑适用于接收,则返回的副本是不可变的目的;否则副本的确切性质由类确定。 非常整洁 - 我更喜欢这个而不是 m5h 的解决方案。既简洁又高效。 我同意大卫,更新了我的回复以指向此回复。 @Brad:这只是意味着具有可变和不可变实现的类。例如。 NSArray & NSMutableArray, NSString & NSMutableString。但不是例如NSViewController,它总是包含可变状态。【参考方案2】:

NSMutableArrayNSArray 的子类,因此您并不总是需要转换,但如果您想确保数组不能被修改,您可以创建一个 NSArray 任何一种方式,具体取决于关于您是否希望它自动发布:

/* Not autoreleased */
NSArray *array = [[NSArray alloc] initWithArray:mutableArray];

/* Autoreleased array */
NSArray *array = [NSArray arrayWithArray:mutableArray];

编辑: Georg Schölly 提供的The solution 是一种更好的方法,而且更简洁,尤其是现在我们有了 ARC,甚至不必调用 autorelease。

【讨论】:

我可以做 (NSArray *) myMutableArray 吗? 是的,因为 NSMutableArray 是有效的 NSArray 的子类。 但是,转换为 (NSArray *) 仍然允许转换回 (NSMutable *)。不是这样吗? @sharvey:是的,没错。如果您不强制转换而是直接将超类分配给子类,则会收到警告。通常,您希望返回一个不可变的副本,因为这是确保您的数组真的不会被修改的唯一方法。 以前称为"Upcasting" (NSArray *) myMutableArray,反之称为"Downcasting"【参考方案3】:

我喜欢这两个主要解决方案:

NSArray *array = [NSArray arrayWithArray:mutableArray];

或者

NSArray *array = [mutableArray copy];

我在它们中看到的主要区别是当 mutableArray 为 nil 时它们的行为方式

NSMutableArray *mutableArray = nil;
NSArray *array = [NSArray arrayWithArray:mutableArray];
// array == @[] (empty array)

NSMutableArray *mutableArray = nil;
NSArray *array = [mutableArray copy];
// array == nil

【讨论】:

这是大错特错。刚检查。 [mutableArray copy] 也返回一个空数组。 @durazno 没错。仔细检查你的测试。如果 [mutableArray copy] 返回一个空数组,那么 mutableArray 一定是一个空数组。我的回答只适用于 mutableArray 为 nil 时。 虽然这是真的,但我觉得你在你的例子中错过了一个更基本的事实。由于您已将 mutableArray 指定为 nil,因此 [mutableArray copy] 可以简化为 [nil copy]。在 Objective-c 中,发送给 nil 的 any 消息将始终为 nil。重要的是要记住“无”和“没有任何内容的数组”之间的区别。 @mkirk 我们不要从手头的问题上分心:“如何将 NSMutableArray 转换为 NSArray?”有两种主要解决方案,它们之间的主要区别在于当可变数组为 nil 时它们的行为方式。【参考方案4】:

你试试这个代码---

NSMutableArray *myMutableArray = [myArray mutableCopy];

NSArray *myArray = [myMutableArray copy];

【讨论】:

这有什么其他人没有做到的?【参考方案5】:

目标-C

以下是将 NSMutableArray 转换为 NSArray 的方法:

//oldArray is having NSMutableArray data-type.
//Using Init with Array method.
NSArray *newArray1 = [[NSArray alloc]initWithArray:oldArray];

//Make copy of array
NSArray *newArray2 = [oldArray copy];

//Make mutablecopy of array
NSArray *newArray3 = [oldArray mutableCopy];

//Directly stored NSMutableArray to NSArray.
NSArray *newArray4 = oldArray;

斯威夫特

在 Swift 3.0 中有新的数据类型 Array。使用 let 关键字声明数组然后它会变成 NSArray 如果使用 var 关键字声明它就会变成 NSMutableArray强>。

示例代码:

let newArray = oldArray as Array

【讨论】:

Swift 部分并不完全正确。有关可变/不可变Arrays 和NSArray/NSMutableArrays 之间的区别,请参见here 和here。它们不一样。【参考方案6】:

在objective-c中:

NSArray *myArray = [myMutableArray copy];

迅速:

 var arr = myMutableArray as NSArray

【讨论】:

【参考方案7】:
NSArray *array = mutableArray;

这个[mutableArray copy] 反模式是示例代码。对于临时的并在当前范围结束时被释放的一次性可变数组,请停止这样做。

运行时无法优化对即将超出范围、减为 0 并永久释放的可变数组的浪费复制。

【讨论】:

NSMutableArray 分配给NSArray 变量不会隐藏它(这是OP 的问题所在)。如果该值意外变异,则公开此类值(例如作为返回值或属性)可能会导致非常难以调试的问题。这适用于内部和外部突变,因为可变值是共享的。 要改变那个数组,你必须 [NSMutableArray arrayWithArray:... 或类似的东西。 不一定。只需将其分配给NSMutableArray 变量就足够了。由于对象从未停止成为可变数组,因此对其调用变异方法将成功并改变共享数据。另一方面,如果原始可变数组被复制(将其更改为不可变数组),然后分配给NSMutableArray 变量并在其上调用了变异方法,则这些调用将失败并出现doesNotRespondToSelector 错误,因为接收到的对象变异方法调用实际上是不可变的,不会响应那些方法。 好的,这对于不注意编译器关于类型转换分配的警告的开发人员可能有一些好处【参考方案8】:

如果您通过可变性构造一个数组,然后想要返回一个不可变版本,您可以简单地通过继承将可变数组作为“NSArray”返回。

- (NSArray *)arrayOfStrings 
    NSMutableArray *mutableArray = [NSMutableArray array];
    mutableArray[0] = @"foo";
    mutableArray[1] = @"bar";

    return mutableArray;

如果您“信任”调用者将(技术上仍然可变的)返回对象视为不可变的 NSArray,那么这比[mutableArray copy] 更便宜。

Apple concurs:

要判断是否可以改变接收到的对象,消息的接收者必须依赖返回值的形式类型。例如,如果它接收到一个类型为不可变的数组对象,它不应该尝试改变它。根据对象的类成员资格来确定对象是否可变是不可接受的编程实践。

这里将更详细地讨论上述做法:

Best Practice: Return mutableArray.copy or mutableArray if return type is NSArray

【讨论】:

【参考方案9】:

我在 swift 3 中搜索答案,这个问题在搜索中显示为第一个结果,我从中得到了答案 所以这里是 swift 3 代码

let array: [String] = nsMutableArrayObject.copy() as! [String]

【讨论】:

以上是关于如何将 NSMutableArray 转换为 NSArray?的主要内容,如果未能解决你的问题,请参考以下文章

将 FMResultSet 转换为 NSMutableArray?

类型为 var Array 的 Swift 类字段被转换为不可变的 NSArray 而不是 NSMutableArray

如何将字符串从 NSMutableArray 传递给 double

如何在 iphone sdk 中将 NSArray/NSMutableArray 转换为 NSFetchedResultsController?

Obj-C:将对象数组转换为 NSDictionary 以与 JSONRepresentation 一起使用

无法将“NSMutableArray”类型的值转换为预期的参数类型“[SKTexture]”