UIWebView 在应用商店版本中的行为与开发版本不同

Posted

技术标签:

【中文标题】UIWebView 在应用商店版本中的行为与开发版本不同【英文标题】:UIWebView acts differnetly in app store version than dev version 【发布时间】:2011-02-25 22:09:29 【问题描述】:

我遇到了一个在模拟器中完美运行的应用程序以及物理 iPhone 4 和 iPhone 3GS 的问题。该应用已获得批准,现已在 App Store 中,但从 App Store 下载的分发版本出现了开发/发布版本中未发现的错误。

这是一款免费应用,但受本地广告支持。当应用程序启动(或从后台返回)时,AppDelegate 会尝试从我们的广告服务器下载一些 html,如果成功,则会显示一个带有 UIWebView 的模态视图控制器,并传递一个包含 HTML 的 NSData 变量。在开发/发布版本中,这非常有效;应用启动,几秒钟后,一个视图向上滑动并显示广告,可以通过一个按钮将其关闭。

但是,来自 App Store 的分发版本有所不同。当模态视图控制器向上滑动时,UIWebView 永远不会加载。请记住,只有在能够下载广告数据的情况下,我才会呈现视图控制器——否则,视图将永远不会呈现。

谢天谢地,我在广告视图控制器中实现了一个计时器,如果 webViewDidFinishLoad 从未触发(其中计时器无效),它将导致模态视图自行关闭,因此至少应用程序用户不会太生气。但是让一个空的视图控制器向上滑动然后毫无理由地滑开仍然很难看。

AppDelegate 中的相关方法如下:

- (void)launchAd

    [NetworkActivity showFor:@"ad"];

    if (!alreadyActive && [ServerCheck serverReachable:@"openx.freewave-wifi.com" hideAlert:YES])
      
        alreadyActive = YES;

        [self performSelectorInBackground:@selector(downloadAdData) withObject:nil];
    

    [NetworkActivity hideFor:@"ad"];


- (void)downloadAdData

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    NSString *baseURL = @"http://appdata.freewave-wifi.com/ad/";

    NSString *file = (IS_IPAD) ? @"ipad.php" : @"iphone.php";

    NSURL *adURL = [NSURL URLWithString:[baseURL stringByAppendingString:file]];

    adData = [[NSData alloc] initWithContentsOfURL:adURL];

    [self performSelectorOnMainThread:@selector(presentAdModal) withObject:nil waitUntilDone:NO];

    [pool release];


- (void)presentAdModal

    if (adData)
    
        AdViewController *adView = [[AdViewController alloc] initWithNibName:nil bundle:nil];
        [adView setAdData:adData];

        UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:adView];


        [navController setModalPresentationStyle:UIModalPresentationFormSheet];
        [navController setModalTransitionStyle:UIModalTransitionStyleCoverVertical];

        [tabBarController presentModalViewController:navController animated:YES];

        [navController release], navController = nil;
        [adView release], adView = nil;
    
    else
        LogError(@"Not presenting ad; unable to create data object.");

顺便说一句,adData 在标题中定义为NSData *adData;

AdViewController 只包含一个 UIWebView,它被加载

[webView loadData:adData MIMEType:@"text/html" textEncodingName:@"utf-8" baseURL:nil];

再一次,这一切都可以完美运行,每次都在模拟器和物理设备中使用开发/发布版本——只是不适用于应用商店的分发版本。我什至将 NSData 转换为 NSString 并使用 NSLog() 将其输出,只是为了证明 HTML 是在模态显示 AdView 之前下载的。

[叹气...]

编辑 1:如果我的原始帖子不清楚,webViewDidFinishLoad 永远不会在分发版本中被调用(但它会在开发/发布版本中调用)。

编辑 2:另外,就在我打电话之前

[webView loadData:adData MIMEType:@"text/html" textEncodingName:@"utf-8" baseURL:nil];

在 AdViewController 中,我添加了一个临时的 NSLog() 并将 adData 转换为 NSString 并将其记录到控制台,HTML 就在那里。那么,UIWebView 只是拒绝加载 NSData?

【问题讨论】:

