Is there a way to throw errors from firebase login to error handling? - swift

I have one class that i call RealTimeAPI and then the actual LoginViewController class and what i want to do is i want to add my register method in my RealtimeApi class and call register in my LoginView. But then i need to errorhandle in my LoginView so i need to throw the error from the completionhandler in the registerfunction RealtimeAPIs Createuser. is this possible or no? this is my code so far.
RealtimeAPIClass
import Foundation
import Firebase
enum RegisterError: Error
{
case IncompleteForm
case NonMatchingForm
case FirebaseError
}
class RealTimeApi
{
private let Reference: DatabaseReference! = Database.database().reference()
private var nilOrNot = [Bool]()
public var errorDescription: String?
func Register(FullName: String?, Username: String?, Email: String?, EmailVerification: String?, Password: String?, PasswordVerification: String? )
{
Auth.auth().createUser(withEmail: Email!, password: Password, completion: er, Error){
}
}
func Login(Username:String, Password: String)
{
}
func CheckLoggedinUser() -> Bool
{
let currentuser = Auth.auth().currentUser
if(currentuser == nil)
{
return false
}else{
return true
}
}
}
Loginview
import UIKit
import Firebase
class LogInV: UIViewController {
#IBOutlet weak var UsernameTxt: UITextField!
#IBOutlet weak var PasswordTxt: UITextField!
#IBOutlet var TextfieldRegistrationCollection: [UITextField]!
#IBOutlet weak var ImageView: UIView!
#IBOutlet weak var RegisterView: UIView!
#IBOutlet weak var RV_VerticalAlignmentConstraint: NSLayoutConstraint!
#IBOutlet weak var RegisterBtnO: UIButton!
var Data = RealTimeApi()
var TextFieldStyle = TextfieldStyling()
override func viewDidLoad() {
super.viewDidLoad()
TextFieldStyle.StylizeTextField(StylizedTextField: UsernameTxt)
TextFieldStyle.StylizeTextField(StylizedTextField: PasswordTxt)
for i in 0...TextfieldRegistrationCollection.count - 1 {
TextFieldStyle.StylizeTextField(StylizedTextField: TextfieldRegistrationCollection[i])
}
TextfieldValidation()
RV_VerticalAlignmentConstraint.constant += view.bounds.height
}
override func viewDidAppear(_ animated: Bool) {
RegisterBtnO.isEnabled = false
}
#IBAction func LoginButtons(_ sender: UIButton) {
switch sender.tag{
case 0:
break
case 1:
Slide()
break
default:
print("button not pressed")
break
}
}
func Slide()
{
UIView.animate(withDuration: 1, delay: 0, options: .curveEaseIn, animations: {
self.RV_VerticalAlignmentConstraint.constant -= self.view.bounds.height
self.view.layoutIfNeeded()
}, completion: nil)
}
#IBAction func RegisterBtn(_ sender: UIButton) {
}
//Validate textfields so that user register does not work for empty input
func TextfieldValidation()
{
for i in 0...TextfieldRegistrationCollection.count - 1
{
TextfieldRegistrationCollection[i].addTarget(self, action: #selector(LogInV.textFieldDidChange), for: UIControlEvents.editingChanged)
}
}
//selector function for controlling empty textfield
#objc func textFieldDidChange(){
var NoneIsEmpty = Int()
for i in 0...TextfieldRegistrationCollection.count - 1{
if let text = TextfieldRegistrationCollection[i].text, text.isEmpty == false {
NoneIsEmpty += 1
}
}
if(NoneIsEmpty == TextfieldRegistrationCollection.count)
{
RegisterBtnO.isEnabled = true
}else{
RegisterBtnO.isEnabled = false
}
NoneIsEmpty = 0
}
func showAlert(error: String)
{
let Erroralert = UIAlertController(title: "Error", message: error, preferredStyle: .alert)
Erroralert.addAction(UIAlertAction(title: "Dissmiss",style: .cancel ,handler: {action in
print("tapped actionbutton")
}))
present(Erroralert, animated: true)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
}
}
func UploadCustomerList(customer: Customer)
{
}
}
So basically i want to do something like this
Auth.auth().createUser(withEmail: Email!, password: Password, completion: User, Error){
throw Error
}

I have created a helper class with the following method:
func setupAlert(with title: String, with message: String?, viewController: UIViewController) {
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
let cancel = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alert.addAction(cancel)
viewController.present(alert, animated: true, completion: nil)
}
you must pass the viewcontroller in the parameter where you want to display the alert. Then you can also pass the error, which can be found in Auth.auth()

