【问题标题】:UIPopoverController keeps reloading UIWebViewUIPopoverController 不断重新加载 UIWebView
【发布时间】:2013-11-22 21:10:53
【问题描述】:

我有一个 UIPopoverController,我正在加载一个 ViewController 来保存一个 UIWebView。当我按下按钮显示弹出框时,网页加载正常。我也可以忽略 Popover。当我按下按钮再次显示 Popover 时,UIWebView 会重新加载。有没有办法在 ViewController 中维护/持久化 WebView 的状态,以便在弹出/关闭弹出框时内容保持不变?

也许另一个问题是,当一个 Popover 被解除时,我的 ViewController 是否被擦除了?我不认为它应该是因为它不是局部变量,但我不太确定我是否对 UIPopoverController 的行为有误解。

相关代码如下:

在我的主视图控制器中:

_popoverMenuVC  = [[TBPopoverMenuViewController alloc] init];
_popoverMenuVC.delegate = self;
_popoverMenuVC.contentSizeForViewInPopover = CGSizeMake(300, 300*(1+sqrt(5)/2.));
_popoverCtr = [[UIPopoverController alloc] initWithContentViewController:_popoverMenuVC];

我的按钮代码:

- (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];
    }
}

我的 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];

}

处理活动指标的几个代表:

#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];
}
}

我在 iPhone 上有一个非常相似的实现,显然没有 Popover,只是使用 ViewControllers,它似乎工作正常。想知道这是否必须与 PopoverController 本身一起使用...

感谢您的帮助!

编辑 1:

我将以下代码移至我的主 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];

我的 viewDidAppear 函数中没有任何内容了,我现在将其移至 viewDidLoad:

- (void)viewDidLoad
{
[super viewDidLoad];
wv.delegate = self;
[wv loadRequest:req];
[self.view addSubview:wv];
}

但 WebView 不再加载(我认为这与此问题有关:iOS 7 UIWebView doesn't load webpage)

将上述代码从 ViewDidLoad 移动到 viewDidAppear 将加载我的 WebView,但同样的重新加载问题仍然存在。

任何额外的帮助将不胜感激!

编辑 2:

我进行了一些代码重构,以便专注于可能导致此行为的原因:

在我的主 ViewController 中,我正在设置我的 PopoverViewController 及其 WebView,并将其设置为 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];

所有这些都发生在我的 TBPopoverMenuViewController 代码之外。

在我的 TBPopoverMenuViewController.h 中,我为 wv 和 req 设置了一个属性。

在我的 TBPopoverMenuViewController.m 中,我合成了我的 wv,但不是我的 req。

这是我的 viewDidLoad,我将 wv 的委托设置为 self。

- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
[self.view setBackgroundColor:[UIColor whiteColor]];
wv.delegate = self;
//    [wv loadRequest:_req];

}

在 viewDidAppear 中,这是我加载请求的地方。

-(void) viewDidAppear:(BOOL)animated{
[super viewDidAppear:NO];
[self setupActivityIndicator];
[wv loadRequest:_req];
}

试图在其他任何地方加载我的请求,在视图中加载,甚至在主 ViewController 中,它不会在弹出窗口中加载请求。它似乎只希望在 viewDidAppear 函数中发生。

此外,当我第二次尝试加载弹出框时,您可以看到前一个 wv 页面加载到之前的位置,但随后几乎立即在请求似乎重新加载到该 web 视图之上。

有人有解决办法吗?当弹出框消失并重新呈现时,我如何维护我的 webview。这似乎在 iPhone 上的非弹出窗口实现中运行良好,这让我认为 iPad/iOS7/UIPopoverControllers 缺少一些东西。

任何帮助将不胜感激!

编辑 3:

在使用 Xcode 的 Instruments 工具进行一些调试后,我意识到调用:

[wv loadRequest:_req];

在我的 ViewController 的 viewDidAppear 中导致内存泄漏!因此,在我的 UIWebView 重新加载以及我在哪里/如何加载我的请求的问题中似乎有一些重要的东西。正如我之前提到的,我尝试在我的主视图控制器中的 Popover 的 ViewController 之外调用 loadRequest,但没有成功。我也尝试在 viewDidLoad 中调用 loadRequest,也没有成功。

