debugging - iOS building custom rating control issue -
i know there's lots of 3rd party solutions out there, i've decided build 1 myself in full control of animations , learn new.
it seems of time made through subclassing uicontrol , tracking touches, i've used different approach. create system buttons images. way nice highlight animation on press free. anyway, works quite nice until press on fast. here's gif of what's happening.
sometimes, if fast full star gets stuck. i'll try explain what's happening behind animation. since full , empty stars have different color, change tint color of button each time becomes full or empty. animation see separate uiimageview added on top of button right before beginning of animation block , removed in completion block. believe on emptying star animation not fired , image not removed in completion block. can't catch bug in code.
i added debugging code see if block makes star empty fired. seems is, , completion block called.
2015-04-23 13:00:00.416 reratingcontrol[24011:787202] touch number: 5 2015-04-23 13:00:00.416 reratingcontrol[24011:787202] removing star @ index: 4 2015-04-23 13:00:00.693 reratingcontrol[24011:787202] star removed
star indexes zero-based, 5th star supposed removed, it's not.
full project on github. it's pretty small. appreciate if me fix this. oh, , feel free use code if want :-)
update. suggested post logic code here. didn't right away because felt cumbersome.
button action method:
- (void)buttonpressed:(id)sender { static int touchnumber = 0; nslog(@"\ntouch number: %d", touchnumber); touchnumber++; if (self.isupdating) { return; } self.updating = yes; nsinteger index = [self.stars indexofobject:sender]; __block nstimeinterval delay = 0; [self.stars enumerateobjectsusingblock:^(id obj, nsuinteger idx, bool *stop) { restarbutton *btn = (restarbutton*)obj; if (idx <= index) { if (!btn.isfull) { nslog(@"\nadding star @ index: %ld", (long)idx); [btn makefullwithdelay:delay]; delay += animationdelay; } } else { if (btn.isfull) { nslog(@"\nremoving star @ index: %ld", (long)idx); [btn makeemptywithdelay:0]; } } }]; if ([self.delegate respondstoselector:@selector(ratingdidchangeto:)]) { [self.delegate ratingdidchangeto:index + 1]; } self.updating = no; }
empty full star method:
- (void)makeemptywithdelay:(nstimeinterval)delay { // if (!self.isfull) { // return; // } self.full = no; uiimageview *fullstar = [[uiimageview alloc] initwithimage:self.starimagefull]; [self addsubview:fullstar]; cgfloat xoffset = cgrectgetmidx(self.bounds) - cgrectgetmidx(fullstar.bounds); cgfloat yoffset = cgrectgetmidy(self.bounds) - cgrectgetmidy(fullstar.bounds); fullstar.frame = cgrectoffset(fullstar.frame, xoffset, yoffset); [self setimage:self.starimageempty forstate:uicontrolstatenormal]; [self settintcolor:self.superview.tintcolor]; [uiview animatewithduration:animationduration delay:delay options:uiviewanimationoptioncurveeaseout animations:^{ //fullstar.transform = cgaffinetransformmakescale(0.1f, 0.1f); fullstar.transform = cgaffinetransformmaketranslation(0, 10); fullstar.alpha = 0; } completion:^(bool finished) { [fullstar removefromsuperview]; nslog(@"star removed"); }];
make empty star full method:
} - (void)makefullwithdelay:(nstimeinterval)delay { // if (self.isfull) { // return; // } self.full = yes; uiimageview *fullstar = [[uiimageview alloc] initwithimage:self.starimagefull]; cgfloat xoffset = cgrectgetmidx(self.bounds) - cgrectgetmidx(fullstar.bounds); cgfloat yoffset = cgrectgetmidy(self.bounds) - cgrectgetmidy(fullstar.bounds); fullstar.frame = cgrectoffset(fullstar.frame, xoffset, yoffset); fullstar.transform = cgaffinetransformmakescale(0.01f, 0.01f); [self addsubview:fullstar]; [uiview animatekeyframeswithduration:animationduration delay:delay options:0 animations:^{ cgfloat ratio = 0.35; [uiview addkeyframewithrelativestarttime:0 relativeduration:ratio animations:^{ fullstar.transform = cgaffinetransformmakescale(animationscaleratio, animationscaleratio); }]; [uiview addkeyframewithrelativestarttime:ratio relativeduration:1 - ratio animations:^{ fullstar.transform = cgaffinetransformidentity; }]; } completion:^(bool finished) { [self setimage:self.starimagefull forstate:uicontrolstatenormal]; [self settintcolor:self.fulltintcolor]; [fullstar removefromsuperview]; }]; }
ah, i've managed find reason behind bug , works perfect now!
i used view debugging see if it's uiimageview animation stuck on button or image of button not set properly. surprised see it's button image causing issue. , looked through code again , realised changing button image in completion block after delay no regard if it's state has changed. simple fix makefullwithdelay: solved issue.
} completion:^(bool finished) { if (self.isfull) { [self setimage:self.starimagefull forstate:uicontrolstatenormal]; [self settintcolor:self.fulltintcolor]; } [fullstar removefromsuperview]; }];
i used whole evening trying find answer yesterday, , after posted question answer came itself. telling people problem helps go through logic more attention guess. :-)
should delete post or might in future?