Related

Using UIEditMenuInteraction with UITextView

How can we use UIEditMenuInteraction with UITextView to customize menu and add more buttons?
Before iOS 16 I was using:
UIMenuController.shared.menuItems = [menuItem1, menuItem2, menuItem3]
Try this sample source:
class ViewController: UIViewController {
#IBOutlet weak var txtView: UITextView!
var editMenuInteraction: UIEditMenuInteraction?
override func viewDidLoad() {
super.viewDidLoad()
setupEditMenuInteraction()
}
private func setupEditMenuInteraction() {
// Addding Menu Interaction to TextView
editMenuInteraction = UIEditMenuInteraction(delegate: self)
txtView.addInteraction(editMenuInteraction!)
// Addding Long Press Gesture
let longPressGestureRecognizer =
UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress(_:)))
txtView.addGestureRecognizer(longPressGestureRecognizer)
}
#objc
func handleLongPress(_ gestureRecognizer: UILongPressGestureRecognizer) {
guard gestureRecognizer.state == .began else { return }
let configuration = UIEditMenuConfiguration(
identifier: "textViewEdit",
sourcePoint: gestureRecognizer.location(in: txtView)
)
editMenuInteraction?.presentEditMenu(with: configuration)
}
}
extension ViewController: UIEditMenuInteractionDelegate {
func editMenuInteraction(_ interaction: UIEditMenuInteraction,
menuFor configuration: UIEditMenuConfiguration,
suggestedActions: [UIMenuElement]) -> UIMenu? {
var actions = suggestedActions
let customMenu = UIMenu(title: "", options: .displayInline, children: [
UIAction(title: "menuItem1") { _ in
print("menuItem1")
},
UIAction(title: "menuItem2") { _ in
print("menuItem2")
},
UIAction(title: "menuItem3") { _ in
print("menuItem3")
}
])
actions.append(customMenu)
return UIMenu(children: actions) // For Custom and Suggested Menu
return UIMenu(children: customMenu.children) // For Custom Menu Only
}
}
Output

Trying to call a function in my code, not working

So I have created a function called startover1() and I am trying to call it in a different function, however, Xcode keeps saying there is an error.
I tried putting the function in different places, but it seems as though the function is not being read.
import Foundation
import UIKit
class BU: UIViewController {
let allBUSentences = BUSentenceBank()
var sentenceNumber2 : Int = 0
#IBOutlet weak var BUSentenceLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
let BUfirstQuestion = allBUSentences.list2[sentenceNumber2]
BUSentenceLabel.text = BUfirstQuestion.BUSentenceText
}
#IBOutlet var BUNextButton: UIButton!
#IBAction func BUNext2(_ sender: Any) {
sentenceNumber2 = sentenceNumber2 + 1
nextSentence()
}
func nextSentence() {
if sentenceNumber2 <= 19 {
BUSentenceLabel.text = allBUSentences.list2[sentenceNumber2].BUSentenceText
}
else{
let alert2 = UIAlertController(title: "Game Over", message: "Restart and keep drinking?", preferredStyle: .alert)
let restartAction2 = UIAlertAction(title: "Restart", style: .default) { (UIAlertAction) in self.startover1()
}
alert2.addAction(restartAction2)
present(alert2, animated: true, completion: nil)
}
func startover1() {
sentenceNumber2 = 0
nextSentence()
}
}
}
Hopefully it will recognize the method. The error is Value of type 'BU' has no member 'startover1'
The problem is that nextSentence is nested inside another func declaration. To make it work simply remove the declaration to outside of the previous function scope defined by the {brackets}. Check out:
import Foundation
import UIKit
class BU: UIViewController {
let allBUSentences = BUSentenceBank()
var sentenceNumber2 : Int = 0
#IBOutlet weak var BUSentenceLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
let BUfirstQuestion = allBUSentences.list2[sentenceNumber2]
BUSentenceLabel.text = BUfirstQuestion.BUSentenceText
}
#IBOutlet var BUNextButton: UIButton!
#IBAction func BUNext2(_ sender: Any) {
sentenceNumber2 = sentenceNumber2 + 1
nextSentence()
}
func nextSentence() {
if sentenceNumber2 <= 19 {
BUSentenceLabel.text = allBUSentences.list2[sentenceNumber2].BUSentenceText
}
else{
let alert2 = UIAlertController(title: "Game Over", message: "Restart and keep drinking?", preferredStyle: .alert)
let restartAction2 = UIAlertAction(title: "Restart", style: .default) { (UIAlertAction) in self.startover1()
}
alert2.addAction(restartAction2)
present(alert2, animated: true, completion: nil)
}
startover1() //This is not a declaration, but a call
}
//This is startover1 declaration
func startover1() {
sentenceNumber2 = 0
nextSentence()
}
}

