简体   繁体   English

无法实例化函数无法转换类型为'__NSArrayI'的值

[英]Cannot instantiate function Could not cast value of type '__NSArrayI'

I have made the following function in Swift 3: 我在Swift 3中做了以下功能:

    func parseJSON() {
    var JsonResult: NSMutableArray = NSMutableArray()

    do {
        JsonResult = try JSONSerialization.jsonObject(with: self.data as Data, options:JSONSerialization.ReadingOptions.allowFragments) as! NSMutableArray
    } catch let error as NSError {
        print(error)
    }
    var jsonElement:NSDictionary=NSDictionary()
    let locations: NSMutableArray = NSMutableArray()

    for i in 0 ..< JsonResult.count
    {
        jsonElement = JsonResult[i] as! NSDictionary
        let location = Parsexml()

        if let title = jsonElement["Title"] as? String,
            let body = jsonElement["Body"] as? String,
            let userId = jsonElement["UserId"] as? Int,
            let Id = jsonElement["Id"] as? Int
        {

            location.title = title
            location.body = body
            location.userId = userId
            location.id = Id

        }

        locations.add(location)
    }
    DispatchQueue.main.async { () -> Void in

        self.delegate.itemsDownloaded(items: locations)

    }

When i call this function from another method, i get the following error: 当我从另一种方法调用此函数时,出现以下错误:

Could not cast value of type '__NSArrayI' (0x105d4fc08) to 'NSMutableArray' (0x105d4fcd0). 无法将类型'__NSArrayI'(0x105d4fc08)的值强制转换为'NSMutableArray'(0x105d4fcd0)。

It points me towards the element here: 它指向这里的元素:

  JsonResult = try JSONSerialization.jsonObject(with: self.data as Data, options:JSONSerialization.ReadingOptions.allowFragments) as! NSMutableArray

Where it exits with a SIGBRT.. 它以SIGBRT退出的位置。

What have i missed here? 我在这里错过了什么?

You are trying to convert an NSArray into an NSMutable array which is what the warning is complaining about. 您正在尝试将NSArray转换为NSMutable数组,这是警告所抱怨的内容。

Take the array it provides you, and then convert it into a mutable one. 使用它提供的数组,然后将其转换为可变数组。

let jsonArray = try JSONSerialization.jsonObject(with: self.data as Data, options:JSONSerialization.ReadingOptions.allowFragments) as! NSArray
jsonResult = jsonArray.mutableCopy() as! NSMutableArray

Unrelated, but you may also want to user a lower case value for the JsonResult to fit with normal iOS style guidelines. 无关,但您可能还想为JsonResult使用小写字母值以符合常规的iOS样式准则。 It should instead be jsonResult. 它应该改为jsonResult。

Another way to improve your code: 改进代码的另一种方法:

You are not mutating your JsonResult , so you have no need to declare it as NSMutableArray : 您无需JsonResult ,因此无需将其声明为NSMutableArray

    var JsonResult = NSArray()

    do {
        JsonResult = try JSONSerialization.jsonObject(with: self.data as Data, options:JSONSerialization.ReadingOptions.allowFragments) as! NSArray
    } catch let error as NSError {
        print(error)
    }

And some steps to improve your code... 以及一些改善代码的步骤...

enum MyError: Error {
    case NotArrayOfDict
}
func parseJSON() {
    do {
        guard let jsonResult = try JSONSerialization.jsonObject(with: self.data as Data) as? [[String: Any]] else {
            throw MyError.NotArrayOfDict
        }
        let locations: NSMutableArray = NSMutableArray()

        for jsonElement in jsonResult {
            let location = Parsexml()

            if let title = jsonElement["Title"] as? String,
                let body = jsonElement["Body"] as? String,
                let userId = jsonElement["UserId"] as? Int,
                let Id = jsonElement["Id"] as? Int
            {
                location.title = title
                location.body = body
                location.userId = userId
                location.id = Id

            }

            locations.add(location)
        }
        DispatchQueue.main.async { () -> Void in
            self.delegate.itemsDownloaded(items: locations)
        }
    } catch let error {
        print(error)
    }
}
  • as! casting sometimes crashes your app, use it only when you are 100%-sure that the result is safely converted to the type. 强制转换有时会使您的应用程序崩溃,仅当您100%确保将结果安全地转换为类型时才使用它。 If you are not, using guard-let with as? 如果不是,请使用as? guard-let as? is safer. 更安全。

  • Use Swift types rather than NSSomething as far as you can. 尽可能使用Swift类型而不是NSSomething

  • Specifying .allowFragments is not needed, as you expect the result as an Array. 不需要指定.allowFragments ,因为您期望结果为数组。


And if you can modify some other parts of your code, you can write your code as: 而且,如果您可以修改代码的其他部分,则可以将代码编写为:

func parseJSON() {
    do {
        //If `self.data` was declared as `Data`, you would have no need to use `as Data`.
        guard let jsonResult = try JSONSerialization.jsonObject(with: self.data) as? [[String: Any]] else {
            throw MyError.NotArrayOfDict
        }
        var locations: [Parsexml] = [] //<-Use Swift Array

        for jsonElement in jsonResult {
            let location = Parsexml()

            if let title = jsonElement["Title"] as? String,
                let body = jsonElement["Body"] as? String,
                let userId = jsonElement["UserId"] as? Int,
                let Id = jsonElement["Id"] as? Int
            {

                location.title = title
                location.body = body
                location.userId = userId
                location.id = Id

            }

            locations.append(location)
        }
        DispatchQueue.main.async { () -> Void in
            self.delegate.itemsDownloaded(items: locations)
        }
    } catch let error {
        print(error)
    }
}

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM