firebase authentication ios use of unresolved identifier 'handle' - ios

I'm trying to follow this tutorial for Firebase authentication.. I kinda just followed the code but keep having the Use of unresolved identifier 'handle' error.
Code:
import UIKit
import Firebase
import FirebaseAuth
class SignInViewController: UIViewController {
override func viewWillAppear(_ animated: Bool) {
handle = Auth.auth().addStateDidChangeListener { (auth, user) in // ERROR HERE
// ...
}
}
override func viewWillDisappear(_ animated: Bool) {
Auth.auth().removeStateDidChangeListener(handle!) // ERROR HERE
}
}
Any clue what I should do? Thanks!
#IBAction func createAccount(_ sender: Any) {
let emailTextD = self.emailText.text!
let passwordTextD = self.passwordText.text
Auth.auth().createUser(withEmail: emailTextD, password: passwordTextD!) { (authResult, error) in
// ...
}
}

Add the variable declaration into the class like this:
var handle: AuthStateDidChangeListenerHandle?

Related

Cannot load module 'visionKit' as 'VisionKit'

Im trying to build a simple app to scan documents, but faced this error when trying to import VisionKit module, how can i solve this error ?
My code:
import UIKit
import VisionKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBAction func openCameraButtonTaped(_ sender: Any) {
configureDocumentView()
}
private func configureDocumentView() {
let scaningDocumentViewController = VNDocumentCameraViewController()
scaningDocumentViewController.delegate = self
self.present(scaningDocumentViewController, animated: true, completion: nil)
}
}
extension ViewController: VNDocumentCameraViewControllerDelegate {
func documentCameraViewController(_ controller: VNDocumentCameraViewController, didFinishWith scan: VNDocumentCameraScan) {
for pageNum in 0..<scan.pageCount {
let image = scan.imageOfPage(at: pageNum)
print(image)
}
controller.dismiss(animated: true, completion: nil)
}
}
You are giving a hard time for the compiler, your project name conflicts with Apple's VisionKit. Create a new your project with a different name.

Redirect the user to a specific page after signIn

Main issue is checking if user has a child in the Firebase database so that I know if he is signing up or logging in.
Part 1: Part 1 (Child Database (this works) and making that a user default (I'm not sure how to check it that worked)
Part 2: in different .Swift file (Check if the User Default (aka Education Child) exists. I have pretty much nothing, except I know it must go into viewDidAppear
Part 1
#IBAction func SubmitPressed(_ sender: Any) {
let databaseRef = Database.database().reference()
let uid = Auth.auth().currentUser!.uid
databaseRef.child("Education").child(uid).setValue(self.Education.text!)
UserDefaults.standard.set("Education", forKey: "Education")
Part 2
func viewDidAppear(_ animated: String) {
??????
}
No error for part 1, though not sure if it created the user default. For part 2, I have tried a bunch of stuff, but hasn't worked.
Here is the updated code after first answer:
import Foundation
import UIKit
import SwiftKeychainWrapper
import Firebase
import CoreFoundation
import AVFoundation
import FirebaseDatabase
var educationCache : String {
get {
return (UserDefaults.standard.string(forKey: "Education")!)
} set {
UserDefaults.standard.set(newValue, forKey: "Education")
}
}
relavant part of education/personal info enter page
#IBAction func SubmitPressed(_ sender: Any) {
let databaseRef = Database.database().reference()
let uid = Auth.auth().currentUser!.uid
databaseRef.child("Education").child(uid).setValue(self.Education.text!)
// The following line will save it in userDefault itself. And you dont have to call the whole UserDefault Everywhere
educationCache = "Education"
self.performSegue(withIdentifier: "tohome", sender: nil)
}
homepage
import Foundation
import UIKit
import SwiftKeychainWrapper
import Firebase
import CoreFoundation
import AVFoundation
import FirebaseDatabase
class homepage:UITableViewController {
override func viewDidAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if educationCache.count < 0 {
self.performSegue(withIdentifier: "toFeed", sender: nil)
}
}
override func viewDidLoad() {
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Sign Out", style: .plain, target: self, action: #selector(signOut))
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#objc func signOut (_sender: AnyObject) {
KeychainWrapper.standard.removeObject(forKey: "uid")
do {
try Auth.auth().signOut()
} catch let signOutError as NSError {
print ("Error signing out: %#", signOutError)
}
dismiss(animated: true, completion: nil)
}
}
You dont want to check the condition is the viewController where you are performing specific actions. Also checking the userDefaults everytime is just putting extra views in heirarchy. Firebase provides .addStateDidChangeListener function to keep a check of it. Add the following code to your delegate. It will automatically switch between the users if there are any or not.
AppDelegate.swift
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
observeUser()
return true
}
func observeUser(){
Auth.auth().addStateDidChangeListener { (auth, user) in
if (user != nil) {
// If the user is not nil. Perform this block
self.showInitController(with identifier: "<add_your_storyboard_reusableID_for_homepage>", animated: false)
// The storyboard Id belongs to the HOMEPAGE/FEED, the view where user goes on signIn
} else {
//If there is no user. This block will perform
self.showInitController(with identifier: "<add_your_storyboard_reusableID_for_loginpage>", animated: false)
// The storyboard Id belongs to the SIGNUP PAGE, the view where user goes on signIn
}
}
}
func showInitController(with identifier: String, animated: Bool = false) {
DispatchQueue.main.async {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: identifier)
var topRootViewController: UIViewController = (UIApplication.shared.keyWindow?.rootViewController)!
while((topRootViewController.presentedViewController) != nil){
topRootViewController = topRootViewController.presentedViewController!
}
topRootViewController.present(vc, animated: animated, completion: nil)
}
}
In your swift file one. do the following and never look back. You can automatically redirect to view if you applied the other functions.
#IBAction func SubmitPressed(_ sender: Any) {
let databaseRef = Database.database().reference()
let uid = Auth.auth().currentUser!.uid
databaseRef.child("Education").child(uid).setValue(self.Education.text!)
self.performSegue(withIdentifier: "tohome", sender: nil)
}
In the second view dont bother to do anything anywhere. Just leave it, if nothing in that view is required again.

App crashes with Firebase Phone Auth

I hope that this question is not duplicate because I couldn't find any thing similar.
I have two view controllers:
NEWPhoneAuthViewController
NEWVerifyCodeViewController
NEWPhoneAuthViewController Code:
import UIKit
import Firebase
class NEWPhoneAuthViewController: UIViewController {
#IBOutlet weak var phoneTxtField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func submitPressed(_ sender: Any) {
let phoneNumber = phoneTxtField.text!
PhoneAuthProvider.provider().verifyPhoneNumber(phoneNumber, uiDelegate: nil, completion: { (verificationID, error) in
if let error = error {
debugPrint(error.localizedDescription)
return
}
guard let verificationID = verificationID else { return }
print("Verification ID")
print(verificationID)
let verifyScene = NEWVerifyCodeViewController()
verifyScene.verificationID = verificationID
self.performSegue(withIdentifier: "toCodefromPhoneAuth", sender: nil)
//self.navigationController?.pushViewController(verifyScene, animated: true)
})
}
}
and my NEWVerifyCodeViewController code is:
import UIKit
import Firebase
class NEWVerifyCodeViewController: UIViewController {
#IBOutlet weak var codeTxtField: UITextField!
var verificationID:String?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func verifyPressed(_ sender: Any) {
if let verificationCode = codeTxtField.text {
let credential = PhoneAuthProvider.provider().credential(withVerificationID: verificationID!, verificationCode: verificationCode)
Auth.auth().signIn(with: credential) { (user, error) in
if let error = error {
debugPrint(error.localizedDescription)
}else {
debugPrint("Verified successfully")
print("Navigating to SignUp")
//self.performSegue(withIdentifier: "toSignUpfromCode", sender: nil)
//let newSignUp = NEWSignUp()
//self.navigationController?.pushViewController(newSignUp, animated: true)
//self.performSegue(withIdentifier: "toSignUpFromPhone", sender: nil)
//Once you have verified your phone number kill the firebase session.
//try? Auth.auth().signOut()
}
}
}
}
}
Now the problem is: when I tap on verify button in NEWVerifyCodeViewController the App crashes,
NOTES:
I printed Verification ID and its not NULL.
I printed code that the user receives and its not NULL.
So I'm not sure why that happens, and my console doesn't show any error after the tap except these:
So I made a small tweak that made my project work.
I changed this part in NEWPhoneAuthViewController :
let verifyScene = NEWVerifyCodeViewController()
verifyScene.verificationID = verificationID
to:
first created a global variable called: gVerificationID and set it to:
gVerificationID = verificationID
Thats it, not sure if thats the best practice and not sure why the first code didn't work but this is how I fixed it.

