2

I am new in Swift. I have small application which checks if phone number appears more than 1 in the same day, then my application should stop and error out

I tried few ways but it looks to me that the code skips the part which checks phone number in the same day and moves to next step.

import UIKit
import Firebase
//import FirebaseAuth
//import FirebaseDatabase
var ref_login: DatabaseReference!
var refTransaction: DatabaseReference!
var refcustomerdetails: DatabaseReference!
var refcountcheckin: DatabaseReference!
var CustomerName =    String()
class ViewController: UIViewController {



    @IBOutlet weak var nameText: UITextField!

    @IBOutlet weak var nameLabel: UILabel!
    @IBOutlet weak var phoneText: UITextField!
    @IBOutlet weak var errorText: UILabel!


    override func viewDidLoad() {
        super.viewDidLoad()


        ref_login = Database.database().reference()



        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    @IBAction func loginPressed(_ sender: Any) {
        if self.phoneText.text == "" {
        print("Phone is empty")
        self.errorText.text = "Phone is empty."
        return
        }

        if self.phoneText.text == "000000000" {
            switchownerScreen()
        }
        else {
                    Auth.auth().signIn(withEmail: phoneText.text! + "@gmail.com", password: "fingerjoynails", completion: {(user, error) in
                        if error != nil {
                            print(error)
                            self.errorText.text = "Phone does not exist in system."
                            return
                        }
                        if error == nil {
                            print("self.phoneText.text!",self.phoneText.text!)
                            //Start checking duplicate checking in the same day
                            //Start Date to query
                            let dformatter = DateFormatter()
                            dformatter.dateFormat = "yyyy-MM-dd"
                            let dmyString = dformatter.string(from: Date())
                            let dyourDate = dformatter.date(from: dmyString)
                            dformatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
                            let dmyStringafd = dformatter.string(from: dyourDate!)
                            print("dmyStringafd:------",dmyStringafd)

                            refcountcheckin = Database.database().reference().child("Transactions")
                            let query = refcountcheckin.queryOrdered(byChild: "CHECK_IN_DATE").queryStarting(atValue: dmyStringafd)
                            query.observe(.value, with: { (snapshot) in
                                print("snapshot.childrenCount:----",snapshot.childrenCount)
                                if snapshot.childrenCount>0{
                                    for transactions in snapshot.children.allObjects as![DataSnapshot]{
                                        let transactionObject = transactions.value as? [String: AnyObject]
                                        let transactionPhone = transactionObject?["PHONE"]
                                        let checkPhone = transactionPhone as! String?
                                        print("self.phoneText.text!",self.phoneText.text!)
                                        if checkPhone == self.phoneText.text! {
                                            self.errorText.text = "You already checked in on today."
                                            print("You already checked in on today.")
                                            return
                                        }

                                    }
                                }
                            })
                            //End checking duplicate checking in the same day

                            let phone = self.phoneText.text!
                            //let name = self.nameText.text!
                            let formatter = DateFormatter()
                            // initially set the format based on your datepicker date / server String
                            formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
                            let myString = formatter.string(from: Date()) // string purpose I add here
                            // convert your string to date
                            let yourDate = formatter.date(from: myString)
                            //then again set the date format whhich type of output you need
                            formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
                            // again convert your date to string
                            let myStringafd = formatter.string(from: yourDate!)
                            refcustomerdetails = Database.database().reference().child("Users")
                            let customerdetailsquery = refcustomerdetails.queryOrdered(byChild: "PHONE").queryEqual(toValue: self.phoneText.text!)
                            customerdetailsquery.observe(.value, with: { (snapshot) in
                                if snapshot.childrenCount>0{
                                    for transactions in snapshot.children.allObjects as![DataSnapshot]{
                                        let customerdetailsObject = transactions.value as? [String: AnyObject]
                                        let customerFirstName = customerdetailsObject?["FIRST_NAME"]
                                        let customerLastName = customerdetailsObject?["LAST_NAME"]
                                        let firstname   = customerFirstName as! String?
                                        let lastname = customerLastName as! String?
                                        CustomerName = firstname! + " " + lastname!
                                    }
                                }
                            })
                            ref_login?.child("Transactions").childByAutoId().setValue(["PHONE": phone, "NAME": CustomerName,"CHECK_IN_DATE": myStringafd, "GIFT_CARD_NUMBER": "N"])
                            print("Insert into transaction complete.")
                            self.switchScreen()
                        }
                    })
            }
    }

    func switchScreen() {
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        let controller = storyboard.instantiateViewController(withIdentifier: "usersVC")
        self.present(controller, animated: true, completion: nil)
    }

    func switchownerScreen() {
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        let controller = storyboard.instantiateViewController(withIdentifier: "ownerVC")
        self.present(controller, animated: true, completion: nil)
    }

    func assignbackground(){
        let background = UIImage(named: "login.jpg")

        var imageView : UIImageView!
        imageView = UIImageView(frame: view.bounds)
        imageView.contentMode =  UIViewContentMode.scaleAspectFill
        imageView.clipsToBounds = true
        imageView.image = background
        imageView.center = view.center
        view.addSubview(imageView)
        self.view.sendSubview(toBack: imageView)
    }



}

On the log I can see application inserts record before checking existing condition. My goal is if the phone number is already inserted in transaction table on today, we should NOT allow end user to insert it again.

Log file:

2019-01-20 16:02:50.096558-0800 checkinuser[8558:381633] [BoringSSL] nw_protocol_boringssl_get_output_frames(1301) [C4.1:2][0x7ff55fe02870] get output frames failed, state 8196
2019-01-20 16:02:50.096717-0800 checkinuser[8558:381633] [BoringSSL] nw_protocol_boringssl_get_output_frames(1301) [C4.1:2][0x7ff55fe02870] get output frames failed, state 8196
self.phoneText.text! 4088584842
2019-01-20 16:02:50.097999-0800 checkinuser[8558:381633] TIC Read Status [4:0x0]: 1:57
2019-01-20 16:02:50.098397-0800 checkinuser[8558:381633] TIC Read Status [4:0x0]: 1:57
dmyStringafd:------ 2019-01-20 00:00:00
Insert into transaction complete.
snapshot.childrenCount:---- 10
self.phoneText.text! 4088584842
You already checked in on today.
2019-01-20 16:02:50.260980-0800 checkinuser[8558:381633] 5.15.0 - [Firebase/Database][I-RDB034028] Using an unspecified index. Your data will be downloaded and filtered on the client. Consider adding ".indexOn": "CHECK_IN_DATE" at /Transactions to your security rules for better performance
rmaddy
  • 314,917
  • 42
  • 532
  • 579
Hieu Le
  • 21
  • 2

2 Answers2

0

You are missing some asynchronous understanding.

You can start by taking a look at this answer: https://stackoverflow.com/a/46245943/8869493

The fact that is "not in sequence" is intentional, those are asynchronous tasks.

Gustavo Vollbrecht
  • 3,188
  • 2
  • 19
  • 37
0

This is because you are running a query, which takes time, and you are trying to block the insert if there is a duplicate by running return inside of the function. This means that if the query does not process and reach the return statement before the rest of the method can execute, the return statement will not have time to execute. As the other answer mentioned, using a completion handler is probably the right move, but you may also just be able to move all the logic after your duplicate check into an else statement accompanying if checkPhone == self.phoneText.text!, or move it to a new function, and call that function from there:

if checkPhone == self.phoneText.text! {
    self.errorText.text = "You already checked in on today."
    print("You already checked in on today.")
}else{
    self.yourNewInsertPhoneNumberFucntion()
}
Sam Hollenbach
  • 652
  • 4
  • 19