I'm working on a react native library including auth processes, So I chose ASWebAuthenticationSession to do it. My first step for this RN library was to develop natively first(in Swift). And when I started this new library it cames with both objective-c bridge and swift and I assume that both files could do the same.
But I can't run ASWebAuthenticationSession from the swift file properly where objective c runs it perfectly and I prefer to do it from Swift (If I'm wrong tell me)
The problem is that when I run code from swift the ASWebAuthenticationSession popup closes before any user input but not from objective-c . Here are my codes, if you have an idea thank you by advance.
Swift Version
//MyRnModule.m
@interface RCT_EXTERN_MODULE(MyRNModule, NSObject)
- (dispatch_queue_t)methodQueue
{
return dispatch_get_main_queue();
}
RCT_EXTERN_METHOD(startSecuredView:(NSURL *)uri)
//MyRnModule.swift
@objc(MyRNModule)
class MyRNModule: NSObject {
@objc func startSecuredView(_ url: URL?) {
if let url = url {
if #available(iOS 12.0, *) {
let session = ASWebAuthenticationSession(url: url, callbackURLScheme: "", completionHandler: { (callbackURL, error) in
print("completed")
if let error = error {
print("erorr \(error)")
return
}
if let callbackURL = callbackURL {
print("should handle callback \(callbackURL)")
}
})
if #available(iOS 13.0, *) {
session.presentationContextProvider = self
}
session.start()
}
} else {
print("you must specify url")
}
}
}
extension MyRNModule: ASWebAuthenticationPresentationContextProviding {
@available(iOS 13, *)
func presentationAnchor(for session: ASWebAuthenticationSession) -> ASPresentationAnchor{
if let keyWindow = UIApplication.shared.windows.filter {$0.isKeyWindow}.first {
return keyWindow
} else {
return ASPresentationAnchor()
}
}
}
Objective-C
@interface RCT_EXTERN_MODULE(MyRNModule, NSObject)
- (dispatch_queue_t)methodQueue
{
return dispatch_get_main_queue();
}
RCT_EXPORT_METHOD(startSecuredView:(NSURL *)url)
{
if (!url) {
RCTLogError(@"You must specify a url.");
return;
}
if (@available(iOS 12.0, *)) {
ASWebAuthenticationSession* session =
[[ASWebAuthenticationSession alloc] initWithURL:url
callbackURLScheme: @""
completionHandler:^(NSURL * _Nullable callbackURL,
NSError * _Nullable error) {
_authenticationVCC = nil;
if (callbackURL) {
[RCTSharedApplication() openURL:callbackURL];
}
}];
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
if (@available(iOS 13.0, *)) {
session.presentationContextProvider = self;
}
#endif
_authenticationVCC = session;
[session start];
}
}
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
#pragma mark - ASWebAuthenticationPresentationContextProviding
- (ASPresentationAnchor)presentationAnchorForWebAuthenticationSession:(ASWebAuthenticationSession *)session API_AVAILABLE(ios(13.0)){
return UIApplication.sharedApplication.keyWindow;
}
#endif
Codes seems to reflect same processes, just translated, I don't know what I'm missing out because call of MyRNModule. startSecuredView("https://some.url")
do not behave the same
In your Objective-C Code, you hold a "strong" reference to the session.
In your Swift Code, you do not.
The documentation states that a strong reference is mandatory for iOS < 13.0, otherwise it will be immediately removed as there is no more active reference to the session when your method ends. This results in the window getting closed.
To fix this, you could add an attribute to your class
MyRNModule
and assign the sessionto this attribute instead of a local constant before starting it.And later in your method:
Cite from the docs: