How make globalSignOut in CognitoAuth - Swift? - swift

I have the next block that is called when user wants signOut:
Im using Swift 5 and call the signOut, but need the globalSignOut.
class LoginController: UIViewController{
var auth: AWSCognitoAuth = AWSCognitoAuth.default()
var session: AWSCognitoAuthUserSession?
//..
override func viewDidLoad() {
super.viewDidLoad()
self.auth.delegate = self
}
func signOutAws(){
self.auth.signOut(self, completion: { (error) in
if error != nil{
//show alert..
}else{
self.session = nil
self.auth = AWSCognitoAuth.default()
self.auth.delegate = self
}
})
}
//..
}
I expect that the user session expired in all apps, but has not expired session in all apps.

Related

delegate method does not get called second time

I am building a simple currency converter app. When ViewController gets opened it calls a function from CoinManager.swift:
class ViewController: UIViewController {
var coinManager = CoinManager()
override func viewDidLoad() {
super.viewDidLoad()
coinManager.delegate = self
coinManager.getCoinPrice(for: "AUD", "AZN", firstCall: true)
}
...
}
CoinManager.swift:
protocol CoinManagerDelegate {
func didUpdatePrice(price1: Double, currency1: String, price2: Double, currency2: String)
func tellTableView(descriptions: [String], symbols: [String])
func didFailWithError(error: Error)
}
struct CoinManager {
var delegate: CoinManagerDelegate?
let baseURL = "https://www.cbr-xml-daily.ru/daily_json.js"
func getCoinPrice (for currency1: String,_ currency2: String, firstCall: Bool) {
if let url = URL(string: baseURL) {
let session = URLSession(configuration: .default)
let task = session.dataTask(with: url) { (data, response, error) in
if error != nil {
self.delegate?.didFailWithError(error: error!)
return
}
if let safeData = data {
if let coinData = self.parseJSON(safeData) {
if firstCall {
var descriptions = [""]
let listOfCoins = Array(coinData.keys)
for key in listOfCoins {
descriptions.append(coinData[key]!.Name)
}
descriptions.removeFirst()
self.delegate?.tellTableView(descriptions: descriptions, symbols: listOfCoins)
}
if let coinInfo1 = coinData[currency1] {
let value1 = coinInfo1.Value
if let coinInfo2 = coinData[currency2] {
let value2 = coinInfo2.Value
//this line does not do anything the second time I call getCoinPrice:
self.delegate?.didUpdatePrice(price1: value1, currency1: currency1, price2: value2, currency2: currency2)
//And this one does work
print("delegate:\(currency1)")
} else {
print("no name matches currency2")
}
} else {
print("no name matches currency1")
}
}
}
}
task.resume()
}
}
func ParseJSON....
}
The method it calls (ViewController.swift):
extension ViewController: CoinManagerDelegate {
func didUpdatePrice(price1: Double, currency1: String, price2: Double, currency2: String) {
print("didUpdatePrice called")
DispatchQueue.main.async {
let price1AsString = String(price1)
let price2AsString = String(price2)
self.leftTextField.text = price1AsString
self.rightTextField.text = price2AsString
self.leftLabel.text = currency1
self.rightLabel.text = currency2
}
}
...
}
and finally, CurrencyViewController.swift:
var coinManager = CoinManager()
#IBAction func backButtonPressed(_ sender: UIBarButtonItem) {
dismiss(animated: true, completion: nil)
coinManager.getCoinPrice(for: "USD", "AZN", firstCall: false)
}
So when I launch the app i get following in my debug console:
didUpdatePrice called
delegate:AUD
And when I call getCoinPrice() from CurrencyViewController the delegate method does not get called. I know that my code goes through the delegate function line as I get this in debug console:
delegate:USD
I just can't wrap my head around it. The delegate method does not work when gets called second time. Even though it is called by the same algorithm
It's because you're creating a new object of CoinManager in CurrencyViewController where the delegate is not set. So you've to set the delegate every time you create a new instance of CoinManager.
#IBAction func backButtonPressed(_ sender: UIBarButtonItem) {
dismiss(animated: true, completion: nil)
coinManager.delegate = self
coinManager.getCoinPrice(for: "USD", "AZN", firstCall: false)
}
Update: So, the above solution would require for you to make the delegate conformance in CurrencyViewController. If you're looking for an alternate solution you should probably pass the instance of coinManager in ViewController to CurrencyViewController. For that here are the things you need to update.
In CurrencyViewController:
class CurrencyViewController: UIViewController {
var coinManager: CoinManager! // you can optional unwrap if you intent to use CurrencyViewController without coinManager
//...
And in ViewController:
currencyViewController.coinManager = coinManager // passing the instance of coinManager
Can you share the full code of CoinManager? I see this part
if firstCall {
...
}
Maybe some block logic here or unhandled cases? And can you share the full code of protocol?
Also try to print something before this code:
if error != nil {
self.delegate?.didFailWithError(error: error!)
return
}

didInititate method for Spotify IOS SDK is not calling even though called sessionManager.initiateSession()

I'm going through Spotify's authentication process and am requesting the scopes appRemoteControl for my app to control music and userReadCurrentlyPlaying for current song. I set up everything from the SPTConfiguration, SPTSessionManager, and SPTAppRemote, and their required delegate methods (SPTAppRemoteDelegate, SPTSessionManagerDelegate, SPTAppRemotePlayerStateDelegate) as well as initiating a session with the requested scopes whenever the user presses a button but I can't get the method
func sessionManager(manager: SPTSessionManager, didInitiate session: SPTSession) {
appRemote.connectionParameters.accessToken = session.accessToken
appRemote.connect()
print(session.accessToken)
}
to trigger. The authentication process fully works as it goes into my spotify app and returns back to my application and plays a song from the configuration.playURI = "" , however, the method above never is called. I followed the spotify demo project but still does not work. Here is my full code
class LogInViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
let spotifyClientID = Constants.clientID
let spotifyRedirectURL = Constants.redirectURI
let tokenSwap = "https://***********.glitch.me/api/token"
let refresh = "https://***********.glitch.me/api/refresh_token"
lazy var configuration: SPTConfiguration = {
let configuration = SPTConfiguration(clientID: spotifyClientID, redirectURL: URL(string: "Lyrically://callback")!)
return configuration
}()
lazy var sessionManager: SPTSessionManager = {
let manager = SPTSessionManager(configuration: configuration, delegate: self)
if let tokenSwapURL = URL(string: tokenSwap), let tokenRefreshURL = URL(string: refresh) {
self.configuration.tokenSwapURL = tokenSwapURL
self.configuration.tokenRefreshURL = tokenRefreshURL
self.configuration.playURI = ""
}
return manager
}()
lazy var appRemote: SPTAppRemote = {
let appRemote = SPTAppRemote(configuration: configuration, logLevel: .debug)
appRemote.delegate = self
return appRemote
}()
#IBAction func logIn(_ sender: UIButton) {
let requestedScopes: SPTScope = [.appRemoteControl, .userReadCurrentlyPlaying]
sessionManager.initiateSession(with: requestedScopes, options: .default)
}
}
extension LogInViewController: SPTAppRemotePlayerStateDelegate {
func playerStateDidChange(_ playerState: SPTAppRemotePlayerState) {
print("state changed")
}
}
extension LogInViewController: SPTAppRemoteDelegate {
func appRemoteDidEstablishConnection(_ appRemote: SPTAppRemote) {
print("connected")
appRemote.playerAPI?.delegate = self
appRemote.playerAPI?.subscribe(toPlayerState: { (success, error) in
if let error = error {
print("Error subscribing to player state:" + error.localizedDescription)
}
})
}
func appRemote(_ appRemote: SPTAppRemote, didFailConnectionAttemptWithError error: Error?) {
print("failed")
}
func appRemote(_ appRemote: SPTAppRemote, didDisconnectWithError error: Error?) {
print("disconnected")
}
}
extension LogInViewController: SPTSessionManagerDelegate {
func sessionManager(manager: SPTSessionManager, didInitiate session: SPTSession) {
appRemote.connectionParameters.accessToken = session.accessToken
appRemote.connect()
print(session.accessToken)
}
func sessionManager(manager: SPTSessionManager, didFailWith error: Error) {
print("failed",error)
}
}
Figured it out. Had to get a hold of the sessionManager from the LogInViewController by making an instance of it
lazy var logInVC = LogInViewController()
then added this line of code into the openURLContexts method in scene delegate
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
print("Opened url")
guard let url = URLContexts.first?.url else {
return
}
logInVC.sessionManager.application(UIApplication.shared, open: url, options: [:])
}

