简体   繁体   中英

NSTimer stops after a few seconds

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM