在 Swift 中:Array VS NSArray VS [AnyObject] 之间的区别

Posted

技术标签:

【中文标题】在 Swift 中:Array VS NSArray VS [AnyObject] 之间的区别【英文标题】:in Swift: Difference between Array VS NSArray VS [AnyObject] 【发布时间】:2015-05-07 12:31:43 【问题描述】:

正如标题所说,Array vs NSArray vs [AnyObject] 有什么区别?

此外,最推荐的解决方法是什么。我的意思是推荐的是,最简单的实现是什么。谢谢。

【问题讨论】:

这与 Xcode 无关。 Array 本身不是类型,你需要一个类型参数。 [AnyObject]Array<AnyObject> 一样,都是 Swift 内置的数组类型。 NSArray 是一个 Objective-C 类类型。 【参考方案1】:

Array 是一个 Swift 结构和泛型结构,这意味着它可以是任何特定类型(Int、String、AnyObject 等)的数组

[T]Array<T> 的语法糖

AnyObject 是任何类的对象,包括 Objective-C 类。

NSArray 是一个 Objective-C 构造,可以容纳任何 Objective-C 对象,并且透明地映射到 Array<AnyObject> 和从 Array<AnyObject>

【讨论】:

构造 NSArray 并不总是透明地映射到 [AnyObject]。您可以通过添加“as [anyObject]”来转换它。当您使用 arrayByAddingObjectsFromArray() 将 NSArray 附加到另一个时,这很有用。【参考方案2】:

Array 是一个 struct,因此在 Swift 中它是一个 值类型NSArray 是一个不可变的Objective C ,因此它是Swift 中的一个引用类型,它被桥接到Array<AnyObject>NSMutableArrayNSArray 的可变子类。

var arr : NSMutableArray = ["Pencil", "Eraser", "Notebook"]
var barr = ["Pencil", "Eraser", "Notebook"]

func foo (var a : Array<String>)

    a[2] = "Pen"


func bar (a : NSMutableArray)

    a[2] = "Pen"


foo(barr)
bar(arr)

println (arr)
println (barr)

打印:

(
    Pencil,
    Eraser,
    Pen
)
[Pencil, Eraser, Notebook]

因为foo 更改了a 的本地值,而bar 更改了引用。 如果您使用 let arr 而不是 var 与其他引用类型一样,它也将起作用。

【讨论】:

对于 Swift 3,var 参数已经被移除,添加到 foo() 的第一行:var a = a 在 Swift 3.0 中移除 var 参数是由于对引用和值类型的混淆。 (见SE-0003 Proposal)。代码将不再编译,但 IMO 最能显示差异,所以我会保持原样。 NSMutableArray 与 (inout:[AnyObject]) 哪个更好【参考方案3】:

使用 Krzak 的答案,这里是一个实际的例子:

// Let´s create an Array as a struct showing alternative ways
    var arrStruct = ["Pencil", "Eraser", "Notebook"]
    // or var arrStruct: [String] = ["Pencil", "Eraser", "Notebook"]
    // or var arrStruct: Array = ["Pencil", "Eraser", "Notebook"]
    // or var arrStruct = Array(["Pencil", "Eraser", "Notebook"])
    // All this alternative ways create an array as struct

    // Now let´s create a function that modifies this array struct
    func modifyArr(alternativeArr: [String]) 
    // or func modify(alternativeArr: Array<String>)
    
        alternativeArr[2] = "Pen" // compilation error
        // This won´t work. In swift >= 3.0 all func parametes are a let variable, 
        // this means alternativeArr is defined as a let. What one has to do is 
        // create a local variable and copy the value.

        var localAlternativeArr = alternativeArr
        // or var localAlternativeArr: [String] = alternativeArr
        // or var localAlternativeArr: Array = alternativeArr

        // now we can change it.
        localAlternativeArr[2] = "Pen"
        print(localAlternativeArr) // ["Pencil", "Eraser", "Pen"]
        print(alternativeArr) // ["Pencil", "Eraser", "Notebook"]
    

    modifyArr(alternativeArr: arrStruct)
    print(arrStruct) // ["Pencil", "Eraser", "Notebook"]

    // Since the arrStruct is a struct every time we assign to another variable or 
    // pass it as a func argument a copy is made.



// Now let´s create as an NSMutableArray
    var arrClass: NSMutableArray = ["Pencil", "Eraser", "Notebook"]
    // or var arrStruct = NSMutableArray(array: ["Pencil", "Eraser", "Notebook"])
    // All this create an NSMutableArray as a class

    // Now let´s create a function that modifies this array struct
    func modifyArr(alternativeArr: NSMutableArray)
    
        alternativeArr[2] = "Pen"
        print(alternativeArr)
        // (
        //   Pencil,
        //   Eraser,
        //   Pen
        // )
    

    modifyArr(alternativeArr: arrClass)
    print(arrClass)
    // (
    //   Pencil,
    //   Eraser,
    //   Pen
    // )

    // Since the arrClass is a class everytime we assign to another variable or 
    // pass it as a func argument is passed by reference. Means that any change
    // inside modifyArr is going to change the arrClass outside. The change 
    // is made in the same pointer.

【讨论】:

【参考方案4】:

加上@Krzak 的出色回答,这就是原因

print(NSArray().object(at: 1))   // Triggers an UnmanagedException

2018-11-09 11:38:08.798088-0600 AppName[38786:10497909] * 由于未捕获的异常“NSRangeException”而终止应用程序,原因:“* -[__NSArray0 objectAtIndex:]:空 NSArray' 超出范围的索引 1'

print(Array<Int>()[1])  // Halts with "Thread 1: Fatal error: Index out of range"

这种对错误的不同处理帮助我理解了其中的区别.....e

【讨论】:

以上是关于在 Swift 中:Array VS NSArray VS [AnyObject] 之间的区别的主要内容,如果未能解决你的问题,请参考以下文章

Swift vs Kotlin 在排序数组上的表现

Swift 无法将 NSNumber 桥接到 Float [重复]

Swift中Array的删除对象

Swift--Array 详解

教义数组 vs simple_array vs json_array

swift-Array(数组)