英文:
Pass CurrentValueSubject value wrapped in an AnyPublisher to another class
问题
以下是您的代码的翻译部分:
protocol SomeProtocol {
var isLocalNotificationsEnabledPublisher: AnyPublisher<Bool, Error> { get }
func saveLocalNotifications(_ enabled: Bool) throws
}
final class UserSettingsClass {
private var repository: CoreDataRepo
private var isLocalNotificationsEnabledSubject = CurrentValueSubject<Bool, Error>(false)
// 我将其设置为私有,以防其他类从外部更改它,我只能订阅它的值。
private var cancellables = Set<AnyCancellable>()
init(repository: CoreDataRepo) {
self.repository = repository
binding()
}
}
extension UserSettingsClass: SomeProtocol {
var isLocalNotificationsEnabledPublisher: AnyPublisher<Bool, Error> {
return isLocalNotificationsEnabledSubject.eraseToAnyPublisher()
}
func saveLocalNotifications(_ enabled: Bool) throws {
var userSettings = userSettings // 这是核心数据对象...
userSettings?.isLocalNotificationsEnabled = enabled
// 这是重要部分,它具有此切换。
// 我需要能够将这个值发送到我的LocalNotificaitonsService类,并基于这个值判断是否可以发送本地通知。
if isLocalNotificationsEnabledSubject.value != enabled {
throw someError
}
isLocalNotificationsEnabledSubject.send(userSettings?.isLocalNotificationsEnabled ?? false)
}
}
以下是如何将其绑定到发布者以便我可以订阅saveLocalNotifications方法中发送的值的方式:
private func binding() {
isLocalNotificationsEnabledPublisher
.sink(
receiveCompletion: { _ in },
receiveValue: { [weak self] value in
do {
try saveLocalNotifications(value) // 这里有递归 + 未正确处理错误...
} catch {
return
}
}
).store(in: &cancellables)
}
这段代码导致了导致我的应用程序崩溃的递归。以下是我尝试在本地通知管理器中使用它的方式:
private let isLocalNotificationsEnabledPublisher: AnyPublisher<Bool, Error>
private var cancellables = Set<AnyCancellable>()
public init(isLocalNotificationsEnabledPublisher: AnyPublisher<Bool, Error>) {
self.isLocalNotificationsEnabledPublisher = isLocalNotificationsEnabledPublisher
}
extension LocalNotificationsManager: SomeOtherProtocol {
public func requestNotificationAuthorization() throws {
isLocalNotificationsEnabledPublisher
.sink(
receiveCompletion: { _ in },
receiveValue: { [weak self] value in
if value == true {
Task {
try await self?.center.requestAuthorization(options: [.badge, .sound, .alert])
}
}
}
).store(in: &cancellables)
}
}
因此,这段代码不起作用,因为我不知道如何在本地通知管理器类中获取主题值。我需要能够订阅用户设置中的切换值,并决定是否可以发送本地通知。感谢您提前的帮助。
英文:
Showing you my code:
protocol SomeProtocol {
var isLocalNotificationsEnabledPublisher: AnyPublisher<Bool, Error> { get }
func saveLocalNotifications(_ enabled: Bool) throws
}
final class UserSettingsClass {
private var repository: CoreDataRepo
private var isLocalNotificationsEnabledSubject = CurrentValueSubject<Bool, Error>(false)
// I make it private so that no other classes can change it from outside,
// I can only subscribe on its values.
private var cancellables = Set<AnyCancellable>()
init(repository: CoreDataRepo) {
self.repository = repository
binding()
}
}
extension UserSettingsClass: SomeProtocol {
var isLocalNotificationsEnabledPublisher: AnyPublisher<Bool, Error> {
return isLocalNotificationsEnabledSubject.eraseToAnyPublisher()
}
func saveLocalNotifications(_ enabled: Bool) throws {
var userSettings = userSettings // this is core data object...
userSettings?.isLocalNotificationsEnabled = enabled
// this is the important part, it has this toggle.
// I need to be able to send this value to my LocalNotificaitonsService class and based
// on this value understand whether I can send local notifications or not.
if isLocalNotificationsEnabledSubject.value != enabled {
throw someError
}
isLocalNotificationsEnabledSubject.send(userSettings?.isLocalNotificationsEnabled ?? false)
}
}
Here is how I bind it to my publisher so that I could subscribe to the value that I send in the saveLocalNotifications method:
private func binding() {
isLocalNotificationsEnabledPublisher
.sink(
receiveCompletion: { _ in },
receiveValue: { [weak self] value in
do {
try saveLocalNotifications(value) // recursion here + not handling error properly...
} catch {
return
}
}
).store(in: &cancellables)
}
This code causes recursion that leads to my app crashing.
Here is how I try to use it in my local notifications manager:
private let isLocalNotificationsEnabledPublisher: AnyPublisher<Bool, Error>
private var cancellables = Set<AnyCancellable>()
public init(isLocalNotificationsEnabledPublisher: AnyPublisher<Bool, Error>) {
self.isLocalNotificationsEnabledPublisher = isLocalNotificationsEnabledPublisher
}
extension LocalNotificationsManager: SomeOtherProtocol {
public func requestNotificationAuthorization() throws {
isLocalNotificationsEnabledPublisher
.sink(
receiveCompletion: { _ in },
receiveValue: { [weak self] value in
if value == true {
Task {
try await self?.center.requestAuthorization(options: [.badge, .sound, .alert])
}
}
}
).store(in: &cancellables)
}
So basically this code does not work properly because I do not understand how to get the subject value in the local notifications manager class. I need to be able to sink on the toggle value from the user settings and decide if I can or can not send local notifications.
Thank you in advance.
答案1
得分: 1
你出现递归是因为你调用了saveLocalNotifications
,然后触发了Combine链,因为它反过来调用了isLocalNotificationsEnabledSubject.send(...)
。
为了防止递归,你可以在订阅isLocalNotificationsEnabledSubject
的Combine链中使用removeDuplicates
。
话虽如此,你可能需要重新考虑你的架构,以避免递归的发生。
英文:
You have recursion because you call saveLocalNotifications
and then that triggers the Combine chain again, since that in turn calls isLocalNotificationsEnabledSubject.send(...)
.
To prevent the recursion, you could use removeDuplicates
in the Combine chain where you subscribe to isLocalNotificationsEnabledSubject
That being said, you may wan to reconsider your architecture so that the recursion isn't possible.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论