Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Working example please #117

Closed
amalashin opened this issue Apr 28, 2020 · 5 comments
Closed

Working example please #117

amalashin opened this issue Apr 28, 2020 · 5 comments
Assignees
Labels

Comments

@amalashin
Copy link

amalashin commented Apr 28, 2020

Hello! It seems like SwiftySalesforce is an awesome package but I totally cannot set it up. I tried almost everything and spend around two days 😱 with trying to bring things to work. Explored README as well as #114 and #115 and totally misunderstood what I'm doing wrong. So, do you have a working example?...

For now I have in SceneDelegate.swift:

func sceneDidBecomeActive(_ scene: UIScene) {
        print("become active")
        
        let consumerKey = "3MVG9wEVwV0C9e.....................82X"
        let callbackURL = URL(string: "sfdc://authorization/done")!
        let connectedApp = ConnectedApp(consumerKey: consumerKey, callbackURL: callbackURL)
        sfdc = Salesforce(connectedApp: connectedApp)
        
        let subscription = sfdc.identity().sink(receiveCompletion: { (completion) in
            print(completion)
        }) { identity in
            print(identity)
        }
}

When I start an app, I got a message to allow to authorize. After authorization I got nothing.... What I am doing wrong? 😒

@mike4aday mike4aday self-assigned this Apr 29, 2020
@mike4aday
Copy link
Owner

Hi @amalashin - subscription is not being retained so the network request gets canceled before your closures are called. Try:

var subscriptions = Set<AnyCancellable>()
//... other stuff in SceneDelegate
func sceneDidBecomeActive(_ scene: UIScene) {
    // Set up Salesforce with Connected App info
    sfdc.identity().sink(receiveCompletion: { (completion) in
        print(completion)
    }) { identity in
        print(identity)
    }.store(in: &subscriptions)
}

@amalashin
Copy link
Author

🤦🏻‍♂️
It seems like I need to learn a little bit more about Combine. Thank you for clarification.

Am I right that the authentication question will be automatically opened with any request in case of the expired token?

@amalashin
Copy link
Author

amalashin commented May 1, 2020

It looks like I finally got it! At least, it works for me (and may be will be useful for someone) :) Could you please check.

UserSettings.swift

final class UserSettings: ObservableObject {
    private var sfdc: Salesforce
    private var disposables = Set<AnyCancellable>()
    @Published var identity: Identity? = nil
    
    init() {
        let consumerKey = "3MVG9wEVwV..................HkrL82X"
        let callbackURL = URL(string: "sfdc://authorization/done")!
        let connectedApp = ConnectedApp(consumerKey: consumerKey, callbackURL: callbackURL)
        self.sfdc = Salesforce(connectedApp: connectedApp)
    
        self.sfdc.identity()
        .receive(on: RunLoop.main)
        .eraseToAnyPublisher()
        .sink(
            receiveCompletion: { [weak self] value in
                guard let self = self else { return }
                switch value {
                case let .failure(error):
                    print("Error: \(error)")
                    self.identity = nil
                    break
                case .finished:
                    print("Finished receiving Identity!")
                    break
                }
            },
            receiveValue: {
                self.identity = $0
                print("Identity user: \($0.displayName)")
            }
        ).store(in: &disposables)
    }
}

SceneDelegate.swift

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    var window: UIWindow?

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
 
        let mainView = MainView().environmentObject(UserSettings())

        if let windowScene = scene as? UIWindowScene {
            let window = UIWindow(windowScene: windowScene)
            window.rootViewController = UIHostingController(rootView: mainView)
            self.window = window
            window.makeKeyAndVisible()
        }
    }
}

MainView.swift

struct MainView: View {
    @EnvironmentObject var userSettings: UserSettings
    
    var body: some View {
        if userSettings.identity != nil {
            return AnyView(UserView())
        } else {
            return AnyView(LoadingView())
        }
    }
}

struct UserView: View {
    @EnvironmentObject var userSettings: UserSettings

    var body: some View {
        VStack {
            VStack {
                CircleImage(image: Image("none"))
                Text(userSettings.identity != nil ? userSettings.identity!.displayName : "none")
            }
        }
    }
}

struct LoadingView: View {
    var body: some View {
        Text("Loading...")
    }
}

@mike4aday
Copy link
Owner

Hi @amalashin in answer to your question on authentication:

Yes, correct - Swiftly Salesforce will automatically initiate re-authentication if the stored token has expired.

You could override this default behavior if the user might be confused by the appearance of the Salesforce login form -- see RequestConfig and set authenticateIfRequired to false.

@mike4aday
Copy link
Owner

@amalashin I will close this issue for now - if you have more questions, please re-open or create another.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants