2

I want to have a custom view that can be displayed on several view controllers. I want to set it up just like a UIAlertView, where I initialize it, then call [myView show] to add it to the current view controller. Wanted to know how to go about adding the custom uiview directly from it's class onto the current view controller. The view will also dismiss itself after a set amount of time (basically the custom view is an animation of images displaying some stats for a brief moment before fading out).

Calling from the class method [myView show] would replace having to initialize the view, then call [self.view addSubview:myView].

What is the best approach in displaying / removing the custom view directly from it's class?

Mat
  • 202,337
  • 40
  • 393
  • 406
JimmyJammed
  • 9,598
  • 19
  • 79
  • 146

2 Answers2

4

I took a different tack to jsd, I added it to the view. Maybe the window is better. But this code seemed to do what is wanted when I tried it:

@implementation EWView

+ (void)show:(UIView *)superView {
    EWView *instantView = [[EWView alloc]initWithFrame:CGRectMake(20, 20, 50, 50)];
    instantView.backgroundColor = [UIColor greenColor];
    [superView addSubview:instantView];
    int64_t delayInSeconds = 4.0;
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
        [instantView removeFromSuperview];
    });
}

@end

and I called it from a UIViewController with

[EWView show:self.view];

The view will continue to exist only while the block has not finished executing. When the block finishes, the EWView will be deallocated.

emrys57
  • 6,679
  • 3
  • 39
  • 49
  • Yeah I thought about the singleton approach, but have heard that subclassed UIViews should not be used as singletons for some reason. Wasn't sure if that is a valid statement or not... – JimmyJammed Dec 04 '12 at 20:20
  • I've never heard that, but I know little. But this isn't a singleton. Each call to `[EWView show:]` will create a new instance of `EWView`, which lives for a few seconds and then evaporates. You could have multiple ones simultaneously, I think. Definitely not a singleton. – emrys57 Dec 04 '12 at 20:46
  • Got it. I guess I was thinking along the lines of being memory efficient by not allocating then deallocating the view several times. Instead, I was hoping to allocate it once, then just reuse it as needed. – JimmyJammed Dec 04 '12 at 20:48
  • You'd still need an instance somewhere - you can't display a class, only an instance - and that would need a pointer somewhere. I keep a global singleton class in my projects for that sort of thing. Then in the [EWView show] method, it could look up that global singleton, create it if it was missing, and show it. But I'd not bother, it's not much memory and it comes and goes on a timescale of seconds or more. And the singleton would consume memory while it was not being displayed! – emrys57 Dec 04 '12 at 20:57
2

UIAlertView and friends add themselves to the UIWindow's view, not the current view controller's view. That's what you should do.

If you know that they will always fade out at some predetermined time, you could make a block to do the removal and use dispatch_after(). See How do you trigger a block after a delay, like -performSelector:withObject:afterDelay:?

Community
  • 1
  • 1
jsd
  • 7,673
  • 5
  • 27
  • 47
  • Ok so I am on the right path. I currently add it like so: UIWindow *window = [appDelegate window]; [window addSubview:self]; [self animateRewards]; I already have it animating. The problem is, when I initialize and call it from my viewcontroller, it only shows once. – JimmyJammed Dec 04 '12 at 19:56
  • I am removing it like so: -(void)dismissRewards{ [self removeFromSuperview]; NSLog(@"Removed W: %f H: %f",self.frame.size.width,self.frame.size.height); //Reset Views zBucksView.alpha = 0; xpView.alpha = 0; [zBucksView setFrame:CGRectMake(DEVICE_WIDTH/4-zBucksIcon.size.width/2, DEVICE_HEIGHT/2-zBucksIcon.size.height/2-12, zBucksIcon.size.width, zBucksIcon.size.height+25)]; [xpView setFrame:CGRectMake(DEVICE_WIDTH/4*3-xpIcon.size.width/2, DEVICE_HEIGHT/2-xpIcon.size.height/2-12, xpIcon.size.width, xpIcon.size.height+25)]; } – JimmyJammed Dec 04 '12 at 19:58
  • To clarify, I initialize and call the view, it shows and animates just fine and removes itself from the view controller. But when I try to call it again (already initialized of course), it wont show up. But the view still exists. I am assuming it has to do with the way I am removing it? – JimmyJammed Dec 04 '12 at 20:00
  • You should be able to call addSubview again after calling removeFromSuperview, I don't know why that wouldn't work for you. Maybe try making multiple instances instead of reusing the same one over and over? – jsd Dec 04 '12 at 22:41
  • Yeah that was the issue. Works fine now. Thanks! – JimmyJammed Dec 17 '12 at 21:40