How to make a correct authorization

i am making an app Redmine, i have a website with a user with pass and there are issues. But i can't understand what i should do to make authorization.
Here I have Router, Request, AuthViewController. I also wanted to ask how i have to make AuthRequest? What has to be there?
AuthViewController
import UIKit
class AuthViewController: UIViewController {
#IBOutlet weak var emailField: UITextField!
#IBOutlet weak var passwordField: UITextField!
#IBOutlet weak var signInBotton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func signInDidTap(_ sender: Any) {
login()
}
fileprivate func login(){
AuthRequest.login(email: emailField.text!, password: passwordField.text!){(user, error) in DispatchQueue.main.async {
[unowned self] in self.openIssues()
}
}
}
}
//extension AuthViewController: Router{
// func prepare() {
// Here error with 'seque' if(seque.identifier = Seque.issues.rawValue){
// print("It's OK")
// guard let controller = seque.destination as? IssuesViewController else { print("Wrong destination"); return}
// //controller.presenter = IssuesPresenter();
// }
// }
//
// func openIssues() {
// print("kek")
// }
//
//
// enum Seque: String {
// case issues = "IssuesSeque"
// }
//
//}
There is also an error in if-block in extension.

Automatically delete data from Firebase Database

I have seen some other questions asked but I am having trouble getting it to work. I have a Mac app coded in swift and it has a Firebase login but the user types a key in that is stored on Firebase, is there a way to automatically delete that key when the user has successfully used it?
This is my database.
This is the code that is used currently.
import Cocoa
import FirebaseAuth
import FirebaseDatabase
class LoginViewController: NSViewController {
#IBOutlet weak var textUsername: NSTextField!
#IBOutlet weak var textPassword: NSSecureTextFieldCell!
#IBOutlet weak var btnLogin: NSButton!
var keyArray = \[Int64\]()
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear() {
}
func getLoginState() -> Bool{
let state = UserDefaults.standard.bool(forKey: "isRegistered")
if (state) {
return true
} else {
return false
}
}
override func viewDidAppear() {
let state = self.getLoginState()
if (state){
self.performSegue(withIdentifier: NSStoryboardSegue.Identifier(rawValue: "loginsegue"), sender: nil)
self.view.window?.close()
}
var ref: DatabaseReference!
ref = Database.database().reference()
let keyRef = ref.child("key1")
keyRef.observe(DataEventType.childAdded, with: { (snapshot) in
// let postDict = snapshot.value as? \[String : AnyObject\] ?? \[:\]
let keyStr = snapshot.value as? Int64
if let actualPost = keyStr{
self.keyArray.append(actualPost)
}
})
}
#IBAction override func dismissViewController(_ viewController: NSViewController) {
dismiss(self)
}
#IBAction func close(sender: AnyObject) {
self.view.window?.close()
}
#IBAction func onSignup(_ sender: Any) {
// self.performSegue(withIdentifier: NSStoryboardSegue.Identifier(rawValue: "gotosignup"), sender: sender)
// self.view.window?.close()
}
func dialogOK(question: String, text: String) -> Void {
let alert: NSAlert = NSAlert()
alert.messageText = question
alert.informativeText = text
alert.alertStyle = NSAlert.Style.warning
alert.addButton(withTitle: "OK")
alert.runModal()
}
#IBAction func onLogin(_ sender: Any) {
//self.btnLogin.isEnabled = false
var isKey = false
if (!self.textUsername.stringValue.isEmpty) {
for key in keyArray{
if(Int64(self.textUsername.stringValue)! == key)
{
UserDefaults.standard.set(true, forKey:"isRegistered")
self.performSegue(withIdentifier: NSStoryboardSegue.Identifier(rawValue: "loginsegue"), sender: nil)
self.view.window?.close()
isKey = true
}
}
if (!isKey){
self.dialogOK(question: "Error", text: "Invalid Key")
}
} else {
self.dialogOK(question: "Error", text: "Please Input Key")
}
}
}
You can't sort your database like that and expect a working code, even if there's any. It will make a messy code:
You need to:
Sort your database like [1220:0]. the key first. 0 & 1 as an indicator if it's used or not.
Once the user taps onLogin() you need to set the used key value to 1
Setup Cloud Functions to check if the used key is equal to 1, if yes. then remove the key.
Do the rest of the work.
Related Articles to get you started:
Extend Realtime Database with Cloud Functions
functions.database.RefBuilder

