简体   繁体   English

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

[英]How can I cast an NSMutableArray to a Swift array of a specific type?

I am migrating my iOS project to Swift. 我正在将我的iOS项目迁移到Swift。 I am doing this class by class. 我是按班做的。 When I call Objective C methods from Swift, a lot of Objective C types are converted to their Swift counterparts. 当我从Swift调用Objective C方法时,许多Objective C类型被转换为它们的Swift对应物。

In my case an Objective C NSMutableArray gets converted to Swift's Array<AnyObject> . 在我的例子中,Objective C NSMutableArray被转换为Swift的Array<AnyObject> Now here comes my problem. 现在我的问题来了。 Within my Swift class, I get such an array back from an Objective C object. 在我的Swift类中,我从Objective C对象中获取了这样一个数组。 Now that I am in the Swift world, I would like to cast this array to a specific type instead of AnyObject , because I know for sure what kind of objects exist in this array. 现在我在Swift世界中,我想将此数组转换为特定类型而不是AnyObject ,因为我确定该数组中存在哪种对象。

The compiler won't let me do that! 编译器不会让我这样做! Let me simplify my problem by saying I want to cast to an array containing strings. 让我通过说我想要转换为包含字符串的数组来简化我的问题。 This is what I tried: 这是我试过的:

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

I get the following error from the compiler: 我从编译器得到以下错误:

'String' is not identical to 'AnyObject' 'String'与'AnyObject'不同

I would have to agree with the compiler, since String is indeed not identical to AnyObject. 我必须同意编译器,因为String确实与AnyObject不同。 But I don't see why that is a problem. 但我不明白为什么这是一个问题。 I can downcast AnyObject to String if I want, right? 如果我愿意,我可以将AnyObject转发给String,对吧?

I also tried: 我也尝试过:

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

This seems to be a step in the right direction, but getStrings() returns an NSMutableArray so I get the following error: 这似乎是朝着正确方向迈出的一步,但getStrings()返回一个NSMutableArray因此我收到以下错误:

'NSArray' is not a subtype of 'NSMutableArray' 'NSArray'不是'NSMutableArray'的子类型

Is there any way to do what I am trying to do here? 有没有办法做我想在这里做的事情?

You can make this work with a double downcast, first to NSArray , then to [String] : 您可以使用双向下转换,首先使用NSArray ,然后使用[String]

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

Tested in a Playground with: 在游乐场测试:

import Foundation

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

Update: 更新:

In later versions of Swift (at least 1.2), the compiler will complain about as [String] . 在Swift的后续版本(至少1.2)中,编译器会抱怨as [String] Instead you should use an if let with a conditional downcast as? 相反,你应该使用if let with条件downcast as? :

import Foundation

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

If you are absolutely sure that your NSMutableArray can be cast to [String] , then you can use as! 如果您完全确定您的NSMutableArray可以NSMutableArray[String] ,那么您可以使用as! instead (but you probably shouldn't use this in most cases): 相反(但在大多数情况下你可能不应该使用它):

import Foundation

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

compactMap is your friend in Swift 4.1 and above, as well as in Swift 3.3-3.4 for that matter. compactMap是您在Swift 4.1及更高compactMap中的朋友,也是Swift 3.3-3.4中的朋友。 This means that you don't have any double or forced casting. 这意味着您没有任何双重或强制转换。

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

In previous versions of Swift, 2.0-3.2 and 4.0, you'll want to use flatMap for this purpose. 在以前版本的Swift,2.0-3.2和4.0中,您将需要使用flatMap来实现此目的。 The usage is the same as compactMap : 用法与compactMap相同:

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

With Swift 1.2 the following will work: 使用Swift 1.2,以下内容将起作用:

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

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

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

in Xcode 6.3 i used the following: 在Xcode 6.3中,我使用了以下内容:

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

for swift 3 对于斯威夫特3

you may consider the following code 您可以考虑以下代码

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

In my case compiler wanted me to write it like this to suppress all warnings and compilation problems, so not just that exclamation marks even if field imagesField is already declared with one, but also parentheses and "as!" 在我的情况下,编译器希望我这样编写它来抑制所有警告和编译问题,所以即使字段imagesField已经用一个声明,而且括号和“as!”,也不仅仅是感叹号。 to make it sure that nobody complains. 确保没有人抱怨。

(imagesField!.images as! [UIImage]) 🤮

It made me quite uncomfortable... Swift could be nicer, its new language so... I made extension: 这让我感到非常不舒服......斯威夫特可能更好,它的新语言如此...我做了扩展:

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

Assigned it to Array: 将其分配给Array:

extension Array: CSLang {
}

And now I can write the same statement like this with the same effect: 现在我可以用相同的效果编写相同的语句:

[UIImage].cast(imagesField.images)

Like it or not, this is my way, less question and exclamation marks, better. 喜欢与否,这是我的方式,更少的问题和感叹号,更好。 I made also unit test: 我做了单元测试:

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])
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 NSMutableArray强制转换为自定义类型的快速数组 - NSMutableArray cast to swift Array of custom type 如何在Swift中将[AnyObject]数组转换为[Hashable]或[AnyHashable]数组? - How can I cast an array of [AnyObject] to an array of [Hashable] or [AnyHashable] in Swift? 如何在 swift 中将不同的类型转换为缓冲区? - How to I cast a different type to a buffer in swift? UItableview无法将Swift._SwiftDeferredNSArray类型的值转换为NSMutableArray - UItableview Could not cast value of type Swift._SwiftDeferredNSArray to NSMutableArray 迅速。 SIGABRT:将类型&#39;__NSCFDictionary&#39;的值强制转换为&#39;NSMutableArray&#39; - Swift. SIGABRT: cast value of type '__NSCFDictionary' to 'NSMutableArray' 如何将数组强制转换为NSMutableArray以便能够使用removeObjectAtIndex - How to cast an array as NSMutableArray to be able to use removeObjectAtIndex 如何更改特定数组中的NSMutableArray - how to alter NSMutableArray in an specific array 如何检测特定NSMutableArray中的对象触摸? - How can I detect a touch of an object in a specific NSMutableArray? 如何快速获取多维数组中特定项目的计数 - How can I get the count of specific item in multidimensional array swift 无法转换类型为&#39;Swift._ContiguousArrayStorage的值 <Swift.AnyObject> &#39;至&#39;NSMutableArray&#39; - could not cast value of type 'Swift._ContiguousArrayStorage<Swift.AnyObject>' to 'NSMutableArray'
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM