如何仅在接收数据时制作已发布的属性调用映射
Posted
技术标签:
【中文标题】如何仅在接收数据时制作已发布的属性调用映射【英文标题】:How to make a Published property call map only when it receives data 【发布时间】:2021-06-02 11:12:49 【问题描述】:我是 Combine 的新手,我正在尝试创建一个登录流程,其中:
当我点击登录按钮时,应用会触发 GoogleSignInsign
函数
然后,当在 GoogleDelegate 上接收到会话数据时,它需要向我的服务器端登录方法发起请求。
为此,我有一个控制登录过程的 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
委托之后)才应该映射它。我该怎么做?
【问题讨论】:
【参考方案1】:刚刚想出了解决这个问题的方法。在我的例子中使用的正确数据类型是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
以这种方式使地图仅在主题收到事件时才被调用。
【讨论】:
以上是关于如何仅在接收数据时制作已发布的属性调用映射的主要内容,如果未能解决你的问题,请参考以下文章