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

在Xcode Swift4中实现多ViewController共享自定义模型实例

Hey there! Since you're a Swift newbie working on a code-only project (no Storyboards, all VC setup in AppDelegate), let's figure out how to get your three child VCs sharing and reacting to changes in that custom model instance from your main VC. Here are the best approaches to try, plus some search keywords to dig deeper:

This is the cleanest, most maintainable way to share your model. The idea is simple: your main VC creates the custom model instance, then passes it directly to each child VC when initializing them.

To make the child VCs react to changes in the model, you can use Combine's @Published property wrapper (iOS 13+)—it’s way more straightforward than NotificationCenter for this use case. Here’s how it works:

// First, update your CustomModel to use Combine
import Combine

class CustomModel {
    // Mark variables you want to observe with @Published
    @Published var userName: String = ""
    @Published var score: Int = 0
}

// In a child VC, accept the shared model and subscribe to changes
class ChildVC1: UIViewController {
    // Hold a reference to the shared model (force-unwrap is safe here since we'll set it before VC loads)
    var sharedModel: CustomModel!
    private var cancellables = Set<AnyCancellable>()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Subscribe to changes in userName
        sharedModel.$userName
            .sink { [weak self] newName in
                // Update your UI or run logic when the value changes
                self?.nameLabel.text = newName
            }
            .store(in: &cancellables)
        
        // Do the same for score or other variables
        sharedModel.$score
            .sink { [weak self] newScore in
                self?.scoreLabel.text = "Score: \(newScore)"
            }
            .store(in: &cancellables)
    }
    
    // When you need to update the model from the child VC
    func updateUserName(_ newName: String) {
        sharedModel.userName = newName
    }
}

// In your main VC, create the model and pass it to each child
class MainVC: UIViewController {
    let customModel = CustomModel()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Initialize each child VC and inject the model
        let child1 = ChildVC1()
        child1.sharedModel = customModel
        // Add child1 to your container view hierarchy...
        
        let child2 = ChildVC2()
        child2.sharedModel = customModel
        // Add child2 to your container...
        
        let child3 = ChildVC3()
        child3.sharedModel = customModel
        // Add child3 to your container...
    }
}
2. NotificationCenter (Your Initial Idea)

If you’re targeting iOS versions before 13, or just prefer a more traditional approach, NotificationCenter works too. You’ll post a notification whenever the model’s variables change, and each child VC listens for that notification.

// Update your CustomModel to post notifications on change
class CustomModel {
    var userName: String = "" {
        didSet {
            // Send a notification with the new value
            NotificationCenter.default.post(
                name: NSNotification.Name(rawValue: "CustomModelUserNameChanged"),
                object: self,
                userInfo: ["newUserName": userName]
            )
        }
    }
}

// In a child VC, listen for the notification
class ChildVC1: UIViewController {
    var sharedModel: CustomModel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Register to listen for the notification
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(userNameChanged(_:)),
            name: NSNotification.Name(rawValue: "CustomModelUserNameChanged"),
            object: sharedModel
        )
    }
    
    @objc func userNameChanged(_ notification: Notification) {
        // Extract the new value from the notification
        if let newName = notification.userInfo?["newUserName"] as? String {
            nameLabel.text = newName
        }
    }
    
    // Don't forget to remove the observer when the VC is deinitialized
    deinit {
        NotificationCenter.default.removeObserver(self)
    }
}

// Again, pass the shared model from MainVC to each child like in the first example
3. Singleton Pattern (Use Sparingly)

If you don’t want to pass the model around every time, you can make your CustomModel a singleton—this creates one global instance that all VCs can access directly. Just be careful: singletons stay in memory for the app’s entire lifecycle, which can lead to unexpected issues (like retaining unused objects) and make testing harder.

class CustomModel {
    // Singleton instance
    static let shared = CustomModel()
    // Private initializer to prevent creating other instances
    private init() {}
    
    var userName: String = "" {
        didSet {
            // Use Combine or NotificationCenter here to notify changes, same as before
        }
    }
}

// In any child VC, access the model directly
class ChildVC1: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Read the model's value
        nameLabel.text = CustomModel.shared.userName
        
        // Update the model's value
        CustomModel.shared.userName = "New Name"
    }
}

Search Keywords to Explore More

If you want to dive deeper into these concepts, search for:

  • Swift dependency injection view controllers
  • Swift shared model between view controllers
  • Combine @Published view controller communication
  • NotificationCenter Swift pass data between view controllers
  • Code-only Swift view controller data sharing

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:33:02