FBLoginManager undeclared type

I installed FacebookSDK using Cocoapods, according to Terminal, I have installed FacebookSDK 4.8.0 (CoreKit, ShareKit and LoginKit), I imported the .h files in my BH-File.h, and already initialized everything in my AppDelegate.
For some reason, when trying to log in using a custom button, when I initialize FBLoginManager, I get an error Use of undeclared type "FBLoginManager".
this is my code
if (FBSDKAccessToken.currentAccessToken() == nil)
{
let fbLoginManager : FBSDKLoginManager =
fbLoginManager.logInWithReadPermissions(["public_profile", "email"], fromViewController: self, handler: { (loginResult, error) -> Void in
if error == nil {
print (FBSDKAccessToken.currentAccessToken().tokenString)
}
else {
print ("ERROR*****: \(error)")
}
})
}
What fixed to me was adding import FBSDKCoreKit and FBSDKLoginKit to my class, for some reason is not enough adding it in the BH-file.h
Try something like this, I just checked the code and it works (it's not exactly what you're looking for but I'm sure you can modify it as needed)
import UIKit
import FBSDKCoreKit
import FBSDKLoginKit
class ProfileViewController: UIViewController,FBSDKLoginButtonDelegate {
// #IBOutlet weak var nameLabel: UILabel!
#IBOutlet weak var nameLabel: UILabel!
#IBOutlet weak var imageView: UIImageView!
#IBOutlet weak var nextButton: UIButton!
#IBOutlet weak var fbLoginButton: FBSDKLoginButton!
override func viewDidLoad() {
super.viewDidLoad()
self.fbLoginButton.delegate = self
self.fbLoginButton.readPermissions = ["public_profile"]
self.fbLoginButton.publishPermissions = ["publish_actions"]
NSNotificationCenter.defaultCenter().addObserver(
self,
selector: "fbProfileChanged:",
name: FBSDKProfileDidChangeNotification,
object: nil)
FBSDKProfile.enableUpdatesOnAccessTokenChange(true)
// If we have a current Facebook access token, force the profile change handler
if ((FBSDKAccessToken.currentAccessToken()) != nil)
{
self.fbProfileChanged(self)
} }
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func prefersStatusBarHidden() -> Bool {
return true
}
//facebooks functions
func loginButton(loginButton: FBSDKLoginButton!, didCompleteWithResult result: FBSDKLoginManagerLoginResult!, error: NSError!) {
if (error != nil)
{
print( "\(error.localizedDescription)" )
}
else if (result.isCancelled)
{
// Logged out?
print( "Login Cancelled")
}
else
{
// Logged in?
print( "Logged in, segue now")
self.performSegueWithIdentifier("showHome", sender: self)
}
}
func loginButtonDidLogOut(loginButton: FBSDKLoginButton!) {
}
//see bitfountain
func fbProfileChanged(sender: AnyObject!) {
let fbProfile = FBSDKProfile.currentProfile()
if (fbProfile != nil)
{
// Fetch & format the profile picture
let strProfilePicURL = fbProfile.imagePathForPictureMode(FBSDKProfilePictureMode.Square, size: imageView.frame.size)
let url = NSURL(string: strProfilePicURL, relativeToURL: NSURL(string: "http://graph.facebook.com/"))
let imageData = NSData(contentsOfURL: url!)
let image = UIImage(data: imageData!)
self.nameLabel.text = fbProfile.name
self.imageView.image = image
self.nameLabel.hidden = false
self.imageView.hidden = false
self.nextButton.hidden = false
}
else
{
self.nameLabel.text = ""
self.imageView.image = UIImage(named: "")
self.nameLabel.hidden = true
self.imageView.hidden = true
}
}
#IBAction func nextButtonPressed(sender: UIButton) {
self.performSegueWithIdentifier("showHome", sender: self)
}
}