Delegate method called twice in Xcode 8.1/Swift 3.0 with debugger breakpoint -
i have problem xcode 8.1/swift 3. think might bug in debugger xcode software thought see if sees missing. working on ios application need override backspace method used uitextfield. setup delegate watch backspace key being pressed. program works until set debugger breakpoint in overridden method (see code below). when backspace method gets called twice each time press key instead of 1 time. if delete breakpoint code works. bug or doing wrong? here code help!
import uikit class viewcontroller: uiviewcontroller, eqfielddelegate { override func viewdidload() { super.viewdidload() let newfield = eqfield() newfield.mydelegate = self newfield.becomefirstresponder() view.addsubview(newfield) newfield.frame = cgrect(x: 50, y: 50, width: 200, height: 150) } func backspacepressed( ){ print("in backspacepressed") // breakpoint added here } }
here subclass of uitextfield:
import uikit class eqfield: uitextfield { var mydelegate: eqfielddelegate? override func deletebackward() { super.deletebackward() mydelegate?.backspacepressed() } } protocol eqfielddelegate { func backspacepressed() }
i have theory why happening.
to illustrate, imagine we're making our own button. should have following behavior mimic apple's:
- on touch down, call
backspacepressed
- after .5 seconds, if touch still down, call
backspacepressed
again - after every .1 seconds, if touch still down, call
backspacepressed
again
here's how implement it:
add end of
viewdidload
let button = uibutton(type: .system) button.settitle("tap me", for: .normal) button.addtarget(self, action: #selector(viewcontroller.handlebuttontouched(button:)), for: .touchdown) button.addtarget(self, action: #selector(viewcontroller.handlebuttonreleased(button:)), for: .touchupinside) button.frame = cgrect(x: 50, y: newfield.frame.maxy, width: 200, height: 150) view.addsubview(button)
add after
viewdidload
var buttontimer: timer? func handlebuttontouched(button: uibutton) { buttontimer = timer.scheduledtimer(withtimeinterval: 1.0, repeats: false, block: { [weak self] timer in print("button's been held down while!") self?.backspacepressed() self?.buttontimer = timer.scheduledtimer(withtimeinterval: 0.1, repeats: true, block: { (timer) in print("button's still held down") self?.backspacepressed() }) }) print("button pressed") // add breakpoint here self.backspacepressed() } func handlebuttonreleased(button: uibutton) { buttontimer?.invalidate() }
(optional) comment out log console matches mine experiment
func backspacepressed( ){ //print("in backspacepressed") }
without breakpoint, if tap , hold button, you'll logs printed following behavior outlined above:
button pressed button's been held down while! button's still held down button's still held down button's still held down button's still held down
if tap button (don't hold it), you'll get
button pressed
however, if set breakpoint, tap button, , wait second after breakpoint hits before pressing continue, 2 logs:
button pressed button's been held down while!
you'd think, since didn't hold button long enough, wouldn't second log. what's happening timer ticking down though you're stopped on breakpoint, , when execution returns program, result of timer evaluated before button release evaluated.
i'm not sure why things happen in order - why can't button release handled before timer event? can see in normal execution without breakpoint, it's not question of happens first - short button tap cause handlebuttonreleased called before timer can go off.
i suspect in case, apple's keyboard doing similar, , you're setting breakpoint that's holding touch in stasis while timer somewhere decides yes, indeed long press! though isn't. don't have workaround, shines light on what's happening.
Comments
Post a Comment