RealmSwift currentUser cannot be called if more that one valid, logged-in user exists

I have a realm platform and I can register and login a user fine. When I try to open a Synced Realm file with the current User it will not allow it and Xcode throws the error currentUser cannot be called if more that one valid, logged-in user exists. I have followed all the information I can find on realms docs and I can't make sense as to why this is happening. I have a Login View Controller and a separate View Controller that contains the realm file. Here is example code of the problem I am dealing with.
LogInViewController
import Cocoa
import RealmSwift
class LoginViewController: NSViewController {
#IBOutlet weak var username: NSTextField!
#IBOutlet weak var password: NSSecureTextField!
let realm = try! Realm()
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func loginButtonPressed(_ sender: NSButton) {
let login = SyncCredentials.usernamePassword(username: "\(username.stringValue)", password: "\(password.stringValue)", register: false)
SyncUser.logIn(with: login, server: Constants.AUTH_URL, onCompletion: { [weak self] (user, err) in
if let _ = user {
if let mainWC = self?.view.window?.windowController as? MainWindowController {
mainWC.segueToHome()
print("Login Pressed")
}
} else if let error = err {
fatalError(error.localizedDescription)
}
})
}
}
SecondViewController
import Cocoa
import RealmSwift
class ViewController: NSViewController {
#IBOutlet weak var textField: NSTextField!
override func viewDidLoad() {
super.viewDidLoad()
let config = SyncUser.current!.configuration(realmURL: Constants.REALM_URL, fullSynchronization: false, enableSSLValidation: true, urlPrefix: nil)
self.realm = try! Realm(configuration: config)
}
func save(data: Data) {
do {
try realm.write {
realm.add(data)
}
} catch {
print("there was an error saving data \(error)")
}
}
#IBAction func saveData(_ sender: NSButton) {
let saveData = Data()
saveData.textField = textField.stringValue
save(data: data)
}
func loadData() {
data = realm.objects(Data.self).sorted(byKeyPath: "timestamp", ascending: false)
}
}
Maybe, this page help you solve the problem.
I solved the same problem.
///
/// quit all other users session
///
for u in SyncUser.all {
u.value.logOut()
}
///
///
///
let creds: SyncCredentials = SyncCredentials.usernamePassword(
username: YOUR_USER,
password: YOUR_PASS
)
SyncUser.logIn(
with: creds,
server: YOUR_AUTH_URL
) { (user: SyncUser?, err: Error?) in
///
/// Your action ...
///
}
After logOut and logIn, this method will success probably.
let config = SyncUser.current!.configuration(realmURL: Constants.REALM_URL, fullSynchronization: false, enableSSLValidation: true, urlPrefix: nil)
self.realm = try! Realm(configuration: config)
If you are using Realm with Firebase, a snippet like this will save you from authentication headaches.
Check to see if the SyncUser uid matches the uid from firebase, and sign out extraneous accounts.
for syncUser in SyncUser.all {
if(syncUser.key != (FirebaseAuth.Auth.auth().currentUser?.uid ?? "")) {
syncUser.value.logOut()
}
}

Custom FirebaseUI AuthViewController

Using the FirebaseUI Auth 1.0 version and swift 3.
Followed the sample and read the explains how to subclass the FUIAuthPickerViewController but everything I tried it's giving me a
fatal error: unexpectedly found nil while unwrapping an Optional valueonlet controller = self.authUI!.authViewController()
I exactly copied the example and there is it working, so can someone explain what I did wrong or why this is happening?
Code in my ViewController where I want the user to login
ViewController.swift
import Firebase
import FirebaseAuthUI
import FirebaseGoogleAuthUI
import FirebaseFacebookAuthUI
var ref: FIRDatabaseReference!
var remoteConfig: FIRRemoteConfig!
fileprivate var _refHandle: FIRDatabaseHandle!
fileprivate var _authHandle: FIRAuthStateDidChangeListenerHandle!
fileprivate(set) var auth: FIRAuth? = FIRAuth.auth()
fileprivate(set) var authUI: FUIAuth? = FUIAuth.defaultAuthUI()
fileprivate(set) var customAuthUIDelegate: FUIAuthDelegate = FUICustomAuthDelegate()
func configAuth() {
//listen for changes in auth state
_authHandle = FIRAuth.auth()?.addStateDidChangeListener({ (auth: FIRAuth, currentuser: FIRUser?) in
self.users.removeAll(keepingCapacity: false)
self.tableView.reloadData()
if currentuser != nil {
// User is signed in.
self.fetchUser()
} else {
// No user is signed in.
//self.login()
self.loginSession()
}
})
}
func loginSession() {
self.authUI?.delegate = self.customAuthUIDelegate
let googleAuth = FUIGoogleAuth(scopes: [kGoogleUserInfoEmailScope,
kGooglePlusMeScope,
kGoogleUserInfoProfileScope])
let facebookAuth = FUIFacebookAuth(permissions: ["public_profile",
"email",
"user_friends"])
self.authUI?.providers = [googleAuth, facebookAuth]
let controller = self.authUI!.authViewController()
self.present(controller, animated: true, completion: nil)
}
Here the
FUICustomAuthDelegate.swift
import UIKit
import FirebaseAuthUI
import FirebaseAuth
class FUICustomAuthDelegate: NSObject, FUIAuthDelegate {
func authUI(_ authUI: FUIAuth, didSignInWith user: FIRUser?, error: Error?) {
guard let authError = error else { return }
let errorCode = UInt((authError as NSError).code)
switch errorCode {
case FUIAuthErrorCode.userCancelledSignIn.rawValue:
print("User cancelled sign-in");
break
default:
let detailedError = (authError as NSError).userInfo[NSUnderlyingErrorKey] ?? authError
print("Login error: \((detailedError as! NSError).localizedDescription)");
}
}
func authPickerViewController(forAuthUI authUI: FUIAuth) -> FUIAuthPickerViewController {
return FUICustomAuthPickerViewController(authUI: authUI)
}
and the
FUICustomAuthPickerViewController.swift
import FirebaseAuthUI
#objc(FUICustomAuthPickerViewController)
class FUICustomAuthPickerViewController: FUIAuthPickerViewController {
#IBAction func onClose(_ sender: AnyObject) {
self.cancelAuthorization()
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
}

Given login/signUp code by Parse.com, has binary operator error

I am making SignUp/SignIn pages with watching youtube video.
He makes these pages with parseUI,
In his video, there is no error, but I get an error which is
"binary operator "|" cannot be applied to two 'PFLoginFields' operands" (It is checked where in my code down there. )
I checked in parse.com, parse example code is exactly same code with his.
So my Question is
How can I fix this code to work properly?
or Is there any other Binary operator I can use instead of ||?
import UIKit
import Parse
import ParseUI
class NewResisterVC: UIViewController, PFLogInViewControllerDelegate, PFSignUpViewControllerDelegate {
var logInViewController : PFLogInViewController = PFLogInViewController()
var signUpViewController : PFSignUpViewController = PFSignUpViewController()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
if (PFUser.currentUser() == nil) {
/////////// HERE IS A PROBELM /////////////////
self.logInViewController.fields = (PFLogInFields.UsernameAndPassword | PFLogInFields.LogInButton | PFLogInFields.SignUpButton | PFLogInFields.PasswordForgotten | PFLogInFields.DismissButton)
//////////////////////////////////////////
var loginLogoTitle = UILabel()
loginLogoTitle.text = "bany"
self.logInViewController.logInView!.logo = loginLogoTitle
self.logInViewController.delegate = self
var signUpLogoTitle = UILabel()
signUpLogoTitle.text = "bany"
self.signUpViewController.signUpView!.logo = signUpLogoTitle
self.signUpViewController.delegate = self
self.logInViewController.signUpController = self.signUpViewController
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//MARK: Parse Login
func logInViewController(logInController: PFLogInViewController, shouldBeginLogInWithUsername username: String, password: String) -> Bool {
if(!username.isEmpty || !password.isEmpty) {
return true
}else{
return false
}
}
func logInViewController(logInController: PFLogInViewController, didLogInUser user: PFUser) {
self.dismissViewControllerAnimated(true, completion: nil)
}
func logInViewController(logInController: PFLogInViewController, didFailToLogInWithError error: NSError?) {
print("Fail to login")
}
//MARK: Parse Sign Up
func signUpViewController(signUpController: PFSignUpViewController, didSignUpUser user: PFUser) {
self.dismissViewControllerAnimated(true, completion: nil)
}
func signUpViewController(signUpController: PFSignUpViewController, didFailToSignUpWithError error: NSError?) {
print("fail to sign up...")
}
func signUpViewControllerDidCancelSignUp(signUpController: PFSignUpViewController) {
print("User dismissed sign up")
}
// mark: Actions
#IBAction func simpleAction(send: AnyObject) {
self.presentViewController(self.logInViewController, animated: true, completion: nil)
}
}
The guy in video is using xcode 6 with swift 1.2, you are using xcode 7 with swift 2.0. Syntax has changed, you have to rewrite this line like this:
self.logInViewController.fields = [PFLogInFields.UsernameAndPassword,
PFLogInFields.LogInButton, PFLogInFields.SignUpButton,
PFLogInFields.PasswordForgotten, PFLogInFields.DismissButton]
Also note that you don't need to write typename prefix when assigning to variable:
self.logInViewController.fields = [.UsernameAndPassword, .LogInButton,
.SignUpButton, .PasswordForgotten, .DismissButton]