-2

I'm making a social media app and one of the features in the sign up screen is it checks if the username is taken in real time and puts an X or Check if it's taken (again in real time). I use a timer to accomplish this but for some reason the timer stops after a few seconds. What's going on? And is there a better way of going about doing this?

override func viewDidLoad() {
    username.delegate = self
    email.delegate = self
    password.delegate = self
    var timer = NSTimer()
    timer = NSTimer.scheduledTimerWithTimeInterval(0.01, target: self, selector: Selector("checkOrX"), userInfo: nil, repeats: true)
}

func checkOrX() {
    var query = PFQuery(className: "_User")
    query.whereKey("username", equalTo: self.username.text)
    query.findObjectsInBackgroundWithBlock { (users, error) -> Void in
        if let users = users {
            self.usernameCheck.image = UIImage(named: "X.png")
        } else {
            self.usernameCheck.image = UIImage(named: "Check.png")
        }
    }
}
luk2302
  • 55,258
  • 23
  • 97
  • 137
  • woah, i doubt parse will appreciate that request spam. In what way does the timer "stop"??? Have you added a logging statement? – luk2302 Aug 29 '15 at 16:57
  • What do you mean a logging statement? – Ethan Cotler Aug 29 '15 at 17:00
  • 1
    logging statement: `print("in checkOrX")` in the method. Spend some time reading about debugging, you will be doing a lot of it, we all do. – zaph Aug 29 '15 at 17:01
  • you did not just seriously ask what I mean with logging :O :'((( – luk2302 Aug 29 '15 at 17:01
  • 2
    It might be more effective to check only if the content of the text field changes – there are notifications for that purpose – rather than 100 times a second. – vadian Aug 29 '15 at 17:03
  • @luke2302 Oh I know what a logging statement is. I actually did a lot of that during this. And found out that it stopped printing to the logs. – Ethan Cotler Aug 29 '15 at 17:03
  • @vadian How would I do that? – Ethan Cotler Aug 29 '15 at 17:04
  • observe `UITextFieldTextDidChangeNotification` – vadian Aug 29 '15 at 17:05
  • @vadian How would I use that? Would I implement that in my timer or what? – Ethan Cotler Aug 29 '15 at 17:09
  • please read the documentation about text programming: https://developer.apple.com/library/ios/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/Introduction/Introduction.html section Managing Text Fields and Text Views – vadian Aug 29 '15 at 17:10

1 Answers1

5

Instead of sending 100 requests a second which is bad for multiple reasons, you should send a request at most every time the user changes the actual user name.

Why your current solution is bad:

  • You send too many requests - period
  • You send the same request most times over and over again
  • You might get banned from parse for spamming this much
  • You cause far too much network traffic, assume someone on mobile internet is filling out the login form for 5-10 seconds, getting distracted and having the app open for 1 minute or so, I personally would not be happy to loose a few megabytes for only that.

What you could do:

  • send the request after every change the user makes to his username (use this question & answer and combine it with your checkOrX)
  • as soon as you send a new request, cancel previously sent requests that have not finished your current
  • wait for tiny pauses of the user - if he does not type a new character for 0.1 seconds and only then query the server
  • only send the request if the user tries to submit the form
  • only send the request if the user focuses another form element
  • etc.

An example version of the first "solution" would probably look like

func viewDidLoad() {
    // ...
    self.username.addTarget(self, action: "textFieldDidChange:", forControlEvents: UIControlEvents.EditingChanged)
}

func textFieldDidChange(textField: UITextField) {
    if textField == self.username {
        checkOrX()
    }
}
Community
  • 1
  • 1
luk2302
  • 55,258
  • 23
  • 97
  • 137