我正在将我的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'的子类型
有没有办法做我想在这里做的事情?
答案 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()