tbleckert
tbleckert

Reputation: 3803

iOS: Can't show view after hiding it

I have a activityIndicator and a transparent black layer behind it. When something loads I show them like this:

[activityIndicator startAnimating];
loadingCover.hidden = NO;

And when I hiden them, I just do it like this:

[activityIndicator stopAnimating]; //hides on stop
loadingCover.hidden = YES;

So far everything works. But somehow if I want to show them again, it doesn't work. Any ideas?

EDIT: This is how I do it...

- (void)viewDidLoad {
    [mainView addSubview:loadingCover]; //works
}

- (void)parserDidEndDocument:(NSXMLParser *)parser {
    [loadingCover removeFromSuperview]; //works
}

- (void)refreshRSS:(id)sender {
    [mainView addSubview:loadingCover]; //doesn't work
}

EDIT2: First of all I'm coding with ARC mode and second, loadingCover has been changed to loadingplate, no biggie...

Ok so in my .h file I do this:

UIView *loadingplate;
UIActivityIndicatorView *loadingIndicator;

And in my .m file in viewDidLoad I do this:

CGRect viewRect = CGRectMake(0, 0, 320, 460);
loadingplate = [[UIView alloc] initWithFrame:viewRect];

UIColor *loadingplateColor = [[UIColor alloc] initWithRed:0.0 green:0.0 blue:0.0 alpha:0.8];
[loadingplate setBackgroundColor:loadingplateColor];
loadingplate.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleTopMargin|UIViewAutoresizingFlexibleRightMargin|UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleBottomMargin;

loadingIndicator = [[UIActivityIndicatorView alloc] initWithFrame:viewRect];
[loadingIndicator setContentMode:UIViewContentModeCenter];
[loadingIndicator startAnimating];

loadingIndicator.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleTopMargin|UIViewAutoresizingFlexibleRightMargin|UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleBottomMargin;

[loadingplate addSubview:loadingIndicator];
[mainView addSubview:loadingplate];

EDI3: After reading Jasarien's answer I tried this in my .h file:

@property (strong, nonatomic) UIView *loadingPlate;

And then in my .m file:

@synthesize loadingPlate = _loadingPlate;

In this file in viewDidLoad I'm creating the view.

But this doesn't seem to work either.

Upvotes: 0

Views: 935

Answers (6)

Brodie
Brodie

Reputation: 11

Don't you have to use self.loadingplate to call the property strong and make the retain on your view ?

Upvotes: 0

XJones
XJones

Reputation: 21967

Your basic logic to create, show, and hide loadingPlate looks fine. I use a very similar implementation abstracted in a UIView subclass in my apps. All of the answers are stabs in the dark b/c the code you posted doesn't show an obvious problem other than the discrepancies in your iVar names. I decided to add this answer in the hope that it helps you find the solution.

  1. You don't need a property. As far as retain semantics go, iVars are strong by default. If you do create a property and synthesize it the way you show than be sure to refer to either self.loadingPlate or _loadingPlate in your code.

  2. Make sure you don't have a typo in your iVar name vs your property name. For example, if you have an iVar called loadingplate but your property is loadingPlate then you will end up with two iVars (loadingplate and loadingPlate) as properties automatically create iVars if they don't match one already defined.

  3. Your logic of creating the loadingPlate view in viewDidLoad and adding/removing it from the superview as needed is totally fine. Just make aure you don't have loadingPlate = nil anywhere other than in viewDidUnload.

  4. If it's possible for the superview frame size to change you should explicitly set loadingPlate.frame = mainView.bounds before adding loadingView as a subview. If the frames don't change this won't matter.

If I think of anything else I'll add it later. Good luck.

Upvotes: 1

Jasarien
Jasarien

Reputation: 58448

Please see XJones' comment. This answer is probably wrong.

After Edited question:

It seems that since you're using arc, your loadingPlate view is probably being released too soon.

When you alloc and init your loadingPlate view, it'll have a retain count of +1, as expected from an alloc/init. Yet, because you're using ARC, after you add it as a subview of your main view, ARC releases it. Effectively the loadingPlate view is owned by its super view and when you remove it from the superview, the superview releases it, causing the view to be deallocated. Thus when you try to show it again, it's not there anymore and can't be shown.

The solution to this would be to create a property for your loadingPlate view, and give it a 'strong' reference, (effectively the same as declaring the property as a 'retain'). This way, the object that has this property will own the loadingPlate view, keeping a strong reference to it.

Upvotes: 3

A Salcedo
A Salcedo

Reputation: 6468

Try moving the allocation and initialization of that view to the init method. Also, when you call the method to add it again, one thing you can try is to simply check if it exists first probably by:

if (!loadingPlate) {
// allocate and initialize again because somehow it has been released.
}

At least this way you know if the instance of loadingPlate is still being retained.

Upvotes: 1

gschandler
gschandler

Reputation: 3208

Are you sure loadingCover doesn't still have its hidden property set to YES from the previous time displayed?

Try:

- (void)refreshRSS:(id)sender {
    loadingCover.hidden = NO;
    [mainView addSubview:loadingCover]; //doesn't work
}

Upvotes: 0

bogen
bogen

Reputation: 10422

You're saying loadingCover.hidden = NO does not work? Have you added the view as a subview to the current showing view?

Upvotes: 1

Related Questions