Swift3中Alamofire解析数据至TableView无显示问题求助
Hey there! Let's break down why your UITableView is empty and fix the issues in your code step by step:
1. Broken Alamofire Request Structure
Your current request code has messed-up syntax (commented-out lines mixed with active code) which means the network call isn't even being sent correctly. We'll fix that first.
2. Incorrect JSON Parsing Logic
The Nestoria API response has a specific nested structure: the listings array you need lives inside the response dictionary at the root of the JSON. Your original code tried to iterate over the root dictionary's count, which doesn't match the actual data structure.
3. Wrong Image Field Name
You're using imageUrl to fetch the image, but the API uses img_url as the key. That's why you weren't getting image data, and parsing errors likely prevented other fields from loading too.
4. Missing Main Thread for TableView Refresh
Network calls run on a background thread, so you need to reload the UITableView on the main thread to ensure the UI updates properly.
5. Optional Value Safety & TableView Setup
- Always safely unwrap values from UserDefaults to avoid crashes if the keys don't exist.
- Make sure your UITableView's
dataSourceanddelegateare set (either in code or via Storyboard connections).
Fixed PropertySearchViewController Code
class PropertySearchViewController: UIViewController, UITableViewDataSource, UITableViewDelegate { let URL_Get_Data = "https://api.nestoria.co.uk/api?" @IBOutlet weak var tableViewProperty: UITableView! var properties = [Property]() public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{ return properties.count } public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! PropertyTableViewCell let property = properties[indexPath.row] // Fallback text if fields are nil cell.propertyTitle.text = property.title ?? "No Title" cell.propertyPrice.text = property.price ?? "No Price" if let imageUrl = property.imageUrl { Alamofire.request(imageUrl).responseImage { response in debugPrint(response) // Update UI on main thread DispatchQueue.main.async { if let image = response.result.value { cell.propertyImage.image = image } else { print("No image loaded") cell.propertyImage.image = UIImage(named: "placeholder") // Optional: add a placeholder image } } } } else { cell.propertyImage.image = UIImage(named: "placeholder") // Optional placeholder for missing images } return cell } override func viewDidLoad() { super.viewDidLoad() // Set tableView delegate/data source (if not connected in Storyboard) tableViewProperty.dataSource = self tableViewProperty.delegate = self // Safely retrieve saved values from UserDefaults guard let city = UserDefaults.standard.string(forKey: "city"), let type = UserDefaults.standard.string(forKey: "typeP") else { print("City or property type not found in UserDefaults") return } print("Search values are:", city, type) let params: [String: String] = [ "encoding": "json", "pretty": "1", "action": "search_listings", "country": "uk", "listing_type": type, "place_name": city ] // Correct Alamofire request with proper parsing Alamofire.request(URL_Get_Data, method: .get, parameters: params, encoding: URLEncoding.default) .validate(statusCode: 200..<600) .responseJSON { response in switch response.result { case .success(let json): // Parse JSON according to Nestoria's structure guard let rootDict = json as? [String: Any], let responseDict = rootDict["response"] as? [String: Any], let listingsArray = responseDict["listings"] as? [[String: Any]] else { print("Failed to parse JSON structure") return } // Clear old data before adding new listings self.properties.removeAll() for listing in listingsArray { let title = listing["title"] as? String let price = listing["price_formatted"] as? String let imageUrl = listing["img_url"] as? String // Fixed field name self.properties.append(Property(title: title, price: price, imageUrl: imageUrl)) } // Reload tableView on main thread DispatchQueue.main.async { self.tableViewProperty.reloadData() } case .failure(let error): print("Network request failed:", error.localizedDescription) } } } }
Additional Tips
- Cell Reuse: For better async image handling (to avoid wrong images showing in reused cells), consider using a library like Kingfisher instead of manual Alamofire image requests—it handles cell reuse and caching automatically.
- Placeholder Images: Add a placeholder image to your asset catalog to fill empty image views when no image is available, making your UI look more polished.
- Error Logging: The added error handling will help you debug issues like missing UserDefaults values or network failures quickly.
内容的提问来源于stack exchange,提问作者ema so

