ios - Why are my UI elements not resetting correctly after being animated/scaled off screen? -
so i'll give information project can right front. here image of section of storyboard relevant issue:
and here flow of code:
1) user plays game. scrambles emoji displayed , hide of emoji on right side.
2) when wins game, calls
performsegue(withidentifier: "showwinscreensegue", sender: self)
which perform segue red arrow pointing to. segue modal segue, on current content, cross dissolve.
3) stuff goes on here, , try game screen user can play game. here current code that
// self.delegate gamecontroller called segue // it's set somewhere else in code can call these reset functions gamecontroller.gs = gamestate() guard let d = self.delegate else { return } d.resetgametomatchstate() dismiss(animated: true, completion: { print("modal dismiss completed") gamecontroller.gs = gamestate() self.delegate?.resetgametomatchstate() })
so here's issue is. can see have call delegate?.resetgametomatchstate()
twice happen. if remove top one, nothing happens when call second 1 , vice-versa. makes annoying user see weird jump ui goes old state new state because it's updating late , spastically.
what i've tried far
whole issue has made me confused on how ui system works.
my first thought maybe function trying update ui in thread that's executing ui thread. put whole body of resetgametomatchstate
in dispatchqueue.main.async
call. didn't anything.
then thought working before because when winscreensegue being dismissed before (when "show" segue) calling gamecontroller
's viewdidappear
. tried manually calling function in dismiss callback, didn't work either , feels hacky.
and i'm stuck :( totally appreciated. if it's little info can clear how ui system works.
here resetgametomatchstate():
//reset emoji labels func resetgametomatchstate() { dispatchqueue.main.async { let tier = gamecontroller.gs.tier var = 0 emoji in self.currentemojilabels! { emoji.frame = self.currentemojilabelinitframes[i] emoji.ishidden = false emoji.transform = cgaffinetransform(scalex: 1, y: 1); i+=1 } i=0 emoji in self.goalemojilabels! { emoji.frame = self.goalemojilabelinitframes[i] emoji.ishidden = false emoji.transform = cgaffinetransform(scalex: 1, y: 1); i+=1 } //match state in 1...4 { if gamecontroller.gs.currentemojis[i] == gamecontroller.gs.goalemojis[i] { self.currentemojilabels?.findbytag(tag: i)?.ishidden = true } } //reset highlight let f = self.highlightbarinitframe let currentlabel = self.goalemojilabels?.findbytag(tag: tier) let newsize = cgrect(x: f.origin.x, y: (currentlabel?.frame.origin.y)!, width: f.width, height: (currentlabel?.frame.height)! ) self.highlightbarimageview.frame = newsize //update taps self.updatetapui() //update goal , current emojis show current goal/current selected emoji self.updategoalemojilabels() self.updatecurrentemojilabels() } }
update
found out. thing isn't working when try reset ui resetting right side emoji original positions. @ start of app (in viewdidload) run this:
for emoji in currentemojilabels! { currentemojilabelinitframes.append(emoji.frame) }
this saves original positions used later. because animate them side of screen before hiding them.
when want reset positions, this:
var = 0 emoji in self.currentemojilabels! { emoji.frame = self.currentemojilabelinitframes[i] emoji.ishidden = false emoji.transform = cgaffinetransform(scalex: 1, y: 1); i+=1 }
this should set them original frame , scale, doesn't set position correctly. reset scale though. what's weird can see tiny bit of 1 of emoji off left of screen , when animate, animate far off on left. i'm trying think of why frames off...
update 2
tried changing frame reset code this:
emoji.frame = cgrect(x: 25, y: 25, width: 25, height: 25)
which thought should reset them correctly top left, still shoves them off left. should prove currentemojilabelinitframes not issue , has when i'm setting them. maybe constraints getting reset or messed up?
your first screen, gamecontroller
, should receive viewwillappear
callback uikit when modal winscreencontroller
being dismissed.
so resetgametomatchstate
function set property true
, existing resetgametomatchstate
move viewwillappear
, checking first if property being set.
var resetneeded: bool = false func resetgametomatchstate() { resetneeded = true } override func viewwillappear(_ animated: bool) { super.viewwillappear(animated) // reset code here }
Comments
Post a Comment