PDA

View Full Version : [view addSubview:myView] - problem




Danneman101
Feb 25, 2009, 07:08 PM
Im getting a very weird behaviour from when I add a subview to my main view in one function (the viewWillAppear), and then remove it in another function (webViewDidFinishLoading).

I need the delay between them in order to measure how long the ActivityIndicator should be active (which is until the webpage loaded into the UIWebView is completely loaded, which the webViewDidFinishLoad-function indicates).

Most things function as normal. What does not function, and actually halts the entire app, are links (clicked on <a href="">-tags) from within the various html-pages loaded into the UIWebView.

This is the code-snippet:


// 1. Before the UIWebView is loaded, we load an UIActivityIndicator into the main view
- (void)viewWillAppear:(BOOL)animated
{
activityView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
activityView.frame = CGRectMake(143.0f, 250.0f, 32.0f, 32.0f);
[self.view addSubview:activityView];
[activityView startAnimating];
[activityView release];
}

// 2. Then removes the UIActivityIndicator when the UIWebView has been loades
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
[activityView stopAnimating];
[activityView removeFromSuperview];
}


Note that this seems to have nothing to do with the UIActivityIndicator as such, since Ive also tried loading a UIView in the first function, and removing it in the second, and end up with the same problem.

Also, if I remove the activityView in the first function (which would remove it too soon), this problem disappears.

The same is true if I remove it for instance in a viewDidFinishLoad()-function instead. This will however also remove it too soon, making this solution a no go for my purpose.

Ive also tried adding the subview to, for instance the webview instead, but the same problem presists even then.

Any idea as to how to solve this problem?



caveman_uk
Feb 26, 2009, 02:32 AM
The reason is failing is that viewWillAppear is called only once when a view appears (obviously) but webViewDidFinishLoad is called every time the webView finishes loading anything. So when you click on a link the method is called when the new page gets loaded. Note that there will not have been a matching call to viewWillAppear in that case. So you would be trying to remove a subview that isn't actually in the view hierarchy.

Can't you just hide the subview rather than remove it?

Danneman101
Feb 26, 2009, 04:51 AM
The reason is failing is that viewWillAppear is called only once when a view appears (obviously) but webViewDidFinishLoad is called every time the webView finishes loading anything. So when you click on a link the method is called when the new page gets loaded. Note that there will not have been a matching call to viewWillAppear in that case. So you would be trying to remove a subview that isn't actually in the view hierarchy.

Can't you just hide the subview rather than remove it?

Oh, so that is why the app hangs when a link is clicked - because the uiwebview is reloaded, the webViewDidFinishLoad is called again, and this time it tries to remove the activityView that isn't there anymore. Ok, I think I get it :)


Ive found a good function to use to hide the UIActivityIndicatorView in the webViewDidFinishLoad:

[activityView stopAnimating];
[activityView hidesWhenStopped];


Question 1:
My concern is, wont this create a lot of duplicate instances of the activityView, since the old ones are just hidden, not really removed? Or are they automatically replaced by the new version of the instance once the:
activityView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
..is executed?

Question 2:
Would a better solution be to place a remove-code inside another function that is called only ONCE when the uiwebview already has been first loaded (not on reload, as does the webViewDidFinishLoad)? Is there even such a function?

Question 3:
The ideal solution, though, would be to create an empty, white UIView that the activity indictator is loaded into, so that the background is always the same. However, I cant find a similar hide-function for a UIView?

Danneman101
Feb 26, 2009, 06:06 AM
I found that this method seems to be appropriate to "hide" a UIView:


[self.view sendSubviewToBack:progressAlert];


Works fine.

The only thing Im concerned about is the memory-management. Should I dealloc the UIView and the UIActivityIndicatorView in the dealloc-method, perhaps? Or is the release-method enough to prevent building up the memory?