Swift iOS中Optional<NSMutableArray>无下标问题及数组转模型咨询
Hey there! Let's fix your two key issues step by step:
1. Fixing "value of type 'Optional' has no subscripts" Error
The error pops up because dataArray is an Optional type (Optional<NSMutableArray>), and Swift blocks direct subscript access on optional values until you unwrap them. You need to safely unwrap the optional before accessing its elements.
Safe Unwrapping Options:
Option 1: Using if let (for in-line processing)
// Safely unwrap the optional array if let unwrappedDataArray = dataArray { // Now you can access elements with subscripts let firstElement = unwrappedDataArray[0] // Cast to Swift's native array type for easier handling (if it contains dictionaries) if let swiftArray = unwrappedDataArray as? [[String: Any]] { // Process the Swift array here } } else { // Handle empty/nil array case print("dataArray is nil - no data to process") }
Option 2: Using guard let (for early exit)
guard let unwrappedDataArray = dataArray else { print("dataArray is nil, exiting early") return } // Use the unwrapped array safely below let firstItem = unwrappedDataArray[0]
2. Parsing responseStr into [ShakeInfo] Array
The cleanest way to convert a JSON string to your ShakeInfo model array is using Swift's built-in Codable protocol. Here's how to implement it:
Step 1: Update Your ShakeInfo Model to Conform to Codable
Make your model class adopt Codable (it works seamlessly with NSObject subclasses):
import Foundation class ShakeInfo: NSObject, Codable { // Match these properties to your JSON keys exactly (use CodingKeys if names differ) var date: String? var shakeState: String? // Adjust type to match your actual data (e.g., Bool, Int) // Optional: Use CodingKeys if JSON uses different key names (e.g., snake_case) enum CodingKeys: String, CodingKey { case date case shakeState = "shake_state" // Example mapping for snake_case JSON } override init() { super.init() } }
Step 2: Decode the JSON String to [ShakeInfo]
Convert the string to Data, then use JSONDecoder to parse it into your model array:
// Convert response string to Data first guard let jsonData = responseStr.data(using: .utf8) else { print("Failed to convert response string to Data") return } do { // Decode the Data into an array of ShakeInfo objects let shakeInfoDetails = try JSONDecoder().decode([ShakeInfo].self, from: jsonData) // Now you can use shakeInfoDetails as your model array! print("Successfully parsed \(shakeInfoDetails.count) ShakeInfo items") } catch { // Handle decoding errors (print full error for debugging) print("Decoding failed: \(error.localizedDescription)") print("Full error details: \(error)") }
Alternative: Manual Conversion (No Codable Needed)
If you prefer manual parsing (e.g., if dataArray contains Objective-C dictionaries), loop through the unwrapped array and map each element to ShakeInfo:
if let unwrappedDataArray = dataArray as? [[String: Any]] { var shakeInfoDetails: [ShakeInfo] = [] for itemDict in unwrappedDataArray { let shakeInfo = ShakeInfo() shakeInfo.date = itemDict["date"] as? String shakeInfo.shakeState = itemDict["shakeState"] as? String // Adjust type casting based on your actual data type (e.g., as? Bool) shakeInfoDetails.append(shakeInfo) } // shakeInfoDetails now contains your converted objects }
内容的提问来源于stack exchange,提问作者Anand Gautam

