Search code examples
mongodbauthenticationswiftuirealmrealm-mobile-platform

MongoDB Realm SwiftUI continue session / auto login


I'm using SwiftUI 2 with a MongoDB synced Realm (10.5.2) and I'm currently stuck with how to continue a session once a user reopens the app.

As an authentication I use email and password via a publisher and I know that I can check if the user is logged in with this function:

app.currentUser!.isLoggedIn

which also returns true for my user. However I don't know how I can get the publisher $0 from the

app.login(credentials: .emailPassword(email: username, password: password))
            .receive(on: DispatchQueue.main)
            .sink(receiveCompletion: {
                self.state.shouldIndicateActivity = false
                switch $0 {
                case .finished:
                    break
                case .failure(let error):
                    self.state.error = error.localizedDescription
                }
            }, receiveValue: {
                self.state.cardPublisher.send($0)

            })
            .store(in: &state.cancellables)

method where I use

self.state.cardPublisher.send($0)

to fetch my data. So my question is how do I get the $0 if the user restarts the app.

Sorry if that's a stupid question but I'm quite new to combine.

Any help is much appreciated :)

If it's helpful for you, I currently have these two publishers:

var cardPublisher = PassthroughSubject<RealmSwift.User, Error>()
let cardRealmPublisher = PassthroughSubject<Realm, Error>()

which are used like this:

cardPublisher
            .receive(on: DispatchQueue.main)
            .flatMap { user -> RealmPublishers.AsyncOpenPublisher in
                self.shouldIndicateActivity = true
                var realmConfig = user.configuration(partitionValue: "teamID=123")
                realmConfig.objectTypes = [Card.self, Dog.self]
                return Realm.asyncOpen(configuration: realmConfig)
            }
            .receive(on: DispatchQueue.main)
            .map {
                self.shouldIndicateActivity = false
                return $0
            }
            .subscribe(cardRealmPublisher)
            .store(in: &self.cancellables)

cardRealmPublisher
            .sink(receiveCompletion: { result in
                if case let .failure(error) = result {
                    self.error = "Failed to log in and open realm: \(error.localizedDescription)"
                }
            }, receiveValue: { realm in
                self.cardRealm = realm
                self.loadData()
            })
            .store(in: &cancellables)

Solution

  • I managed to solve it myself and it was actually quite easy. For anyone who might need it as well just use this method once the app loads:

    if app.currentUser!.isLoggedIn {
                    app.currentUser.publisher
                    .receive(on: DispatchQueue.main)
                    .sink(receiveCompletion: {
                        self.shouldIndicateActivity = false
                        switch $0 {
                        case .finished:
                            break
                        case .failure(let error):
                            self.error = error.localizedDescription
                        }
                    }, receiveValue: {
                        self.error = nil
                        self.cardPublisher.send($0)
    
                    })
                    .store(in: &self.cancellables)
    } else { 
    // Regular Login
    }