FirebaseViewController is black

when following the instructions for FirebaseUI to display the LoginViewController it only shows a black screen.
As you can see it kind of replaces the current viewcontroller instead of presenting it.
Here is the code from the presenting viewcontroller
import UIKit
import Firebase
import FirebaseUI
class FirstViewController: UIViewController {
#IBOutlet weak var logoutButton: UIButton!
var rootRef = Firebase(url: Constants.FireBaseUrl)
var loginViewController: FirebaseLoginViewController!
override func viewDidLoad() {
super.viewDidLoad()
loginViewController = FirebaseLoginViewController(ref: rootRef)
loginViewController.enableProvider(.Facebook)
loginViewController.enableProvider(.Password)
loginViewController.didDismissWithBlock { (user: FAuthData!, error: NSError!) -> Void in
if (user != nil) {
// user
} else if (error != nil) {
// error
} else {
// cancel
}
}
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
if (loginViewController.currentUser() == nil) {
presentViewController(loginViewController, animated: true, completion: nil)
}
}
// MARK: - Actions
#IBAction func logoutTouched(sender: AnyObject) {
rootRef.unauth()
}
}

New to testing with swift (quick/nimble), trying to get past oauth screen

I'm attempting to write a quick/nimble test that will just confirm a few things on the screen after my opening screen. The opening screen is simply a button which leads to oauth2 sign in to validate users. I'm just wondering how it is I can spoof a sign in so that I can get to the next screen. I know this is probably not a lot of information but I'm really new to the testing aspect of swift as a whole but I know it's very important to have unit tests.
Here is code that might help:
import UIKit
class ViewController: UIViewController, GIDSignInDelegate, GIDSignInUIDelegate {
#IBOutlet weak var signInButton: GIDSignInButton!
#IBOutlet weak var errorLabel: UILabel!
var googleViewController: GoogleViewController!
var permittedList:[String] = ["me#mysite.com"]
let env = NSProcessInfo.processInfo().environment
override func viewDidLoad() {
self.view.backgroundColor = UIColor(rgb: 0x6a737b)
super.viewDidLoad()
GIDSignIn.sharedInstance().delegate = self
GIDSignIn.sharedInstance().uiDelegate = self
GIDSignIn.sharedInstance().clientID = env["CLIENT_ID"] as? String
GIDSignIn.sharedInstance().signInSilently()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "googledisplay" {
googleViewController = segue.destinationViewController as! GoogleViewController
}
}
func signIn(signIn: GIDSignIn!, didSignInForUser user: GIDGoogleUser!, withError error: NSError!) {
if let err = error {
println(error)
}
else {
if !contains(permittedList, GIDSignIn.sharedInstance().currentUser.profile.email) {
GIDSignIn.sharedInstance().signOut()
GIDSignIn.sharedInstance().disconnect()
self.errorLabel.text = "You must sign in with a permitted email address"
}
else{
self.errorLabel.text = ""
performSegueWithIdentifier("googledisplay", sender: self)
}
}
}
}
test:
import Foundation
import Quick
import Nimble
import PasswordRecovery
class PasswordViewControllerSpec: QuickSpec {
var viewController = PasswordViewController()
override func spec() {
let _ = PasswordViewController().view
viewController.setNewEmail("s#s.com")
viewController.setNewLRA("unknown")
viewController.reset_code(t: 1447267160)
expect(self.viewController.getLRA()).to(equal("LRA"))
}
}
PasswordViewController is the name of the view which is loaded after the original screen. Thank you for any help, if there is anything more needed please tell me!

Resources