弹出框出现后,我能够在 menuBtnPressed 函数中成功调用 loadRequest:

- (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];
    }

归结为我可以在弹出窗口中为 UIWebView 成功调用 loadRequest 的两个地方是:

-在 ViewController 中的 viewDidApepar 中

-在按下按钮呈现我的弹出框之后

根据 Xcode 的 Instruments 工具,这两者似乎仍然会导致内存泄漏。从呈现 -> 解除 -> 重新呈现弹出框返回时,我仍然无法让我的 UIWebView 保持/保持状态。

有什么建议吗?

【问题讨论】:

    标签: ios ipad uiwebview ios7 uipopovercontroller


    【解决方案1】:

    每次present 完成时都会调用弹出框的viewDidAppear 方法。

    因此,每次显示弹出框时,当前代码都会添加一个 new UIWebView,它会转到默认 url(下面是来自先前呈现的所有先前 Web 视图)。

    一些改变应该会给你你想要的行为:

    1. 在弹出内容视图控制器中,将对setupUIs 的调用从viewDidAppear 移动到viewDidLoad。
    2. 在主视图控制器中,将popoverURL 的设置移动到第一个创建弹出内容视图控制器的位置(就在你alloc+init 之后)。

    【讨论】:

    • 很好的答案!我只想强调 viewWillAppear/viewDidAppear 逻辑是多么糟糕、容易出错和脆弱。这些方法应该只用于监控视图的状态,而不是设置 UI、逻辑等。
    • 感谢您的及时答复!我试图实现这一点并遇到了一些问题:将 setupUIs 函数从 viewDidAppear 移动到 viewDidLoad 使得 setupUIs 中的 WebView 不再加载。我觉得它与这个问题有关:stackoverflow.com/questions/18949857/… 我也做了,所以这里的 URL 是硬编码的,用于测试: NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"google.com"]]; 我会试试创建对主视图控制器的请求并查看它是否有效。
    • 我更新了我的帖子,最初尝试解决这个问题,但这似乎没有帮助..
    • 我不确定您是否需要进行其他根本性的更改。这可能与需要修改的 popoverURL 属性有关,因为现在在 viewDidLoad 中调用了 setupUI。该问题没有显示在内容 vc 中如何准确处理 popoverURL。
    • @AnnaKarenina 谢谢安娜!我试图重构代码以专注于问题。我相信现在实现有点清晰了,但同样的问题仍然存在。我摆脱了 popoverURL 变量并硬编码了 URL 以进行测试。任何帮助将不胜感激!
    【解决方案2】:

    事实证明我的问题的答案是...调用 loadRequest 两次。

    //setup popover menu vc
        _popoverMenuVC  = [[TBPopoverMenuViewController alloc] init];
        _popoverMenuVC.wv = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 300, 300*(1+sqrt(5)/2.))];
        _popoverMenuVC.delegate = self;
        _popoverMenuVC.wv.scalesPageToFit = YES;
        _popoverMenuVC.wv.scrollView.bounces = NO; //get rid of bounce for popover menu
        _popoverMenuVC.request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://www.google.com/"]];
        [_popoverMenuVC.wv loadRequest:_popoverMenuVC.request]; //first request
        [_popoverMenuVC.view addSubview:_popoverMenuVC.wv];
        _popoverCtr = [[UIPopoverController alloc] initWithContentViewController:_popoverMenuVC];
        [_popoverMenuVC.wv loadRequest:_popoverMenuVC.request]; // second request
    

    这会导致我想要的行为。 UIWebView 在加载页面的 PopoverViewController 中加载,当我呈现-> 关闭-> 重新呈现弹出框时,页面 UIWebView 就是我离开它的地方。我不知道为什么会这样,它似乎是一个错误或黑客,不得不调用该函数两次。根据 Xcode 中的 Instruments 工具集,loadRequest 似乎也会导致内存泄漏。

    所以我解决了我的问题,但我仍然有点困惑为什么这是解决方案。幸运的是我偶然发现了它......

    任何更有经验的人的澄清将不胜感激!

    【讨论】:

      猜你喜欢
      • 2013-11-23
      • 2017-12-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-25
      • 2015-08-17
      相关资源
      最近更新 更多