swiftswiftuisnapchatuiviewrepresentable

Can I use the Snapchat SDK (SnapKit) with SwiftUI?


I'm trying to integrate Snapkit with an iOS app but I want to use SwiftUI instead of UIKit. I've already done the required setup with Snapkit and now I'm trying to get the snapchat login button to display in my app. I know the Snapkit SDK is made for UIKit and not SwiftUI, but SwiftUI has a way to wrap UIViews into SwiftUI with the UIViewRepresentable protocol. I've tried implementing this but the login button still doesn't display.

Here's my code:

import SwiftUI
import UIKit
import SCSDKLoginKit

struct ContentView: View {
    var body: some View {
        SnapchatLoginButtonView()
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}


struct SnapchatLoginButtonView: UIViewRepresentable {

    func makeCoordinator() -> Coordinator {
        Coordinator()
    }

    func makeUIView(context: Context) -> SCSDKLoginButton {
        let s = SCSDKLoginButton()
        s.delegate = context.coordinator

        return s
    }

    func updateUIView(_ uiView: SCSDKLoginButton, context: Context) {
    }

    class Coordinator: NSObject, SCSDKLoginButtonDelegate {
        func loginButtonDidTap() {
        }
    }
}

I have a feeling I'm missing something from within SCSDKLoginButton, but not sure what it is so here's the file SCSDKLoginButton.h for reference. Any help would be greatly appreciated!

//
//  SCSDKLoginButton.h
//  SCSDKLoginKit
//
//  Copyright © 2018 Snap, Inc. All rights reserved.
//

#import <UIKit/UIKit.h>

@protocol SCSDKLoginButtonDelegate
- (void)loginButtonDidTap;
@end

@interface SCSDKLoginButton : UIView

@property (nonatomic, weak, nullable) id<SCSDKLoginButtonDelegate> delegate;

- (instancetype)initWithCompletion:(nullable void (^)(BOOL success, NSError *error))completion NS_DESIGNATED_INITIALIZER;

@end

Solution

  • @Stephen2697 was right in pointing out that the snap sdk isn't built for iOS 13 yet due to SceneDelegate now handling oauth redirects rather than AppDelegate. I figured out a workaround to use the SCSDKLoginClient.application() method (which was made for appdelegate) to be used in scene delegate. Here's the code, add it to your scene delegate and the completion handler passed in to your Snapchat login will run:

    func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
        for urlContext in URLContexts {
            let url = urlContext.url
            var options: [UIApplication.OpenURLOptionsKey : Any] = [:]
            options[.openInPlace] = urlContext.options.openInPlace
            options[.sourceApplication] = urlContext.options.sourceApplication
            options[.annotation] = urlContext.options.annotation
            SCSDKLoginClient.application(UIApplication.shared, open: url, options: options)
        }
    }
    

    As far as the login button not appearing, make sure to add a completion handler to the SCSDKLoginButton instance or else it won't work. Like this:

    let s = SCSDKLoginButton { (success, error) in
            //handle login
        }