gpt4 book ai didi

swift - 如何让Published属性只在收到数据时调用map

转载 作者:行者123 更新时间:2023-12-05 06:00:13 31 4
gpt4 key购买 nike

我是 Combine 的新手,我正在尝试创建一个登录流程,其中:

  • 当我点击登录按钮时,应用会触发 GoogleSignIn sign 函数
  • 然后,当 GoogleDelegate 收到 session 数据时,它需要启动对我的服务器端登录方法的请求。

为此,我有一个控制登录过程的 GoogleSignInController:

class GoogleSignInController: GIDSignInDelegate {
@Published var onSessionAcquired: GoogleSignInSessionData = ("", "")

func signIn() {
if (GIDSignIn.sharedInstance()?.presentingViewController == nil) {
GIDSignIn.sharedInstance()?.presentingViewController = UIApplication.shared.windows.last?.rootViewController
}
GIDSignIn.sharedInstance()?.signIn()
}

func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error!) {
if let error = error {
if (error as NSError).code == GIDSignInErrorCode.hasNoAuthInKeychain.rawValue {
print("The user has not signed in")
} else {
print("\(error.localizedDescription)")
}
return
}

onSessionAcquired = GoogleSignInSessionData(idToken: user.authentication.idToken ?? "", serverAuthCode: user.serverAuthCode ?? "")

print("Successful sign-in!")
signedIn = true
}
}

然后在 ViewModel 中,我使用一些状态来控制过程:

    static func whenStartedLogin() -> Feedback<State, Event> {
Feedback { (state: State) -> AnyPublisher<Event, Never> in
guard case .loadingGoogleSignIn = state else { return Empty().eraseToAnyPublisher() }

GoogleSignInController.shared.signIn()

return GoogleSignInController.shared.$onSessionAcquired
.receive(on: DispatchQueue.main)
.map { Event.onGoogleSessionAcquired($0) }
.eraseToAnyPublisher()
}
}

static func whenReceivedGoogleSession() -> Feedback<State, Event> {
Feedback { (state: State) -> AnyPublisher<Event, Never> in
guard case let .loadingServerSession(googleSession) = state else { return Empty().eraseToAnyPublisher() }

return self.signIn(idToken: googleSession.idToken, serverAuthCode: googleSession.serverAuthCode)
.map { (userInfo, error) in
if let error = error {
return Event.onFailedToAcquireSession(error)
} else if let userInfo = userInfo {
return Event.onUserInfoAcquired(userInfo)
} else {
return Event.onFailedToAcquireSession(AppError.unknown)
}
}
.eraseToAnyPublisher()
}
}

问题是:当我点击登录按钮时,whenStatedLogin 函数被触发,它将我的事件映射到 Event.onGoogleSessionAcquired。这应该仅在 onSessionAcquired 更改时映射(在调用 sign 委托(delegate)之后)。我该怎么做?

最佳答案

刚想出这个问题的解决方案。在我的案例中要使用的正确数据类型是 PassthroughSubject

let sessionSubject = PassthroughSubject<GoogleSignInSessionData, Never>()

...

func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error!) {
if let error = error {
if (error as NSError).code == GIDSignInErrorCode.hasNoAuthInKeychain.rawValue {
print("The user has not signed in")
} else {
print("\(error.localizedDescription)")
}
return
}

sessionSubject.send(GoogleSignInSessionData(idToken: user.authentication.idToken ?? "", serverAuthCode: user.serverAuthCode ?? ""))

print("Successful sign-in!")
signedIn = true
}

采用这种方式将使 map 仅在主题接收到事件时调用。

关于swift - 如何让Published属性只在收到数据时调用map,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67804019/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com