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

Swift中不使用ReSwift实现跨页面状态更新监听的方法

Hey there! I see you're using ReSwift for cross-page state sync (where your second screen listens to actions from the first, updating its counter and language values), and you want to explore native/non-framework alternatives. Let's go through several solid approaches that work natively in Swift/iOS:

1. NotificationCenter (Observer Pattern)

This is the most straightforward iOS-native solution, perfect for simple event broadcasting across unrelated screens. It uses the observer pattern to send and receive state updates.

Implementation Steps:

First, define a custom notification name to avoid conflicts:

extension Notification.Name {
    static let appStateUpdated = Notification.Name("AppStateUpdated")
}

In your first view controller, trigger a notification with updated state data when the button is tapped:

@IBAction func updateButtonTapped(_ sender: UIButton) {
    // Example updated state values
    let updatedState = ["counter": 3, "language": "English"]
    NotificationCenter.default.post(
        name: .appStateUpdated,
        object: nil,
        userInfo: updatedState
    )
}

In your second view controller, register to listen for the notification and update the UI when it arrives:

override func viewDidLoad() {
    super.viewDidLoad()
    // Set initial state
    counterLabel.text = "2"
    languageLabel.text = "Chinese"

    // Register notification observer
    NotificationCenter.default.addObserver(
        self,
        selector: #selector(handleStateUpdate(_:)),
        name: .appStateUpdated,
        object: nil
    )
}

@objc private func handleStateUpdate(_ notification: Notification) {
    guard let userInfo = notification.userInfo,
          let counter = userInfo["counter"] as? Int,
          let language = userInfo["language"] as? String else { return }
    
    // Update UI with new state
    counterLabel.text = "\(counter)"
    languageLabel.text = language
}

// Always clean up observers to avoid memory leaks
deinit {
    NotificationCenter.default.removeObserver(self)
}

2. Combine Framework (Reactive, Type-Safe Sync)

If you're targeting iOS 13+, Apple's Combine framework offers a more elegant, type-safe alternative to NotificationCenter. It’s built for reactive state management without external dependencies.

Implementation Steps:

First, create an observable state object to hold your app's shared state:

import Combine

class AppState: ObservableObject {
    @Published var counter: Int = 2
    @Published var language: String = "Chinese"
}

Pass this state object to both view controllers (you can use environment objects in SwiftUI, or direct property injection for UIKit):

// Example in SceneDelegate/WindowSceneDelegate
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    let sharedState = AppState()
    
    let firstVC = FirstViewController()
    firstVC.appState = sharedState
    
    let secondVC = SecondViewController()
    secondVC.appState = sharedState
    
    // Set up navigation and window as usual
    let navController = UINavigationController(rootViewController: firstVC)
    window?.rootViewController = navController
    window?.makeKeyAndVisible()
}

In the first view controller, modify the shared state when the button is tapped:

class FirstViewController: UIViewController {
    var appState: AppState!
    
    @IBAction func updateButtonTapped(_ sender: UIButton) {
        appState.counter = 3
        appState.language = "English"
    }
}

In the second view controller, subscribe to state changes and update the UI automatically:

class SecondViewController: UIViewController {
    var appState: AppState!
    private var cancellables = Set<AnyCancellable>()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        updateUI()
        
        // Listen for counter changes
        appState.$counter
            .receive(on: DispatchQueue.main) // Ensure UI updates run on main thread
            .sink { [weak self] newCounter in
                self?.counterLabel.text = "\(newCounter)"
            }
            .store(in: &cancellables)
        
        // Listen for language changes
        appState.$language
            .receive(on: DispatchQueue.main)
            .sink { [weak self] newLanguage in
                self?.languageLabel.text = newLanguage
            }
            .store(in: &cancellables)
    }
    
    private func updateUI() {
        counterLabel.text = "\(appState.counter)"
        languageLabel.text = appState.language
    }
}

3. Singleton State Manager (Simple Shared State)

For small apps or straightforward state needs, a singleton-based state manager is lightweight and easy to implement. It centralizes state and notifies listeners when values change.

Implementation Steps:

Create a singleton manager with state properties and listener support:

class AppStateManager {
    static let shared = AppStateManager()
    private init() {} // Enforce singleton pattern
    
    var counter: Int = 2 {
        didSet { notifyListeners() }
    }
    var language: String = "Chinese" {
        didSet { notifyListeners() }
    }
    
    private var listeners: [UUID: () -> Void] = [:]
    
    func addListener(id: UUID, handler: @escaping () -> Void) {
        listeners[id] = handler
    }
    
    func removeListener(id: UUID) {
        listeners.removeValue(forKey: id)
    }
    
    private func notifyListeners() {
        listeners.values.forEach { $0() }
    }
}

In the first view controller, update the singleton state on button tap:

@IBAction func updateButtonTapped(_ sender: UIButton) {
    AppStateManager.shared.counter = 3
    AppStateManager.shared.language = "English"
}

In the second view controller, register a listener to update the UI when state changes:

class SecondViewController: UIViewController {
    private let listenerId = UUID()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        updateUI()
        
        // Register listener
        AppStateManager.shared.addListener(id: listenerId) { [weak self] in
            DispatchQueue.main.async {
                self?.updateUI()
            }
        }
    }
    
    private func updateUI() {
        counterLabel.text = "\(AppStateManager.shared.counter)"
        languageLabel.text = AppStateManager.shared.language
    }
    
    deinit {
        // Clean up listener to avoid memory leaks
        AppStateManager.shared.removeListener(id: listenerId)
    }
}

4. Delegate Pattern (One-to-One Communication)

If your screens have a direct parent-child relationship (e.g., first screen pushes/presents the second), the delegate pattern works well for targeted, one-to-one state updates.

Implementation Steps:

Define a delegate protocol for state updates:

protocol FirstViewControllerDelegate: AnyObject {
    func didUpdateState(counter: Int, language: String)
}

Add a delegate property to the first view controller:

class FirstViewController: UIViewController {
    weak var delegate: FirstViewControllerDelegate?
    
    @IBAction func updateButtonTapped(_ sender: UIButton) {
        delegate?.didUpdateState(counter: 3, language: "English")
    }
}

Implement the delegate in the second view controller:

class SecondViewController: UIViewController, FirstViewControllerDelegate {
    override func viewDidLoad() {
        super.viewDidLoad()
        // Set initial state
        counterLabel.text = "2"
        languageLabel.text = "Chinese"
    }
    
    func didUpdateState(counter: Int, language: String) {
        counterLabel.text = "\(counter)"
        languageLabel.text = language
    }
}

When presenting/pushing the second view controller from the first, set the delegate:

// In FirstViewController
@IBAction func openSecondVC(_ sender: UIButton) {
    let secondVC = SecondViewController()
    self.delegate = secondVC
    navigationController?.pushViewController(secondVC, animated: true)
}

Each approach has its sweet spot:

  • NotificationCenter: Great for simple, global event broadcasting
  • Combine: Best for reactive, type-safe state management (iOS 13+)
  • Singleton Manager: Lightweight option for small apps
  • Delegate: Ideal for direct, one-to-one screen communication

内容的提问来源于stack exchange,提问作者K.Wu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:54:46