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

时间:2011-02-25 22:09:30

标签: iphone ipad ios uiwebview modal-dialog

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

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

然而,App Store的分发版本不同。当模态视图控制器向上滑动时,UIWebView永远不会加载。请记住,如果能够下载广告数据,我只会提供视图控制器 - 否则,视图永远不会显示。

值得庆幸的是,我在广告视图控制器中实现了一个计时器,如果webViewDidFinishLoad永远不会触发(其中计时器无效),将导致模态视图自行解除,因此至少app用户不会太烦恼。但是,让一个空的视图控制器向上滑动然后滑动显然没有理由仍然是丑陋的。

以下是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];

同样,这一切都可以完美地运行,每次都可以在模拟器和物理设备中使用dev / release构建 - 而不是从应用程序商店进行分发构建。我甚至已经将NSData转换为NSString并使用NSLog()进行了禁止,以证明在以模态方式呈现AdView之前已下载HTML。

[叹息...]

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

编辑2 :此外,就在我致电

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

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

2 个答案:

答案 0 :(得分:2)

HOLY COW。我明白了。

好吧,在我说出我找到的内容之前,我确实想要纠正我自己的原始措辞:模态广告从未在模拟器中工作,但始终在设备上。我知道模拟器可以有它的怪癖,所以我从来没有想过它,特别是因为它总是在设备上工作。我知道这是一个重要的细节,但是这次讨论还没有,但是自从我参与这个项目以来已经过了几个星期,直到今天我都忘了这一切。

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

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

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

答案 1 :(得分:0)

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

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

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

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

在presentAdModal中你只检查adData不是nil - 但它可能不是nil,并且当时你的NSAutoreleasePool仍然从内存中释放 - 因此,你 in这种情况会触发“显示Web视图”代码,但会尝试加载已被删除的NSData对象。这可能包含完整的垃圾,因此没有成功的“网络视图加载”调用。

就像我说的那样,一个很长的镜头,但是在这一点上突然出现在我身上的东西。

<强>更新

问题的完全不同可能是:

您的测试环境(即非App-Store版本)正在从互联网的某个部分(即您的办公室)发出请求,该部分有权访问包含广告的Web服务器,因为IP阻止或任何网络设置是的,而您的App Store版本正在尝试从禁止的互联网部分访问广告服务器。再说一次,可能不是这样,但值得一提。