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

iOS开发:如何实现UIView与UIViewController间的数据展示与传递?

Implementation Solution for Data Display and Communication Between MYView and listViewController

Let's break this down into two key parts: ensuring your custom MYView correctly displays data, and setting up a reliable way to pass data back from MYView to listViewController.


1. Ensure Data is Displayed Correctly in MYView

First, let's confirm your existing setup works smoothly and add any missing pieces:

Step 1: Verify Connections

Make sure:

  • Your MYView is properly added to listViewController's nib/storyboard, and the name label outlet is connected.
  • The chef outlet in listViewController is linked to the MYView instance in the interface.

Step 2: Pass Data from ViewController to MYView

In your listViewController, when you have data ready (e.g., from listViewModel), call the setlisttabData method to update the view:

class listViewController: UIViewController {
    @IBOutlet var chef: MYView!
    private var listViewModel: ListViewModel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Assume your view model fetches or provides the chef data
        if let chefData = listViewModel.fetchChefData() {
            chef.setlisttabData(chefs: chefData)
        }
    }
}

2. Pass Data from MYView to listViewController

The most common and maintainable approaches are using the delegate pattern (recommended for reusable components) or closures (simpler for one-off interactions).

This is ideal if you plan to reuse MYView across multiple view controllers.

Step 1: Define a Delegate Protocol in MYView

Add a protocol to MYView that defines the method for passing data:

import UIKit

// Define delegate protocol
protocol MYViewDelegate: AnyObject {
    func myView(_ view: MYView, didSendChefData chef: listModel)
}

class MYView: UIView {
    @IBOutlet weak var name: UILabel!
    weak var delegate: MYViewDelegate? // Weak to avoid retain cycles
    private var currentChef: listModel? // Store the current data
    
    override func awakeFromNib() {
        super.awakeFromNib()
        // Optional: Add a tap gesture to trigger data pass (adjust based on your UI)
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(onViewTapped))
        addGestureRecognizer(tapGesture)
        isUserInteractionEnabled = true
    }
    
    func setlisttabData(chefs: listModel) {
        self.currentChef = chefs
        self.name.text = chefs.name
    }
    
    @objc private func onViewTapped() {
        // Trigger delegate method when the view is interacted with
        guard let chef = currentChef else { return }
        delegate?.myView(self, didSendChefData: chef)
    }
}

Step 2: Conform listViewController to the Delegate

Update your view controller to implement the delegate method and set the delegate:

class listViewController: UIViewController, MYViewDelegate {
    @IBOutlet var chef: MYView!
    private var listViewModel: ListViewModel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        chef.delegate = self // Set the delegate
        
        // Pass initial data to MYView
        if let chefData = listViewModel.fetchChefData() {
            chef.setlisttabData(chefs: chefData)
        }
    }
    
    // Implement delegate method to receive data
    func myView(_ view: MYView, didSendChefData chef: listModel) {
        // Handle the received data here
        print("Received chef data: \(chef.name)")
        // Example actions: Navigate to detail screen, update view model, etc.
    }
}

Option 2: Closure-Based Approach

If you only need this interaction for this specific view controller, closures are a simpler alternative:

Step 1: Add a Closure Property to MYView

class MYView: UIView {
    @IBOutlet weak var name: UILabel!
    var onChefDataSent: ((listModel) -> Void)?
    private var currentChef: listModel?
    
    override func awakeFromNib() {
        super.awakeFromNib()
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(onViewTapped))
        addGestureRecognizer(tapGesture)
        isUserInteractionEnabled = true
    }
    
    func setlisttabData(chefs: listModel) {
        self.currentChef = chefs
        self.name.text = chefs.name
    }
    
    @objc private func onViewTapped() {
        guard let chef = currentChef else { return }
        onChefDataSent?(chef)
    }
}

Step 2: Assign the Closure in listViewController

class listViewController: UIViewController {
    @IBOutlet var chef: MYView!
    private var listViewModel: ListViewModel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Assign the closure to handle data
        chef.onChefDataSent = { [weak self] selectedChef in
            guard let self = self else { return }
            print("Received chef via closure: \(selectedChef.name)")
            // Handle the data as needed
        }
        
        // Pass initial data to MYView
        if let chefData = listViewModel.fetchChefData() {
            chef.setlisttabData(chefs: chefData)
        }
    }
}

Key Notes

  • Always use weak for delegate properties and [weak self] in closures to prevent retain cycles.
  • Adjust the trigger for data pass (e.g., button tap instead of view tap) based on your UI requirements.
  • Ensure your listModel class is properly defined with the name property (and any other data you need to pass).

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 07:58:09