You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS Swift请求获取数组响应报错:__NSArrayI无法转为NSDictionary求助

Fixing "__NSArrayI to NSDictionary" Cast Error in Swift iOS Requests

Hey there! That error pops up because you’re trying to force-cast a JSON array into a dictionary—and since those are totally different types, the app crashes. Let’s break down how to fix this properly, with safe handling for both array and dictionary responses.

First: Understand the Root Cause

Chances are you’ve got code somewhere that looks like this:

// ❌ Bad: Force-casting without checking type
let responseDict = try JSONSerialization.jsonObject(with: data) as! [String: Any]

When the API returns an array instead of a dictionary, Swift can’t make that cast, hence the __NSArrayI (Objective-C’s immutable array) to NSDictionary error.

Solution 1: Check JSON Type Before Casting

Use a switch statement or optional binding to safely check whether the parsed JSON is an array or dictionary, then handle each case separately. Here’s how to implement this in a URLSession request:

URLSession.shared.dataTask(with: yourRequestURL) { data, response, error in
    guard let data = data, error == nil else {
        print("Request failed: \(error?.localizedDescription ?? "Unknown error")")
        return
    }

    do {
        // Parse JSON into a generic Any type first
        let jsonResponse = try JSONSerialization.jsonObject(with: data, options: [])

        // Check what type we're dealing with
        switch jsonResponse {
        case let dict as [String: Any]:
            // Handle dictionary response here
            print("Received dictionary: \(dict)")
            // Your existing dictionary logic goes here
        case let array as [Any]:
            // Handle array response here
            print("Received array: \(array)")
            // Add logic to process the array
        default:
            print("JSON is neither an array nor dictionary")
        }
    } catch {
        print("JSON parsing failed: \(error.localizedDescription)")
    }
}.resume()

This way, you never force-cast blindly—you handle each possible response type explicitly.

For a cleaner, more maintainable approach, use Swift’s Codable protocol to define models for your responses. This avoids manual type casting entirely and makes your code safer.

Let’s say your API might return either a single User object (dictionary) or an array of User objects. First define the User model:

struct User: Codable {
    let id: Int
    let name: String
    let email: String
    // Add other properties matching your API response
}

Then, in your request completion, try parsing into both possible types:

do {
    // First try parsing as a single User (dictionary)
    if let singleUser = try? JSONDecoder().decode(User.self, from: data) {
        print("Got single user: \(singleUser.name)")
        // Handle single user logic
    } 
    // If that fails, try parsing as an array of Users
    else if let userArray = try? JSONDecoder().decode([User].self, from: data) {
        print("Got \(userArray.count) users")
        // Handle array of users logic
    } else {
        print("Response doesn't match expected User or [User] type")
    }
}

Codable takes care of all the type checking under the hood, and your code becomes much easier to read and extend.

Key Takeaway

Never use as! for JSON type casting unless you’re 100% certain the response type will never change. Always use optional casting (as?) or explicit type checks to handle different response formats safely.

内容的提问来源于stack exchange,提问作者reza_khalafi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 07:31:24