I have a UIPopoverController that I am loading with a ViewController to hold a UIWebView. When I press a button to present the Popover, the webpage loads fine. I can dismiss the Popover just as fine as well. When I press a button to present the Popover again, the UIWebView reloads. Is there a way to maintain/persist the state of the WebView in the ViewController so that the content remains the same when the popover is presented/dismissed?
Maybe another question is, when a Popover is dismissed, is my ViewController wiped? I don't believe it should be because it isn't a local variable, but I'm not so sure if I have a misunderstaing of how UIPopoverController's behave.
Relevant code below:
In my main ViewController:
_popoverMenuVC = [[TBPopoverMenuViewController alloc] init];
_popoverMenuVC.delegate = self;
_popoverMenuVC.contentSizeForViewInPopover = CGSizeMake(300, 300*(1+sqrt(5)/2.));
_popoverCtr = [[UIPopoverController alloc] initWithContentViewController:_popoverMenuVC];
Code for my button:
- (void)menuBtnPressed:(id)sender
{
if (IS_IPAD) {
UIButton *btn = (UIButton*)sender;
if (!_popoverCtr.isPopoverVisible) {
//set url for popover webview
_popoverMenuVC.popoverURL = @"http://www.google.com";
// show popover
[_popoverCtr setPopoverContentSize:CGSizeMake(300, 300*(1+sqrt(5)/2.))];
[_popoverCtr presentPopoverFromRect:btn.frame
inView:self.view
permittedArrowDirections:UIPopoverArrowDirectionDown
animated:YES];
} else {
// hide popover
[_popoverCtr dismissPopoverAnimated:YES];
}
}
Code for my popoverMenuVC:
-(void) viewDidAppear:(BOOL)animated{
[self setupUIs];
}
- (void)setupUIs
{
// webview
wv = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 300, 300*(1+sqrt(5)/2.))];
//activity indicator
self.activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
self.activityIndicator.frame = CGRectMake(0.0, 0.0, 40, 40);
self.activityIndicator.center = self.view.center;
// darkview for activity indicator
self.darkView = [[UIView alloc] initWithFrame:CGRectMake(0, 0,300, 300*(1+sqrt(5)/2.))];
[self.darkView setBackgroundColor:[UIColor blackColor]];
[self.darkView setAlpha:0.4];
wv.delegate = self;
wv.scalesPageToFit = YES;
wv.scrollView.bounces = NO; //get rid of bounce for popover menu
[self.view addSubview:wv];
}
A few delegates for handing activity indicator:
#pragma mark Activity Indicator
- (void) showLoadingIndicator
{
[self.view insertSubview:self.darkView aboveSubview:self.view];
[self.view insertSubview:self.activityIndicator aboveSubview:self.darkView];
[self.activityIndicator startAnimating];
}
- (void) hideLoadingIndicator
{
[self.activityIndicator stopAnimating];
[self.activityIndicator removeFromSuperview];
[self.darkView removeFromSuperview];
}
#pragma mark UIWebView Delegates
-(void)webViewDidStartLoad:(UIWebView *)webView{
NSLog(@"Webview is starting to load");
[self showLoadingIndicator];
}
-(void)webViewDidFinishLoad:(UIWebView *)webView{
NSLog(@"request: %@", [[webView request] description]);
if(!webView.loading){
NSLog(@"Webview has finished loading");
[self hideLoadingIndicator];
}
}
I have a very similar implementation of this working for iPhone, without the Popover obviously, just with ViewControllers and it seems to work fine. Wondering if this has to work with the PopoverController itself...
Thanks for any help!
Edit 1:
I moved the following code to my main ViewController:
_popoverMenuVC = [[TBPopoverMenuViewController alloc] init];
_popoverMenuVC.wv = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 300, 300*(1+sqrt(5)/2.))];
_popoverMenuVC.wv.scalesPageToFit = YES;
_popoverMenuVC.wv.scrollView.bounces = NO; //get rid of bounce for popover menu
_popoverMenuVC.req = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://www.google.com"]];
_popoverCtr = [[UIPopoverController alloc] initWithContentViewController:_popoverMenuVC];
I have nothing in my viewDidAppear function anymore, I now moved it to viewDidLoad:
- (void)viewDidLoad
{
[super viewDidLoad];
wv.delegate = self;
[wv loadRequest:req];
[self.view addSubview:wv];
}
But the WebView doesn't load anymore (which I think is related to this issue: iOS 7 UIWebView doesn't load webpage)
Moving the above code from ViewDidLoad to viewDidAppear will load my WebView, yet the same reloading problem persists.
Any additional help would be appreciated!
Edit 2:
I did some code refactoring in order to focus in on what might be causing this behavior:
In my main ViewController, I am setting up my PopoverViewController, along with its WebView, and setting it to be the init content for our UIPopoverController:
_popoverMenuVC = [[TBPopoverMenuViewController alloc] init];
_popoverMenuVC.wv = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 300, 300*(1+sqrt(5)/2.))];
_popoverMenuVC.wv.scalesPageToFit = YES;
_popoverMenuVC.wv.scrollView.bounces = NO; //get rid of bounce for popover menu
_popoverMenuVC.req = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://www.google.com"]];
[_popoverMenuVC.view addSubview:_popoverMenuVC.wv];
_popoverCtr = [[UIPopoverController alloc] initWithContentViewController:_popoverMenuVC];
All of this is happening once outside of my TBPopoverMenuViewController's code.
In my TBPopoverMenuViewController.h, I set up a property for wv and req.
In my TBPopoverMenuViewController.m, I synthesize my wv, but not my req.
Here is my viewDidLoad, where I set the wv's delegate to self.
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
[self.view setBackgroundColor:[UIColor whiteColor]];
wv.delegate = self;
// [wv loadRequest:_req];
}
And in viewDidAppear, this is where I load my request.
-(void) viewDidAppear:(BOOL)animated{
[super viewDidAppear:NO];
[self setupActivityIndicator];
[wv loadRequest:_req];
}
Trying to load my request anywhere else, in view did load, or even in the main ViewController, it doesn't load the request in the popover. It only seems to want to happen in the viewDidAppear function.
Further, when I try to load the popover the second time, you can see the previous wv with the page loaded where it was before, but then almost immediately after the request seems to reload on top of that webview.
Does anyone have a solution? How can I maintain my webview when the popover dismisses and is re-presented. This seems to work fine on iPhone in a non-popover implementation, making me think that there is something I'm missing for iPad/iOS7/UIPopoverControllers.
Any help would be appreciated!
Edit 3:
After some debugging with Xcode's Instruments tool, I've realized that calling:
[wv loadRequest:_req];
In the viewDidAppear of my ViewController results in a memory leak! So there seems to be something essential in my problem with the UIWebView reloading and where/how I'm loading my request. As I've mentioned before, I've tried calling loadRequest outside of my Popover's ViewController in my main View Controller, with no luck. I also tried to call loadRequest in viewDidLoad, with no luck as well.
I was able to successfully call loadRequest in my menuBtnPressed function after the popover is presented:
- (void)menuBtnPressed:(id)sender
{
if (IS_IPAD) {
popOverBtn = (UIButton*)sender;
if (!_popoverCtr.isPopoverVisible) {
[_popoverCtr setPopoverContentSize:CGSizeMake(300, 300*(1+sqrt(5)/2.))];
[_popoverCtr presentPopoverFromRect:popOverBtn.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionDown animated:YES];
[_popoverMenuVC.wv loadRequest:_popoverMenuVC.request];
} else {
// hide popover
[_popoverCtr dismissPopoverAnimated:YES];
}
Which boils down to the two places I can actually successfully call loadRequest for the UIWebView in my popover are:
-in viewDidApepar in the ViewController
-after presenting my popover with a button press
Both of these seem to still result in a memory leak according to Xcode's Instruments tools. I still can't get my UIWebView to maintain/persist state when going back from presenting -> dismissing -> re-presenting the popover.
Any suggestions?