Value of type '[Users]' has no member 'username' - swift

I'm trying to create a simple user login ViewController that connects to a database full of user information for my app but I get the error stated in the title.
import UIKit
import Alamofire
class Users: Decodable {
let username: String
let email: String
let password: String
init(username: String, email: String, password: String) {
self.username = username
self.email = email
self.password = password
}
class LoginVC: UIViewController {
var loggingin = [Users]()
#IBOutlet weak var usernameTxtField: UITextField!
#IBOutlet weak var passwordTxtField: UITextField!
#IBOutlet weak var checkCredsBtn: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let jsonURL = "http://host-2:8888/getLogin.php"
let url = URL(string: jsonURL)
URLSession.shared.dataTask(with: url!) { (data, response, error) in
do {
self.loggingin = try JSONDecoder().decode([Users].self, from: data!)
for eachUser in self.loggingin {
print(eachUser.username + " : " + eachUser.password)
}
}
catch {
print("Error")
}
}.resume()
}
#IBAction func checkCreds(_ sender: Any) {
if usernameTxtField == loggingin.username && passwordTxtField == loggingin.password {
print("YES")
}
}
}
}

The reason of this compile time error appears in checkCreds function, you are trying to access the username and password properties directly from the array which is obviously incorrect. What you should do instead is to get the desired object from loggingin array and do comparing with its properties:
#IBAction func checkCreds(_ sender: Any) {
let currentUser = loggingin[0]
if usernameTxtField == currentUser.username && passwordTxtField == currentUser.password {
print("YES")
}
}
In the above example, I just got the first object; I would assume that you already able to get the desired object currentUser (what's the used index) for getting the object from the loggingin.

Related

How do I access the variables that google provides outside of the function?

i'm trying to access the emailAddress variable in a different view controller however its always not in scope.
i want to call something like
login.emailAddress
in a different vc.
heres my code for your refeerence, i understand that there are similar questions however i struggle to translate that into my code. .
import UIKit
import GoogleSignIn
let login = LoginController()
class LoginController: UIViewController {
#IBOutlet weak var signInButton: GIDSignInButton!
let signInConfig = GIDConfiguration(clientID: "12345-abcdef.apps.googleusercontent.com")
#IBAction func signIn(_ sender: Any) {
GIDSignIn.sharedInstance.signIn(with: signInConfig, presenting: self) { user, error in
guard error == nil else { return }
guard let user = user else { return }
var emailAddress = user.profile?.email
var fullName = user.profile?.name
var givenName = user.profile?.givenName
var familyName = user.profile?.familyName
var profilePicUrl = user.profile?.imageURL(withDimension: 320)
let userProfile = (fullName, givenName, emailAddress, profilePicUrl)
print("Sign in Sucessfull")
print(fullName!)
print(givenName!)
print(familyName!)
print(emailAddress!)
print(profilePicUrl!)
// If sign in succeeded, display the app's main content View.
let vc = self.storyboard?.instantiateViewController(withIdentifier: "NavigationViewController") as! UINavigationController
self.navigationController?.pushViewController(vc, animated: true)
self.present(vc, animated: true, completion: nil)
}
}
}
An option would be storing the value in a class property:
class LoginController: UIViewController {
#IBOutlet weak var signInButton: GIDSignInButton!
private var userMail: String?
let signInConfig = GIDConfiguration(clientID: "12345-abcdef.apps.googleusercontent.com")
#IBAction func signIn(_ sender: Any) {
GIDSignIn.sharedInstance.signIn(with: signInConfig, presenting: self) { user, error in
guard error == nil else { return }
guard let user = user else { return }
self.userMail = user.profile?.email
[...]
}
}
}

Problem with empty value of variable in SWIFT

I'm making simple app- single view app with segues. I've create a model with few variables:
import Foundation
class ActualValues {
var id: String = "ID:"
var product: String?
var issue: String?
In deferent view controller I can change and save value of this (for example id):
class LoginViewController: UIViewController {
var workModel: ActualValues?
var closureBlock: (() -> Void)?
#IBOutlet weak var idTextField: UITextField!
#IBOutlet weak var idCheckButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func idCheckButtonDidPress(_ sender: UIButton) {
workModel?.id = "ID: \(idTextField.text!)"
closureBlock?()
self.dismiss(animated: true, completion: nil)
}
func configureID(model: ActualValues) {
workModel = model
}
}
And now, I want to take my variable "id" value and send it to the server. If I do that, the value of id is empty. And this is my problem. I created func in other model:
func startSending() {
db.collection("\(currentMonth())").document("Damian").collection("Michal").addDocument(data: [
"ID": "\(String(describing: av.id))",
"Start": "\(currentDate())",
"Product": "\(String(describing: av.product))"
]) { err in
if let err = err {
print("Error writing document: \(err)")
} else {
print("Document successfully written!")
}
}
Anyone can help me? Problem is because I can't send id value to the server- id is empty.
PS: I've used closure becouse I had a problem with display actual id in label on my HomeViewController.
You should create an instance of ActualValues for workModel first. Now your workModel is nil and you can't add an id to your property (workModel). You can set a breakpoint to idCheckButtonDidPress and print workModel to see if it is nil.
Your ActualValues class must be like ->
class ActualValues {
var id: String
var product: String?
var issue: String?
init(id: String, product: String?, issue: String?) {
self.id = id
self.product = product
self.issue = issue
}
}
And then you should call configureID with new model ->
#IBAction func idCheckButtonDidPress(_ sender: UIButton) {
let model = ActualValues(id: "ID: \(idTextField.text!)", product: nil, issue: nil)
configureID(model: model)
closureBlock?()
dismiss(animated: true)
}
Now you have an instance of ActualValues and we added id into it. You can use workModel to send the object.

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

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()
}
}

Getting data from Parse as “Optional(test)” and want to do something with that “test” part

I am new to Parse and I am trying to retrieve my first password (my password is: test). But I can only receive it as “Optional(test)”. The “test” there is actually the password that I want to receive but I can’t get it out of the paranthesis. My code is as follows;
import UIKit
import Parse
import Bolts
class ViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var userNameTextField: UITextField!
#IBOutlet weak var passwordTextField: UITextField!
#IBOutlet weak var credentialsLabel: UILabel!
#IBAction func checkCredentialsButton(sender: AnyObject) {
var query = PFQuery(className:"userName")
query.getObjectInBackgroundWithId("the id of my object") {
(userNameRetrieved: PFObject?, error: NSError?) -> Void in
if error == nil && userNameRetrieved != nil {
println(userNameRetrieved)
println("Username has been retrieved succesfully")
println(userNameRetrieved?.objectForKey("username"))
} else {
println(error)
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.userNameTextField.delegate = self
self.passwordTextField.delegate = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func textFieldShouldReturn(userText: UITextField) -> Bool {
userNameTextField.resignFirstResponder()
passwordTextField.resignFirstResponder()
return true
}
}
And my logs are as follows;
Optional(<userName: "my username", objectId: “the id that i am using", localId: (null)> {
ACL = "<PFACL: “my acl">";
username = test;
})
Username has been retrieved succesfully
Optional(test)
Is there a way for me to use that password to log my user in?
Also, is there a way for me to retrieve an array of passwords that are registered to check if the password is true or not?
use if let to unwrap the optional
#IBAction func checkCredentialsButton(sender: AnyObject) {
var query = PFQuery(className:"userName")
query.getObjectInBackgroundWithId("the id of my object") {
(userNameRetrieved: PFObject?, error: NSError?) -> Void in
if error == nil && userNameRetrieved != nil {
if error == nil && userNameRetrieved != nil {
if let userArray = userNameRetrieved {
print(userArray)
if let username = userNameRetrieved?.objectForKey("username") {
print(username)
}
}
} else {
println(error)
}
}
}