0

I have a label that appears after a gesture and I want to fade the label out. The following code works, but if I do several gestures in a row, the last ones don't finish the fade and display but then stop abruptly. Here is my code:

- (void) gestureLabelAppear:(NSString *)theLabelText
{
    myLabel = [[UILabel alloc] initWithFrame:CGRectMake(gestureEndPoint.x, gestureEndPoint.y, 200, 20)];
    myLabel.center=CGPointMake(gestureEndPoint.x, gestureEndPoint.y);
    myLabel.textAlignment = UITextAlignmentCenter;  
    myLabel.text =theLabelText;
    [self.view addSubview:myLabel];
    [self fadeOutLabels];

}

-(void)fadeOutLabels
{
    [UIView animateWithDuration:3.0 
                          delay:0.0 
                        options:UIViewAnimationCurveEaseInOut 
                     animations:^ {
                         myLabel.alpha = 0.0;
                     } 
                     completion:^(BOOL finished) {
                         [myLabel removeFromSuperview];
                         NSLog(@"removed label");
                     }];
}

Any suggestions on how to fix?

David L
  • 4,347
  • 3
  • 18
  • 30

3 Answers3

0

The problem may be that you're asking the processor to do too many animations in succession and/or the animations are interrupted by other processes in the event loop. I often find timing problems like this are cured by inserting a delay.

Try replacing [self fadeOutLabels]; with [self performSelector:@selector(fadeOutLabels) withObject:nil afterDelay:(NSTimeInterval)0.1];

And/or replace [self.view addSubview:myLabel]; with [self.view performSelector:@selector(addSubview:) withObject:myLabel afterDelay:(NSTimeInterval)0.1];

(I don't mean to imply that I understand all the inner workings, only that this kludge has worked for me in the past with similar issues.)

Wienke
  • 3,723
  • 27
  • 40
  • I tried your code but it's doing the same thing. I'm thinking it might be related to allocating the same label multiple times. It consistently works with 2 labels on the screen but the 3rd label generally ends without properly fading. Any other thoughts? – David L Apr 15 '12 at 12:15
  • Right after I posted the last comment, I looked at the code one more time. I removed `[myLabel removeFromSuperview];` and all the labels fade properly. – David L Apr 15 '12 at 12:21
  • First, you were kind, but you should uncheck this answer as accepted, since it didn't work. Next, actually, even if the code is working now, you do have a leak. Changing the myLabel assignment to `myLabel = [[[UILabel alloc] initWithFrame:CGRectMake(gestureEndPoint.x, gestureEndPoint.y, 200, 20)] autorelease];` would take care of that -- except that all the labels are now going to hang around for the life cycle of your view since you are omitting `removeFromSuperview`...I'll put this in another answer. – Wienke Apr 15 '12 at 13:12
  • I removed the accepted check. I'm new to this and I thought since I had answered it I should check it. – David L Apr 17 '12 at 00:27
0

You solved your main problem by omitting removeFromSuperview in the fadeOutLabels method, but now those labels are going to accumulate, hogging memory. And you had a leak to begin with by doing an alloc without providing for its release.

I think these two changes might perfect the solution you've already arrived at:

1) Make a property for UILabel called "myLabel."

2) Change gestureLabelAppear and fadeOutLabels to this:

- (void) gestureLabelAppear:(NSString *)theLabelText 
{
if (self.myLabel) {
    [self.myLabel removeFromSuperview];
    self.myLabel = nil;
}
self.myLabel = [[[UILabel alloc] initWithFrame:CGRectMake(gestureEndPoint.x, gestureEndPoint.y, 200, 20)] autorelease];
self.myLabel.center=CGPointMake(gestureEndPoint.x, gestureEndPoint.y);
self.myLabel.textAlignment = UITextAlignmentCenter;  
self.myLabel.text =theLabelText;
[self.view addSubview:self.myLabel];
[self fadeOutLabels];

}

-(void)fadeOutLabels 
{
[UIView animateWithDuration:3.0 
                      delay:0.0 
                    options:UIViewAnimationCurveEaseInOut 
                 animations:^ {
                     myLabel.alpha = 0.0;
                 } 
                 completion:NULL];
}
Wienke
  • 3,723
  • 27
  • 40
  • I tried this code and it doesn't do the trick either. It's removing the previous label from the view when `gestureLabelAppear` is called from another gesture before the previous animation ends. Also, I got a compiler error for `autorelease` since I am using ARC I don't think I need to do that. I did some more research and found this link about using tags with labels [http://stackoverflow.com/a/9691975/1203475]. I will post code in answer below. – David L Apr 17 '12 at 01:27
0

Here is the code that seems to work. I needed to add tags to the labels so I could explicitly refer to the individual labels I was creating. I verified that the labels disappear by changing the alpha value to .2 and watching them disappear.

- (void) gestureLabelAppear:(NSString *)theLabelText 
{
    counter=counter+1;
    self.myLabel = [[UILabel alloc] initWithFrame:CGRectMake(gestureEndPoint.x, gestureEndPoint.y, 200, 20)];
    self.myLabel.center=CGPointMake(gestureEndPoint.x, gestureEndPoint.y);
    self.myLabel.textAlignment = UITextAlignmentCenter;  
    self.myLabel.text =[NSString stringWithFormat:@"%@-%d",theLabelText,counter];
    self.myLabel.tag=counter;
    [self.view addSubview:self.myLabel];
    [self fadeOutLabels:counter];    

}

-(void)fadeOutLabels:(int)theTag 
{
    [UIView animateWithDuration:3.0 
                      delay:0.0 
                    options:UIViewAnimationCurveEaseInOut 
                 animations:^ {
                     self.myLabel.alpha = 0.2;
                 } 
                 completion:^(BOOL finished) {
                    UILabel *label = (UILabel *)[self.view viewWithTag:theTag]; 
                    [[self.view viewWithTag:theTag] removeFromSuperview];
                    label=nil;
                 }];
}
David L
  • 4,347
  • 3
  • 18
  • 30
  • I'm glad you've got it working, but I'm confused because this looks the same as what you were doing originally -- removing the newly added label as soon as the fade anim completes. Nice work with `viewWithTag`. Now that you are keeping track of it with a tag, it doesn't seem necessary to make a property for the label. – Wienke Apr 17 '12 at 11:31
  • I think the difference from the original code is that originally, each time the fade completed, the most recently created label was removed (since they were all `myLabel`). Now, with the addition of the tags, the label's are referenced individually. The result is that the completion of the fade sequence now removes the label with the tag that started the fade sequence instead of the most recently created one. – David L Apr 17 '12 at 16:36
  • Now *that* sounds like a solution, always removing the *penultimately* added tag, as opposed to the one that just faded out. But wouldn't that require you to call `[self fadeOutLabels:counter-1]` (and doing the removal only if counter were >= 0, to accommodate the first occurrence)? As it is, you're tagging *and* fading per the incremented counter. – Wienke Apr 18 '12 at 00:44
  • I have the counter as the 1st line of the `gestureLabelAppear` method so the tag is assigned with the same tag that is passed in `[self fadeOutLabels:counter]`. If I incremented the counter after `self.myLabel.tag=counter;` and before calling `fadeOutLabels` I would have that issue. By setting the alpha value so it doesn't fade to zero, I can test and verify that all the labels disappear. – David L Apr 18 '12 at 16:04