Swift3中如何排序JSON数据并加载至UITableView?加载失败求助
Hey there! Let's work through your problem step by step—loading JSON into a UITableView and sorting that data in Swift 3 can trip you up if you're missing a few key pieces, so let's break it down clearly.
Step 1: Create Data Models for Your JSON Structure
Your JSON has nested objects (like address and company), so we'll make model classes to store this parsed data properly. Swift 3 doesn't have Codable (that came in Swift 4+), so we'll use dictionary-to-model initialization:
// Nested Address model class Address: NSObject { var street: String? var suite: String? var city: String? var zipcode: String? init(dictionary: [String: Any]) { self.street = dictionary["street"] as? String self.suite = dictionary["suite"] as? String self.city = dictionary["city"] as? String self.zipcode = dictionary["zipcode"] as? String // Add lat/lng properties here if you need the geo data } } // Nested Company model class Company: NSObject { var name: String? var catchPhrase: String? init(dictionary: [String: Any]) { self.name = dictionary["name"] as? String self.catchPhrase = dictionary["catchPhrase"] as? String } } // Main User model class User: NSObject { var id: Int? var name: String? var username: String? var email: String? var address: Address? var phone: String? var website: String? var company: Company? init(dictionary: [String: Any]) { self.id = dictionary["id"] as? Int self.name = dictionary["name"] as? String self.username = dictionary["username"] as? String self.email = dictionary["email"] as? String // Parse nested address object if let addressDict = dictionary["address"] as? [String: Any] { self.address = Address(dictionary: addressDict) } // Parse nested company object if let companyDict = dictionary["company"] as? [String: Any] { self.company = Company(dictionary: companyDict) } self.phone = dictionary["phone"] as? String self.website = dictionary["website"] as? String } }
Step 2: Parse JSON into a User Array
Next, we'll take your JSON data (whether from a local file or API) and convert it into an array of User objects.
For Local JSON Files:
var usersArray: [User] = [] @IBOutlet weak var tableView: UITableView! func loadLocalJSON() { // Locate the JSON file in your app bundle guard let jsonPath = Bundle.main.path(forResource: "users", ofType: "json") else { print("Error: JSON file not found in bundle") return } do { let jsonData = try Data(contentsOf: URL(fileURLWithPath: jsonPath)) // Convert data to JSON array guard let jsonArray = try JSONSerialization.jsonObject(with: jsonData, options: .allowFragments) as? [[String: Any]] else { print("Error: JSON is not a valid array") return } // Map JSON array to User objects usersArray = jsonArray.map { User(dictionary: $0) } // Refresh the table view tableView.reloadData() } catch let error { print("Parsing error: \(error.localizedDescription)") } }
For API-Fetched JSON:
func fetchUsersFromAPI() { guard let apiURL = URL(string: "https://your-api-endpoint-here.com/users") else { print("Error: Invalid API URL") return } URLSession.shared.dataTask(with: apiURL) { [weak self] data, response, error in guard let data = data, error == nil else { print("Fetch error: \(error?.localizedDescription ?? "Unknown error")") return } do { guard let jsonArray = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [[String: Any]] else { print("Error: API response is not a valid array") return } // Map to User array and refresh table on main thread self?.usersArray = jsonArray.map { User(dictionary: $0) } DispatchQueue.main.async { self?.tableView.reloadData() } } catch let error { print("Parsing error: \(error.localizedDescription)") } }.resume() }
Step 3: Connect to UITableView Data Source
Make sure your view controller conforms to UITableViewDataSource and implement the required methods. Don't forget to set the table view's data source (via Storyboard outlets or code):
override func viewDidLoad() { super.viewDidLoad() tableView.dataSource = self // Call your JSON loading function here loadLocalJSON() // OR fetchUsersFromAPI() } // MARK: - UITableView Data Source func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return usersArray.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { // Use your cell reuse identifier (set this in Storyboard first!) let cell = tableView.dequeueReusableCell(withIdentifier: "UserCell", for: indexPath) let currentUser = usersArray[indexPath.row] // Populate cell with user data cell.textLabel?.text = currentUser.name cell.detailTextLabel?.text = currentUser.email // Example: Show nested address data (city) if let userCity = currentUser.address?.city { cell.detailTextLabel?.text = "\(currentUser.email ?? "") | \(userCity)" } return cell }
Step 4: Sort the User Array
To sort your data, add a sort call right after parsing the JSON. Here are common sorting options:
Sort by Name (Ascending):
usersArray.sort { guard let name1 = $0.name, let name2 = $1.name else { return false } return name1 < name2 }
Sort by ID (Descending):
usersArray.sort { guard let id1 = $0.id, let id2 = $1.id else { return false } return id1 > id2 }
Add this sort code right before reloading the table view. For example, in loadLocalJSON():
// After mapping to User array usersArray = jsonArray.map { User(dictionary: $0) } // Sort here usersArray.sort { guard let name1 = $0.name, let name2 = $1.name else { return false } return name1 < name2 } tableView.reloadData()
Quick Troubleshooting Tips
- Double-check your JSON format: The sample JSON you provided is missing a closing
}at the end—make sure your actual JSON is valid. - Ensure your table view's data source is connected (either via Storyboard or
tableView.dataSource = self). - Always refresh the table view on the main thread (critical for API-fetched data).
- Verify your cell reuse identifier matches what's in your code and Storyboard.
内容的提问来源于stack exchange,提问作者Ankit Kumawat

