首先看看GIF:
第二页正在收听第一页上的操作。首先,第二页有状态:counter = 2
和language = Chinese
。但是当在第一页上按下按钮时,第二页的状态会更新。
我正在使用名为ReSwift
的模块,如果您熟悉redux
,则它是redux
的Swift版本。但是,我想知道如何在不使用此模块的情况下完成此操作。 (我不会问如何确切地了解GIF中发生的事情,但总的来说listen to updates/events on another page
因此,我希望没有" hacky"解决方案)。
如果您对ReSwift
方式感兴趣,请参阅以下代码
以下内容与此问题无关
Language.swift:
enum Language {
case English
case Chinese
}
LanguageState.swift:
import ReSwift
struct LanguageState: StateType {
var language: Language = .English
}
CounterState.swift:
import ReSwift
struct CounterState: StateType {
var counter: Int = 0
}
AppState.swift:
import ReSwift
struct AppState: StateType {
var counterState: CounterState = CounterState()
var languageState: LanguageState = LanguageState()
}
Actions.swift:
import ReSwift
struct CounterActionIncrease: Action {}
struct CounterActionDecrease: Action {}
struct ChangeLanguageToEnglish: Action {}
struct ChangeLanguageToChinese: Action {}
LanguageReducer.swift:
import ReSwift
func LanguageReducer(action: Action, state: LanguageState?) -> LanguageState {
var state = state ?? LanguageState()
switch action {
case _ as ChangeLanguageToEnglish:
state.language = .English
case _ as ChangeLanguageToChinese:
state.language = .Chinese
default:
break
}
return state
}
CounterReducer.swift:
import ReSwift
func CounterReducer(action: Action, state: CounterState?) -> CounterState {
var state = state ?? CounterState()
switch action {
case _ as CounterActionIncrease:
state.counter += 1
case _ as CounterActionDecrease:
state.counter -= 1
default:
break
}
return state
}
AppReducer.swift:
import ReSwift
func AppReducer(action: Action, state: AppState?) -> AppState {
return AppState(
counterState: CounterReducer(action: action, state: state?.counterState),
languageState: LanguageReducer(action: action, state: state?.languageState)
)
}
然后,在AppDelegate.swift
:
import UIKit
import ReSwift
let store = Store<AppState>(reducer: AppReducer, state: nil)
...
...
最后,您可以以标准方式订阅ViewControllers
商店
答案 0 :(得分:2)
只需将其插入Xcode游乐场即可查看其机械工作原理。如果它打印&#34; Slick daddy&#34;然后它就联系起来了。可能需要进行大量的微调,例如确保您只更新已更改的数据,但是,如果代表模式不是您的选择,则使用观察者是一个很好的选择。
class ControllerA {
// use a data model for the view controller
let dataModel = "Slick daddy"
init() {
postNoti()
}
// whenever a change is made, first update the data model and
// then post a notification and attach the data model object
func postNoti() {
NotificationCenter.default.post(name: Notification.Name("slickDaddy"), object: dataModel)
}
}
class ControllerB {
init() {
addObserver()
}
// add an observer for that notification
func addObserver() {
NotificationCenter.default.addObserver(self, selector: #selector(notificationHandler(_:)), name: Notification.Name("slickDaddy"), object: nil)
}
// handle the notification using the data model and make
// the changes to the current controller
@objc func notificationHandler(_ sender: Notification) {
guard let model = sender.object else {
return
}
print(model) // verifies it works
}
}
let b = ControllerB()
let a = ControllerA()
// prints "Slick daddy"
答案 1 :(得分:1)
您可以使用NotificationCenter
来实现这一目标。首先,我们必须创建一个单例类,并创建一个全局变量didUpdateNotificationName
,我们将用它来发布事件并订阅事件:
let didUpdateDataNotificationName = "didUpdateDataNotificationName"
class AppState {
static var shared = AppState()
private init(){
self.counter = 0
self.language = "English"
}
private (set) var counter: Int {
didSet {
NotificationCenter.default.post(name: NSNotification.Name(rawValue: didUpdateDataNotificationName), object: nil)
}
}
private (set) var language: String {
didSet {
NotificationCenter.default.post(name: NSNotification.Name(rawValue: didUpdateDataNotificationName), object: nil)
}
}
func update(counter: Int){
self.counter = counter
}
func update(language: String){
self.language = language
}
}
之后,在每个UIViewController上,您可以添加更新的侦听器:
NotificationCenter.default.addObserver(
self,
selector: #selector(updateView),
name: NSNotification.Name(rawValue: didUpdateDataNotificationName),
object: nil)
同时确保实现将在每个通知上执行的方法,在我们的案例中updateView
:
@objc func updateView(){
label.text = "\(DataModel.shared.counter) \(DataModel.shared.language)"
}
现在,每次更新AppState
类中的变量时,都会向所有观察者发送通知。
一个非常重要的注意事项是,当您处理通知时,应该在不再需要时删除观察者。例如,在您班级的deinit
方法中:
deinit {
NotificationCenter.default.removeObserver(
self,
name: NSNotification.Name(rawValue: didUpdateDataNotificationName),
object: self)
}
答案 2 :(得分:0)
如果是UITabBarController,您只需使用以下代码即可访问FirtsViewController中的SecondViewController
var svc:SecondViewController = self.tabBarController.viewControllers[1] as SecondViewController!