如何将NSMutableArray转换为特定类型的Swift数组?

时间:2014-09-14 20:10:14

标签: ios objective-c swift

我正在将我的iOS项目迁移到Swift。我是按班做的。当我从Swift调用Objective C方法时,很多Objective C类型都转换为它们的Swift对应物。

在我的情况下,Objective C NSMutableArray被转换为Swift的Array<AnyObject>。现在我的问题来了。在我的Swift类中,我从Objective C对象中获取了这样一个数组。既然我在Swift世界中,我想将此数组转换为特定类型而不是AnyObject,因为我确定该数组中存在哪种对象。

编译器不允许我这样做!让我通过说我想要转换为包含字符串的数组来简化我的问题。这就是我试过的:

var strings = myObjcObject.getStrings() as [String]

我从编译器中收到以下错误:

  

'String'与'AnyObject'

不同

我必须同意编译器,因为String确实与AnyObject不同。但我不明白为什么这是一个问题。如果我愿意,我可以将AnyObject转发给String,对吗?

我也尝试过:

var strings = myObjcObject.getStrings() as? [String]

这似乎是朝着正确方向迈出的一步,但getStrings()返回NSMutableArray,因此我收到以下错误:

  

'NSArray'不是'NSMutableArray'的子类型

有没有办法做我想在这里做的事情?

8 个答案:

答案 0 :(得分:124)

你可以通过双向下转换来完成这项工作,首先是NSArray,然后是[String]

var strings = myObjcObject.getStrings() as NSArray as [String]

在Playground中测试:

import Foundation

var objCMutableArray = NSMutableArray(array: ["a", "b", "c"])
var swiftArray = objCMutableArray as NSArray as [String]

更新

在Swift的后续版本(至少1.2)中,编译器会抱怨as [String]。相反,您应该使用if let条件下转as?

import Foundation

var objCMutableArray = NSMutableArray(array: ["a", "b", "c"])
if let swiftArray = objCMutableArray as NSArray as? [String] {
    // Use swiftArray here
}

如果您 绝对 确定您的NSMutableArray可以投放到[String],那么您可以使用as!代替({1>}但在大多数情况下你可能不应该使用它):

import Foundation

var objCMutableArray = NSMutableArray(array: ["a", "b", "c"])
var swiftArray = objCMutableArray as NSArray as! [String]

答案 1 :(得分:30)

compactMap是您在Swift 4.1及更高版本中的朋友,也是Swift 3.3-3.4中的朋友。这意味着您没有任何双重或强制转换。

let mutableArray = NSMutableArray(array: ["a", "b", "c"])
let swiftArray: [String] = mutableArray.compactMap { $0 as? String }

在以前版本的Swift,2.0-3.2和4.0中,您需要使用flatMap来实现此目的。用法与compactMap相同:

let swiftArray: [String] = mutableArray.flatMap { $0 as? String }

答案 2 :(得分:5)

使用Swift 1.2,以下内容将起作用:

let mutableArray = NSMutableArray(array: ["a", "b", "c"])
let swiftArray = NSArray(array: mutableArray) as? [String]

答案 3 :(得分:5)

let mutableArray = NSMutableArray()

mutableArray.add("Abc")
mutableArray.add("def")
mutableArray.add("ghi")

if let array = mutableArray as? [String] {
    print(array)    // ["Abc", "def", "ghi"]
}

答案 4 :(得分:2)

在Xcode 6.3中我使用了以下内容:

var mutableArray = NSMutableArray(array:"1", "2", "3")
let swiftArray = mutableArray as AnyObject as! [String]

答案 5 :(得分:1)

for swift 3

您可以考虑以下代码

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

答案 6 :(得分:0)

在我的情况下,编译器希望我这样写,以消除所有警告和编译问题,因此,即使已将imageImagesField声明为1,也不只是带有感叹号,还应加上括号和“ as!”。确保没有人抱怨。

(imagesField!.images as! [UIImage]) 

这让我感到非常不舒服。Swift可能更好,它的新语言是……我做了扩展:

 public static func cast(_ object: Any) -> Self {
        return object as! Self
    }

将其分配给数组:

extension Array: CSLang {
}

现在我可以像这样写同样的语句了,效果相同:

[UIImage].cast(imagesField.images)

不管喜欢与否,这是我的方式,问号和感叹号更少,更好。我也做了单元测试:

func testCast() {
    let array: NSMutableArray? = NSMutableArray()
    array?.add("test string 1")
    array?.add("test string 2")
    let stringArray: [String] = [String].cast(array)
    XCTAssertEqual("test string 2", stringArray[1])
}

答案 7 :(得分:0)

我为此在NSArray上创建了一个扩展。

extension NSArray {
    func swiftArray<T>() -> [T] {
        let result: [T] = self.compactMap { $0 as? T }
        return result
    }
}

class Test {
    var title: String
    init(title: String) {
        self.title = title
    }
}

let mutableArray = NSMutableArray()
mutableArray.add(Test(title: "1"))
mutableArray.add(Test(title: "2"))
mutableArray.add(Test(title: "3"))
mutableArray.add(Test(title: "4"))

let tests: [Test] = mutableArray.swiftArray()