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

iOS开发:读取Plist数组元素并传值至ViewController展示菜品信息

Solution for Passing Restaurant Menu Data to Table View

Hey there! Let's fix this step by step to get your restaurant menu data showing up correctly in the RestaurantViewController when a collection view cell is tapped.

First, Let's Clean Up Data Handling with Models

Instead of relying on NSMutableArray (which is Objective-C-era code), let's define Swift structs to model your data. This makes it way easier to work with and avoids messy dictionary access.

// Define a model for individual menu items
struct MenuItem {
    let name: String
    let price: String // Use Double instead if your plist stores numeric prices
}

// Define a model for restaurants
struct Restaurant {
    let name: String
    let menuItems: [MenuItem]
}

Next, Load and Parse the Plist Properly

Load your plist once (not every time a cell is tapped!) and convert it into our [Restaurant] array. Add this method to your collection view controller:

private func loadRestaurants() -> [Restaurant] {
    // Get the plist path safely
    guard let plistPath = Bundle.main.path(forResource: "ResturantFile", ofType: "plist"),
          // Load raw data as an array of dictionaries
          let rawRestaurantData = NSArray(contentsOfFile: plistPath) as? [[String: Any]] else {
        print("Failed to load or parse the RestaurantFile.plist")
        return []
    }
    
    var restaurants = [Restaurant]()
    
    for rawRestaurant in rawRestaurantData {
        // Extract the restaurant name (the only key in each dictionary)
        guard let restaurantName = rawRestaurant.keys.first,
              // Extract the menu items array for this restaurant
              let rawMenuItems = rawRestaurant[restaurantName] as? [[String: String]] else {
            continue // Skip invalid entries
        }
        
        // Convert raw menu items to our MenuItem model
        let menuItems = rawMenuItems.compactMap { itemDict in
            guard let itemName = itemDict["itemName"],
                  let itemPrice = itemDict["ItemPrice"] else {
                return nil // Skip items missing name/price
            }
            return MenuItem(name: itemName, price: itemPrice)
        }
        
        restaurants.append(Restaurant(name: restaurantName, menuItems: menuItems))
    }
    
    return restaurants
}

Then load this array in viewDidLoad so it's ready to use:

var restaurants: [Restaurant] = []
var restaurantImageArray: [UIImage] = [] // Your existing image array

override func viewDidLoad() {
    super.viewDidLoad()
    restaurants = loadRestaurants()
    // Other setup code for your collection view
}

Fix the didSelectItemAt Method

Your original code had a broken sorting line and was reloading the plist every tap. Let's replace it with logic that grabs the selected restaurant's data and passes it to RestaurantViewController:

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    // Get the selected restaurant from our preloaded array
    let selectedRestaurant = restaurants[indexPath.row]
    let selectedImage = restaurantImageArray[indexPath.row]
    
    // Option 1: Use your existing closure to pass data
    blockClosure?(selectedImage, selectedRestaurant.name, selectedRestaurant.menuItems)
    
    // Option 2: If you're using navigation to push the VC directly (instead of closure)
    let restaurantVC = RestaurantViewController()
    restaurantVC.restaurantImage = selectedImage
    restaurantVC.restaurantName = selectedRestaurant.name
    restaurantVC.menuItems = selectedRestaurant.menuItems
    navigationController?.pushViewController(restaurantVC, animated: true)
}

Set Up RestaurantViewController to Display the Data

Update your RestaurantViewController to accept the data and populate the table view:

class RestaurantViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
    // Properties to receive data
    var restaurantImage: UIImage?
    var restaurantName: String?
    var menuItems: [MenuItem] = []
    
    @IBOutlet weak var tableView: UITableView!
    @IBOutlet weak var restaurantImageView: UIImageView!
    @IBOutlet weak var restaurantNameLabel: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Configure table view
        tableView.dataSource = self
        tableView.delegate = self
        
        // Set up UI with received data
        restaurantImageView.image = restaurantImage
        restaurantNameLabel.text = restaurantName
        title = restaurantName
    }
    
    // MARK: - UITableView Data Source
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return menuItems.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "MenuItemCell", for: indexPath)
        let item = menuItems[indexPath.row]
        
        // Configure cell labels (adjust based on your cell's structure)
        cell.textLabel?.text = item.name
        cell.detailTextLabel?.text = item.price
        
        return cell
    }
}

Key Fixes from Your Original Code

  • No more repeated plist loads: We load the data once in viewDidLoad instead of every time a cell is tapped.
  • Broken sorting logic removed: Your original sorted(by: {$0 == "ItemName"}) was incorrect because it tried to compare array elements to a string instead of sorting menu items properly (our model handles this cleanly).
  • Type-safe data passing: Using structs ensures we're passing valid, typed data instead of ambiguous Any objects.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 06:35:35