你好???? 我花了 10 多個小時來實作Combine框架,但不清楚如何鏈接Publisher和Subscriber. 在示例中,我只想setTheme從類中呼叫 funkTheme并自動更新類game中的變數Game。我知道如何實作它,didSet但主要目標是用Combine. 非常感謝您的幫助。
import SwiftUI
import Combine
import Foundation
class Theme: ObservableObject {
@Published private(set) var choosenTheme: Color? // Publisher right?
func setTheme(with color: Color?) {
if let unwrappedColor = color {
self.choosenTheme = unwrappedColor
} else {
self.choosenTheme = nil
}
}
}
class Game: ObservableObject {
@Published var game: String? // Subscriber right?
private let gameTheme = Theme()
private var cancellables = Set<AnyCancellable>()
init() {
addSubscribers()
}
private func addSubscribers() { // I think something wrong here
gameTheme.$choosenTheme
.map(createGame)
.sink { [weak self] (returnedString) in
print("Value from sink \(String(describing: returnedString))")
self?.game = returnedString
}
.store(in: &cancellables)
}
private func createGame(for theme: Color?) -> String? {
if let unwrappedTheme = theme {
print(unwrappedTheme)
return String("\(unwrappedTheme)")
} else {
return nil
}
}
}
// Test:
var testTheme = Theme()
testTheme.setTheme(with: .orange)
var testGame = Game()
print(testGame.game) // Should be Orange
testTheme.setTheme(with: .blue)
print(testGame.game) // Should be Blue
testTheme.setTheme(with: nil)
print(testGame.game) // Should be nil
uj5u.com熱心網友回復:
您遇到的問題是有兩個實體Theme
您在此處創建的一個:
// Test:
var testTheme = Theme()
還有一個在里面Game:
private let gameTheme = Theme()
然后你正在改變第一個主題并期望第二個主題改變。要解決問題,您必須Theme將Game.
首先,您需要進行一些更改以Game允許Theme注入:
class Game: ObservableObject {
@Published var game: String?
private let gameTheme: Theme
private var cancellables = Set<AnyCancellable>()
init(gameTheme: Theme) {
self.gameTheme = gameTheme
addSubscribers()
}
接下來,您必須在測驗時執行該注入:
var testTheme = Theme()
testTheme.setTheme(with: .orange)
var testGame = Game(gameTheme: testTheme)
如果您這樣做 - 您將看到更改正確反映在列印件中。
如果您愿意,可以顯著簡化您的兩個類:
class Theme: ObservableObject {
@Published private(set) var chosenTheme: Color?
func setTheme(with color: Color?) {
chosenTheme = color
}
}
class Game: ObservableObject {
@Published var game: String?
private let gameTheme: Theme
init(gameTheme: Theme) {
self.gameTheme = gameTheme
addBindings()
}
private func addBindings() {
gameTheme
.$chosenTheme
.map(createGame)
.assign(to: &$game)
}
private func createGame(for theme: Color?) -> String? {
theme.map { $0.description }
}
}
uj5u.com熱心網友回復:
它根本不應該改變。你正在做的是設定一個實體的主題Theme。但是,在您的Game課堂上,您正在聽另一堂課。
你現在看到問題了嗎?Game要么用你正在更新的主題初始化你,要么制作Theme一個singleton.
嘗試這個:
import SwiftUI
import Combine
import Foundation
class Theme: ObservableObject {
static var shared = Theme()
@Published private(set) var choosenTheme: Color? // Publisher right?
func setTheme(with color: Color?) {
if let unwrappedColor = color {
self.choosenTheme = unwrappedColor
} else {
self.choosenTheme = nil
}
}
}
class Game: ObservableObject {
@Published var game: String? // Subscriber right?
private let gameTheme = Theme.shared
private var cancellables = Set<AnyCancellable>()
init() {
addSubscribers()
}
private func addSubscribers() { // I think something wrong here
gameTheme.$choosenTheme
.map(createGame)
.sink { [weak self] (returnedString) in
print("Value from sink \(String(describing: returnedString))")
self?.game = returnedString
}
.store(in: &cancellables)
}
private func createGame(for theme: Color?) -> String? {
if let unwrappedTheme = theme {
print(unwrappedTheme)
return String("\(unwrappedTheme)")
} else {
return nil
}
}
}
// Test:
var testGame = Game() //Game initialization should precede Theme because now the listener starts listening for the orange change
var testTheme = Theme.shared
testTheme.setTheme(with: .orange)
print(testGame.game) // Should be Orange
testTheme.setTheme(with: .blue)
print(testGame.game) // Should be Blue
testTheme.setTheme(with: nil)
print(testGame.game) // Should be nil
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/491673.html