我很好奇这个!我已经下载了该应用程序并使用 Wireshark 嗅探连接,但乍一看找不到任何异常。您是否注意到 UIWebView 标题在再次弹出视图之前设置为 Canceled?这是在哪里发生的? @oculus。 IS_IPAD 定义如下:#define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) @Rog,UIWebView 位于添加到导航控制器的视图中,当计时器到期时(因为从未调用过 webViewDidFinishLoad),我有一个设置标题的方法导航控制器“取消”并关闭视图控制器。 【参考方案1】:

圣牛。我想通了。

好的,在我说出我的发现之前,我确实想更正我自己原来的措辞:模态广告从未在模拟器中工作过,但总是在设备上工作。我知道模拟器可能有它的怪癖,所以我从来没有想过它,特别是因为它总是在设备上工作。我知道这是本次讨论中缺少的一个重要细节,但我从事这个项目已经有几个星期了,直到今天我都忘记了。

那么……在修补东西时,我注意到 AdView.xib 不在我的项目文件列表中。我扩展了几个文件夹,以为它可能被意外拖入其中一个,但根本没有列出。不过,这确实让我感到困惑——Xcode 从不抱怨缺少资源(没有警告或错误;总是完美的编译)。

所以,我导航到物理位置并将 AdView.xib 添加到项目中。现在,模态广告在模拟器中显示,这是第一次。我认为既然现在应用程序在模拟器中正常工作,它应该在分发构建中工作正常(奇怪的相关性,但在我的更新到达 App Store 之前,这就是我得到的全部)。

显然,我将提交更新,所以在更新到达 App Store 之前我不会接受我自己的答案(假设我实际上已经修复了它)。

【讨论】:

App昨天通过了,问题就解决了。仍然对丢失的 XIB 一直被忽视感到恼火。【参考方案2】:

好的,这是一个非常长的镜头,但也许值得考虑。

关于 initWithContentsOfURL 的docs for NSData 状态“返回的对象可能与原始接收者不同。”因此,如果它 一个不同的对象,并且实际上是自动释放的,请考虑代码中的这一行:

adData = [[NSData alloc] initWithContentsOfURL:adURL];

这不会为 adData 添加保留计数 - 您没有编写 self.adData = 或类似内容。因此,请记住所提到的场景,即返回的 NSData 被自动释放:您的方法 downloadAdData 将其内容包装在 NSAutoreleasePool 中。这是正确的做法。但是,这可能会导致在主线程上调用 presentAdModal 之前释放 adData。所以...

在 presentAdModal 中,您只需检查 adData 是否为 nil ——但它可以不是 nil,并且此时您的 NSAutoreleasePool 仍已从内存中释放——因此,您这种情况会触发“显示 Web 视图”代码,但会尝试加载已被丢弃的 NSData 对象。这可能会包含完整的垃圾,因此没有成功的“加载 Web 视图”调用。

正如我所说,这是一个远射,但在这一点上唯一让我跳出来的东西。

更新:

您的问题的一个完全不同的原因可能是:

由于 IP 阻塞或那里的任何网络设置,您的测试环境(即非 App-Store 构建)正在从有权访问包含广告的网络服务器的互联网的某个部分(即您的办公室)发出请求是,而您的 App Store 发布版本正在尝试从互联网的某些部分访问广告服务器,这是被禁止的。同样,可能并非如此,但值得一提。

【讨论】:

下载广告 HTML 从未出现过问题。但是,为了测试您的第一个想法,我将 adData 转换为字符串并将其打印在 presentAdModal 中的 if(adData) 之前,并且 HTML 在控制台中,但 UIWebView 没有加载。好想,不过!值得一试。

以上是关于UIWebView 在应用商店版本中的行为与开发版本不同的主要内容,如果未能解决你的问题,请参考以下文章

ionic v3 build IOS 上传到应用商店时出现“UIWebView”错误

UImenucontroller 在 App Store 中的行为与在开发中的行为不同

Windows10 LTSB/LTSC版安装应用商店与UWP

您是未出现在 Google Play 商店中的此应用的 Beta 版测试人员

与 Safari/Chrome 相比,相同 URL 的 UIWebView 行为不同

iOS H5容器的一些探究:UIWebView和WKWebView的比较和选择