macOS Swift项目中如何全局共享选中的Patient对象?
Hey there! Let's tackle this global patient sharing problem for your macOS app. You’ve tried notifications, delegates, and segues without luck—so let’s look at two clean, straightforward approaches that fit your setup perfectly:
1. Singleton Pattern (Quickest Implementation)
Since you already have a ChosenPatient class, turning it into a singleton is the simplest way to ensure a single, globally accessible instance. This lets any view controller access the selected patient directly.
Step 1: Update the ChosenPatient Class
Modify your existing class to include a static shared instance, and add an optional notification trigger when the patient data changes:
class ChosenPatient: NSObject { // Global singleton instance—only one exists across the app static let shared = ChosenPatient() var data = Patient() { didSet { // Optional: Notify other VCs when the patient is updated NotificationCenter.default.post( name: NSNotification.Name(rawValue: "ChosenPatientDidUpdate"), object: nil ) } } // Keep your existing methods here // ... your existing methods ... }
Step 2: Use the Singleton in SearchViewController
When a user selects a patient in your table view, update the singleton’s data:
// Inside your SearchViewController's table view selection handler func tableView(_ tableView: NSTableView, didSelectRowAt row: Int) { let selectedPatient = // Get your selected Patient object from Realm/data source ChosenPatient.shared.data = selectedPatient // Call updateLabels if needed for this VC updateLabels() }
Step 3: Access the Patient in DetailViewController
In your DetailViewController’s updateLabels() method, directly fetch the singleton’s data. If you want to auto-update when the patient changes, add a notification observer:
override func viewDidLoad() { super.viewDidLoad() // Listen for patient updates to refresh labels automatically NotificationCenter.default.addObserver( self, selector: #selector(updateLabels), name: NSNotification.Name(rawValue: "ChosenPatientDidUpdate"), object: nil ) } @objc func updateLabels() { let currentPatient = ChosenPatient.shared.data // Update your labels here, e.g.: nameLabel.stringValue = currentPatient.name // ... other label updates ... } // Clean up the observer when the VC is deallocated deinit { NotificationCenter.default.removeObserver(self) }
2. Dependency Injection (More Flexible & Testable)
If you prefer a more decoupled approach (great for long-term maintainability), use your root TabViewController to hold the ChosenPatient instance and pass it to both child view controllers.
Step 1: Add a Property to TabViewController
class TabViewController: NSTabViewController { // Hold the single ChosenPatient instance let sharedChosenPatient = ChosenPatient() override func viewDidLoad() { super.viewDidLoad() // Pass the instance to both child VCs when the tab view loads passSharedPatientToChildren() } private func passSharedPatientToChildren() { if let searchVC = viewControllers?[0] as? SearchViewController { searchVC.chosenPatient = sharedChosenPatient } if let detailVC = viewControllers?[1] as? DetailViewController { detailVC.chosenPatient = sharedChosenPatient } } }
Step 2: Add a Property to Child View Controllers
In both SearchViewController and DetailViewController, add a reference to ChosenPatient:
// In SearchViewController class SearchViewController: NSViewController { var chosenPatient: ChosenPatient! // When selecting a patient: func tableView(_ tableView: NSTableView, didSelectRowAt row: Int) { let selectedPatient = // Get selected Patient chosenPatient.data = selectedPatient updateLabels() } } // In DetailViewController class DetailViewController: NSViewController { var chosenPatient: ChosenPatient! @objc func updateLabels() { let currentPatient = chosenPatient.data // Update labels here } }
Which Approach Should You Choose?
- Singleton: Go with this if you want the fastest, simplest implementation. It’s perfect for small to medium apps where you don’t anticipate needing multiple "selected patient" instances.
- Dependency Injection: Choose this if you want more control, easier testing, or plan to expand your app’s architecture later. It keeps your code loosely coupled and avoids the "global state" pitfalls of singletons.
Both approaches will let you access the same Patient object across any view controller in your app—pick the one that best fits your workflow!
内容的提问来源于stack exchange,提问作者AlbertUI

