在 applicationDidEnterBackground 中添加的视图直到 app returns 从后台不可见
View added in applicationDidEnterBackground not visible until app returns from background
我在 applicationDidEnterBackground:
中将 imageView 添加到我的应用程序的主 window
- (void)applicationDidEnterBackground:(UIApplication *)application
{
UIImageView *splash = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"splashimage.png"]];
splash.frame = self.window.bounds;
[self.window addSubview:splash];
}
我希望当我按下设备的主页按钮将应用程序置于后台,然后双击主页按钮查看任务管理器时,我会看到 splashimage.png 显示。但似乎应用程序进入后台时截取的屏幕截图不包括此叠加 imageView。我认为它会,因为我添加了没有动画的 imageView。
为什么会发生这种情况?
更新:即使我在 applicationDidEnterBackground 中隐藏我的 window,我仍然可以在应用程序进入后台状态后在任务管理器中看到完整的 window,未隐藏。当我按下主页按钮时,window 只会在应用程序 returns 之后从后台隐藏片刻。
- (void)applicationDidEnterBackground:(UIApplication *)application
{
//this does not work either!
self.window.hidden = YES;
}
更新:顺便说一下,我明白 applicationDidEnterBackground 有 5 秒的时间来完成。我现在只用
测试这个
self.window.hidden = YES;
在 applicationDidEnterBackground 中,applicationWillResignActive 中没有任何内容,并且当应用程序进入后台时 window 仍然没有隐藏;只有当它returns到前台时。所以这告诉我,我的应用程序中一定有其他东西不允许在 applicationDidEnterBackground 中发生这种情况。顺便说一下,如果我移动
self.window.hidden = YES;
对于 applicationWillResignActive,当应用程序进入后台时 window 是隐藏的。但我试图弄清楚什么会阻止应用程序在 applicationDidEnterBackground 中完成这个单一的、简单的、非动画的任务。任何想法表示赞赏。
更新:此特定问题与使用 BannerViewController (iAd) 有关。我在 UITabBarController 中使用它。还不确定到底是什么问题,或者它是否也与它在 UITabBarController 中的使用有关。
更新:我认为这个问题与 UITabBarController 无关,但通常与 BannerViewController (iAd) 有关。现在明白为什么...
更新:BannerViewController.m 中的这一行导致了问题:
[self.view addSubview:bannerView]
在这个方法中:
- (void)viewDidLayoutSubviews
{
CGRect contentFrame = self.view.bounds, bannerFrame = CGRectZero;
ADBannerView *bannerView = [BannerViewManager sharedInstance].bannerView;
#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_6_0
NSString *contentSizeIdentifier;
// If configured to support iOS <6.0, then we need to set the currentContentSizeIdentifier in order to resize the banner properly.
// This continues to work on iOS 6.0, so we won't need to do anything further to resize the banner.
if (contentFrame.size.width < contentFrame.size.height) {
contentSizeIdentifier = ADBannerContentSizeIdentifierPortrait;
} else {
contentSizeIdentifier = ADBannerContentSizeIdentifierLandscape;
}
bannerFrame.size = [ADBannerView sizeFromBannerContentSizeIdentifier:contentSizeIdentifier];
#else
// If configured to support iOS >= 6.0 only, then we want to avoid currentContentSizeIdentifier as it is deprecated.
// Fortunately all we need to do is ask the banner for a size that fits into the layout area we are using.
// At this point in this method contentFrame=self.view.bounds, so we'll use that size for the layout.
bannerFrame.size = [_bannerView sizeThatFits:contentFrame.size];
#endif
if (bannerView.bannerLoaded) {
contentFrame.size.height -= bannerFrame.size.height;
bannerFrame.origin.y = contentFrame.size.height;
} else {
bannerFrame.origin.y = contentFrame.size.height;
}
_contentController.view.frame = contentFrame;
// We only want to modify the banner view itself if this view controller is actually visible to the user.
// This prevents us from modifying it while it is being displayed elsewhere.
if (self.isViewLoaded && (self.view.window != nil)) {
[self.view addSubview:bannerView];
bannerView.frame = bannerFrame;
#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_6_0
bannerView.currentContentSizeIdentifier = contentSizeIdentifier;
#endif
}
}
不确定为什么或什么,如果我仍然想使用 BannerViewController 可以采取任何措施来修复它。
更新:从下面接受的答案,这就是为我解决这个问题的方法(bannerVC 是对 BannerViewController 的引用)。
- (void)applicationWillResignActive:(UIApplication *)application {
[bannerVC.view snapshotViewAfterScreenUpdates:YES];
}
更新:我意识到这段代码确实应该在 applicationDidEnterBackground 中。但是,AdBannerView 似乎没有办法及时停止动画,这样就可以发生这种情况。所以现在,根据我的理解,applicationWillResignActive 就是剩下的,但它给用户留下了 'less-than' 体验。我将不胜感激有关如何停止 AdBannerView 动画的任何建议,以便快照可以显示在 applicationDidEnterBackground 中,而不仅仅是从后台返回时。
更新:
要重现问题:
- 下载iAdSuite
- 打开 TabbedBanner 示例。
- 将下面的代码添加到 AppDelegate:
- 运行 应用程序。 (帧乱了,因为它还没有更新,但这个例子仍然会显示问题)
- 点击主页按钮一次可将应用置于后台。
- 双击主页按钮可在任务管理器中查看该应用程序。
如果您对 applicationWillResignActive 中的代码进行了注释,而对 applicationDidEnterBackground 中的代码未进行注释,您将不会在任务管理器中看到蓝色启动画面。但是,如果您已注释掉 applicationDidEnterBackground 中的代码并取消注释 applicationWillResignActive 中的代码,您应该会在任务管理器中看到蓝色启动画面。然而,这是不可取的。问题是如何在 applicationDidEnterBackground 方法中显示启动画面。
- (void)applicationWillResignActive:(UIApplication *)application {
//works - but undesirable
//[self addDummyView];
//[_tabBarController.view snapshotViewAfterScreenUpdates:YES];
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
//does not work - needs to work to show dummyview only when application actually goes into the background
[self addDummyView];
[_tabBarController.view snapshotViewAfterScreenUpdates:YES];
}
- (void)addDummyView {
UIView *topView = _tabBarController.view;
UIView *colorView = [[UIView alloc] initWithFrame:topView.frame];
[colorView setBackgroundColor:[UIColor blueColor]];
[topView addSubview:colorView];
[topView bringSubviewToFront:colorView];
}
你的代码没问题。你应该知道当你双击主页按钮时 applicationDidEnterBackground
不会被调用。当您切换到另一个应用程序或转到跳板时调用它。
所以,您应该只按一次主页按钮,然后双击它,您的应用程序的屏幕截图应该有图像视图。我在测试项目中复制了您的用例,它对我有用。
如果还是不行,你应该看看imageview的image是不是nil。哦,请不要隐藏应用程序 window。
当 applicationDidEnterBackground 方法 returns 时,应用程序当前视图的快照被用于多任务视图。您看不到更新的原因是快照是在绘图周期之前拍摄的。即使您调用 setNeedsDisplay 之前仍然拍摄快照。
要等到视图更新(在添加子视图之后),请调用:
[self.view snapshotViewAfterScreenUpdates:YES];
值为 YES
。这会强制您的更改首先呈现。您可以在此处的苹果文档中阅读有关处理此类内容的更多信息:https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/StrategiesforHandlingAppStateTransitions/StrategiesforHandlingAppStateTransitions.html#//apple_ref/doc/uid/TP40007072-CH8-SW27
你可以在这里得到答案:Show splash screen when application enters background。
将您的代码保存在 applicationWillResignActive 中。
我在 applicationDidEnterBackground:
中将 imageView 添加到我的应用程序的主 window- (void)applicationDidEnterBackground:(UIApplication *)application
{
UIImageView *splash = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"splashimage.png"]];
splash.frame = self.window.bounds;
[self.window addSubview:splash];
}
我希望当我按下设备的主页按钮将应用程序置于后台,然后双击主页按钮查看任务管理器时,我会看到 splashimage.png 显示。但似乎应用程序进入后台时截取的屏幕截图不包括此叠加 imageView。我认为它会,因为我添加了没有动画的 imageView。
为什么会发生这种情况?
更新:即使我在 applicationDidEnterBackground 中隐藏我的 window,我仍然可以在应用程序进入后台状态后在任务管理器中看到完整的 window,未隐藏。当我按下主页按钮时,window 只会在应用程序 returns 之后从后台隐藏片刻。
- (void)applicationDidEnterBackground:(UIApplication *)application
{
//this does not work either!
self.window.hidden = YES;
}
更新:顺便说一下,我明白 applicationDidEnterBackground 有 5 秒的时间来完成。我现在只用
测试这个self.window.hidden = YES;
在 applicationDidEnterBackground 中,applicationWillResignActive 中没有任何内容,并且当应用程序进入后台时 window 仍然没有隐藏;只有当它returns到前台时。所以这告诉我,我的应用程序中一定有其他东西不允许在 applicationDidEnterBackground 中发生这种情况。顺便说一下,如果我移动
self.window.hidden = YES;
对于 applicationWillResignActive,当应用程序进入后台时 window 是隐藏的。但我试图弄清楚什么会阻止应用程序在 applicationDidEnterBackground 中完成这个单一的、简单的、非动画的任务。任何想法表示赞赏。
更新:此特定问题与使用 BannerViewController (iAd) 有关。我在 UITabBarController 中使用它。还不确定到底是什么问题,或者它是否也与它在 UITabBarController 中的使用有关。
更新:我认为这个问题与 UITabBarController 无关,但通常与 BannerViewController (iAd) 有关。现在明白为什么...
更新:BannerViewController.m 中的这一行导致了问题:
[self.view addSubview:bannerView]
在这个方法中:
- (void)viewDidLayoutSubviews
{
CGRect contentFrame = self.view.bounds, bannerFrame = CGRectZero;
ADBannerView *bannerView = [BannerViewManager sharedInstance].bannerView;
#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_6_0
NSString *contentSizeIdentifier;
// If configured to support iOS <6.0, then we need to set the currentContentSizeIdentifier in order to resize the banner properly.
// This continues to work on iOS 6.0, so we won't need to do anything further to resize the banner.
if (contentFrame.size.width < contentFrame.size.height) {
contentSizeIdentifier = ADBannerContentSizeIdentifierPortrait;
} else {
contentSizeIdentifier = ADBannerContentSizeIdentifierLandscape;
}
bannerFrame.size = [ADBannerView sizeFromBannerContentSizeIdentifier:contentSizeIdentifier];
#else
// If configured to support iOS >= 6.0 only, then we want to avoid currentContentSizeIdentifier as it is deprecated.
// Fortunately all we need to do is ask the banner for a size that fits into the layout area we are using.
// At this point in this method contentFrame=self.view.bounds, so we'll use that size for the layout.
bannerFrame.size = [_bannerView sizeThatFits:contentFrame.size];
#endif
if (bannerView.bannerLoaded) {
contentFrame.size.height -= bannerFrame.size.height;
bannerFrame.origin.y = contentFrame.size.height;
} else {
bannerFrame.origin.y = contentFrame.size.height;
}
_contentController.view.frame = contentFrame;
// We only want to modify the banner view itself if this view controller is actually visible to the user.
// This prevents us from modifying it while it is being displayed elsewhere.
if (self.isViewLoaded && (self.view.window != nil)) {
[self.view addSubview:bannerView];
bannerView.frame = bannerFrame;
#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_6_0
bannerView.currentContentSizeIdentifier = contentSizeIdentifier;
#endif
}
}
不确定为什么或什么,如果我仍然想使用 BannerViewController 可以采取任何措施来修复它。
更新:从下面接受的答案,这就是为我解决这个问题的方法(bannerVC 是对 BannerViewController 的引用)。
- (void)applicationWillResignActive:(UIApplication *)application {
[bannerVC.view snapshotViewAfterScreenUpdates:YES];
}
更新:我意识到这段代码确实应该在 applicationDidEnterBackground 中。但是,AdBannerView 似乎没有办法及时停止动画,这样就可以发生这种情况。所以现在,根据我的理解,applicationWillResignActive 就是剩下的,但它给用户留下了 'less-than' 体验。我将不胜感激有关如何停止 AdBannerView 动画的任何建议,以便快照可以显示在 applicationDidEnterBackground 中,而不仅仅是从后台返回时。
更新: 要重现问题:
- 下载iAdSuite
- 打开 TabbedBanner 示例。
- 将下面的代码添加到 AppDelegate:
- 运行 应用程序。 (帧乱了,因为它还没有更新,但这个例子仍然会显示问题)
- 点击主页按钮一次可将应用置于后台。
- 双击主页按钮可在任务管理器中查看该应用程序。
如果您对 applicationWillResignActive 中的代码进行了注释,而对 applicationDidEnterBackground 中的代码未进行注释,您将不会在任务管理器中看到蓝色启动画面。但是,如果您已注释掉 applicationDidEnterBackground 中的代码并取消注释 applicationWillResignActive 中的代码,您应该会在任务管理器中看到蓝色启动画面。然而,这是不可取的。问题是如何在 applicationDidEnterBackground 方法中显示启动画面。
- (void)applicationWillResignActive:(UIApplication *)application {
//works - but undesirable
//[self addDummyView];
//[_tabBarController.view snapshotViewAfterScreenUpdates:YES];
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
//does not work - needs to work to show dummyview only when application actually goes into the background
[self addDummyView];
[_tabBarController.view snapshotViewAfterScreenUpdates:YES];
}
- (void)addDummyView {
UIView *topView = _tabBarController.view;
UIView *colorView = [[UIView alloc] initWithFrame:topView.frame];
[colorView setBackgroundColor:[UIColor blueColor]];
[topView addSubview:colorView];
[topView bringSubviewToFront:colorView];
}
你的代码没问题。你应该知道当你双击主页按钮时 applicationDidEnterBackground
不会被调用。当您切换到另一个应用程序或转到跳板时调用它。
所以,您应该只按一次主页按钮,然后双击它,您的应用程序的屏幕截图应该有图像视图。我在测试项目中复制了您的用例,它对我有用。
如果还是不行,你应该看看imageview的image是不是nil。哦,请不要隐藏应用程序 window。
当 applicationDidEnterBackground 方法 returns 时,应用程序当前视图的快照被用于多任务视图。您看不到更新的原因是快照是在绘图周期之前拍摄的。即使您调用 setNeedsDisplay 之前仍然拍摄快照。
要等到视图更新(在添加子视图之后),请调用:
[self.view snapshotViewAfterScreenUpdates:YES];
值为 YES
。这会强制您的更改首先呈现。您可以在此处的苹果文档中阅读有关处理此类内容的更多信息:https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/StrategiesforHandlingAppStateTransitions/StrategiesforHandlingAppStateTransitions.html#//apple_ref/doc/uid/TP40007072-CH8-SW27
你可以在这里得到答案:Show splash screen when application enters background。
将您的代码保存在 applicationWillResignActive 中。