每次应用激活时显示启动画面
Posted
技术标签:
【中文标题】每次应用激活时显示启动画面【英文标题】:Show splash screen each time app becomes active 【发布时间】:2015-05-05 17:18:59 【问题描述】:我希望每次应用激活时都显示启动画面。我创建了一个函数showSplash
,我调用了applicationDidBecomeActive:
-(void)showSplash
UIImageView *splashScreen = [[UIImageView alloc] initWithImage:[UIImage imageNamed: @"Default.png"]];
[self.window.rootViewController.view addSubview: splashScreen];
[self.window makeKeyAndVisible];
NSLog(@"begin splash");
[UIView animateWithDuration: 4.2
delay: 0.5
options: UIViewAnimationOptionCurveEaseOut
animations: ^
splashScreen.alpha = 0.0;
completion: ^ (BOOL finished)
[splashScreen removeFromSuperview];
NSLog(@"end splash");
];
这就是我调用这个函数的方式:
- (void)applicationDidBecomeActive:(UIApplication *)application
[self showSplash];
但没有出现启动画面。请纠正我。
【问题讨论】:
您看到正在打印的日志消息了吗? @PhillipMills:是的。它们被打印出来,但从不显示启动画面。 @Nitish 也许您想使用启动 xib 或故事板。看看useyourloaf.com/blog/2014/12/24/… @devgr :这对在应用程序激活时显示启动画面有何帮助? @BlakeMerryman :我完全意识到这一点。不过谢谢。这是我正在开发的产品,而不是 AppStore 应用程序。 【参考方案1】:如果您希望应用程序在每次返回时都重新开始,您还可以禁用后台执行,如 Apple Documentation 中所述(最后一节标题为“退出后台执行”):
如果您根本不希望您的应用在后台运行,您可以 通过添加显式选择退出后台 UIApplicationExitsOnSuspend 键(值为 YES)到您应用的 Info.plist 文件。
【讨论】:
这是一个很好的观点。谢谢。但我只希望每次都出现飞溅。应用程序的其余部分保持在后台时的状态。【参考方案2】:添加启动视图后 - 将其置于前面
改变
UIImageView *splashScreen = [[UIImageView alloc] initWithImage:[UIImage imageNamed: @"Default.png"]];
[self.window.rootViewController.view addSubview: splashScreen];
[self.window makeKeyAndVisible];
到
UIImageView *splashScreen = [[UIImageView alloc] initWithImage:[UIImage imageNamed: @"Default.png"]];
[self.window addSubview: splashScreen];
[self.window bringSubviewToFront: splashScreen]; //!
[self.window makeKeyAndVisible];
【讨论】:
【参考方案3】:请确保您的窗口根视图控制器主视图在您想要显示启动画面的那一刻是您应用中最顶层的视图...
【讨论】:
【参考方案4】:检查 splashScreen (UIImageView) 的框架。将其框架设置为根视图控制器的边界。
【讨论】:
【参考方案5】:您可以尝试使用这样的递归搜索顶视图控制器:
- (UIViewController *)findTopViewController
return [self topViewControllerFrom:self.window.rootViewController];
- (UIViewController *)topViewControllerFrom:(UIViewController *)vc
if (vc.navigationController.visibleViewController != nil)
return [self topViewControllerFrom:vc.navigationController.visibleViewController];
if (vc.tabBarController.selectedViewController != nil)
return [self topViewControllerFrom:vc.tabBarController.selectedViewController];
return vc;
现在调用 [self findTopViewController]
应该有望返回您应用的当前可见/*** VC,您可以这样做:
[[self findTopViewController].view addSubview:splashScreen];
...
【讨论】:
谢谢,但没有显示。这是我根据您所做的更改: UIImageView *splashScreen = [[UIImageView alloc] initWithImage:[UIImage imageNamed: @"Default.png"]]; [[self findTopViewController].view addSubview:splashScreen]; [self.window makeKeyAndVisible]; 尝试在applicationDidBecomeActive
上设置一个断点,然后当它中断时在控制台中运行:po [self findTopViewController]
,你得到一个视图控制器还是nil
?
是的,这返回了 nil。但即使我得到了我在 didFinishLaunchingWithOptions 中的 rootViewController - UIViewController *rootViewController = [storyboard instantiateViewControllerWithIdentifier:@"ProjectsController"];根控制器 = 根视图控制器;还是不行。
在调用[storyboard instantiateViewControllerWithIdentifier...
之后你是否在调用self.window.rootViewController = rootViewController
之类的东西?
@Nitish 你有没有尝试像 splashScreen.frame=rootViewController.bounds 这样设置启动画面图像视图的框架?【参考方案6】:
你可以这样做:
#import "AppDelegate.h"
#define kSplashScreen (UIScreen.mainScreen.bounds.size.height == 568) ? @"Default-568h" \
: (UIScreen.mainScreen.bounds.size.height == 667) ? @"Default-667" \
: (UIScreen.mainScreen.bounds.size.height == 736) ? @"Default-Portrait" \
: @"Default"
@interface AppDelegate ()
@property (nonatomic) UIWindow *splashWindow;
@property (nonatomic) UIWindow *keyWindow;
@property (nonatomic, getter=isSplashConfigured) BOOL splashConfigured;
@property (nonatomic, getter=isShowingSplash) BOOL showingSplash;
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
[self animateSplash];
return YES;
- (void)applicationDidEnterBackground:(UIApplication *)application
[self showOrHideSplash];
- (void)applicationWillEnterForeground:(UIApplication *)application
[self showOrHideSplash];
- (void)showOrHideSplash
[self.splashWindow setHidden:[self isShowingSplash]];
if ([self isShowingSplash])
[self.keyWindow makeKeyAndVisible];
else
[self.splashWindow makeKeyAndVisible];
[self animateSplash];
self.showingSplash = !self.showingSplash;
- (void)animateSplash
if ([self isSplashConfigured])
[self.window.rootViewController.view addSubview:self.splashWindow];
[self.window makeKeyAndVisible];
else
self.keyWindow = [[UIApplication sharedApplication] keyWindow];
self.splashWindow = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.splashWindow.rootViewController = [[UIViewController alloc] init];
self.splashWindow.rootViewController.view.frame = self.splashWindow.bounds;
UIImageView *splashImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:kSplashScreen]];
splashImage.frame = self.splashWindow.bounds;
[self.splashWindow.rootViewController.view addSubview:splashImage];
[self.splashWindow makeKeyAndVisible];
[self.splashWindow setHidden:YES];
self.splashConfigured = YES;
NSLog(@"begin splash");
__weak AppDelegate* weakSelf = self;
[UIView animateWithDuration:4.2 delay:0.5 options:UIViewAnimationOptionCurveEaseOut animations: ^
weakSelf.splashWindow.alpha = 1.0;
weakSelf.splashWindow.alpha = 0.0;
completion: ^(BOOL finished)
[weakSelf.splashWindow removeFromSuperview];
NSLog(@"end splash");
];
@end
【讨论】:
【参考方案7】:这是一个有点麻烦的解决方案,但它工作正常。这个想法是在所有控制器之上添加新的UIWindow
- (void)showSplash
id <UIApplicationDelegate> appDelegate = [[UIApplication sharedApplication] delegate];
UIWindow *window = [[UIWindow alloc] initWithFrame:[appDelegate window].frame];
UIViewController *splashController = [UIViewController new];
UIImageView *imgView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"Default.png"]];
splashController.view = imgView;
window.rootViewController = splashController;
window.windowLevel = UIWindowLevelAlert;
window.hidden = NO;
[window makeKeyAndVisible];
[UIView animateWithDuration:4.2 delay:0.5 options:UIViewAnimationOptionCurveEaseOut animations:^
window.alpha = 0.0;
completion:^(BOOL finished)
window.hidden = YES;
window.rootViewController = nil;
[[appDelegate window] makeKeyAndVisible];
[[appDelegate window] setNeedsDisplay];
];
【讨论】:
【参考方案8】:请在下面找到此问题的解决方案。
将闪屏代码拆分成两种方法; showSplash
和 hideSplash
。
在方法applicationWillResignActive
中调用showSplash
。在方法中,创建imageView
并将其添加到rootViewController
;将其 alpha 设置为 0.0f,然后将其设置为 alpha 1.0f。这是为了确保当应用程序进入后台时用户看不到 imageView。
现在在applicationDidBecomeActive
中致电hideSplash
。在hideSplash
中删除带有动画的imageView。请看下面的代码;
-(void)showSplash
_splashScreen = [[UIImageView alloc] initWithImage:[UIImage imageNamed: @"Default"]];
[self.window.rootViewController.view addSubview:_splashScreen];
_splashScreen.alpha = 0.0f;
[UIView animateWithDuration:0.3f animations:^
_splashScreen.alpha = 1.0f;
];
- (void)hideSplash
[UIView animateWithDuration: 4.2
delay: 0.5
options: UIViewAnimationOptionCurveEaseOut
animations: ^
_splashScreen.alpha = 0.0;
completion: ^ (BOOL finished)
[_splashScreen removeFromSuperview];
NSLog(@"end splash");
];
- (void)applicationWillResignActive:(UIApplication *)application
[self showSplash];
- (void)applicationDidBecomeActive:(UIApplication *)application
[self hideSplash];
我希望这会有所帮助! :-)
【讨论】:
【参考方案9】:添加
splashScreen.frame = self.window.rootViewController.view.frame;
下面
UIImageView *splashScreen = [[UIImageView alloc] initWithImage:[UIImage imageNamed: @"alertBg.png"]];
例子
-(void)showSplash
UIImageView *splashScreen = [[UIImageView alloc] initWithImage:[UIImage imageNamed: @"Default.png"]];
splashScreen.frame = self.window.rootViewController.view.frame;
[self.window.rootViewController.view addSubview: splashScreen];
[self.window makeKeyAndVisible];
NSLog(@"begin splash");
[UIView animateWithDuration: 4.2
delay: 0.5
options: UIViewAnimationOptionCurveEaseOut
animations: ^
splashScreen.alpha = 0.0;
completion: ^ (BOOL finished)
[splashScreen removeFromSuperview];
NSLog(@"end splash");
];
【讨论】:
【参考方案10】:实现此目的的最佳方法是将图像添加到AppDelegate's window
。
在下面的代码中statusView
是视图之一,它由一些图像组成。所以将它添加到您的AppDelegate's window
中作为subView
[[[[UIApplication sharedApplication] delegate] window] addSubview:statusView];
现在,只要您希望它显示一段时间,就显示此视图,但同时将其置于前面。
-(void)showStatusView
[UIView animateWithDuration:0.5 animations:^
[[[[UIApplication sharedApplication] delegate] window] bringSubviewToFront:statusView];
statusView.alpha = 1;
];
最好在AppDelegate's
方法didBecomeActive
上调用上述方法。
此外,一旦应用程序将退出活动状态,立即显示启动屏幕。这样,ios 将拍摄屏幕快照,在应用即将激活时显示几秒钟。
- (void)applicationDidEnterBackground:(UIApplication *)application
[self showStatusView];
- (void)applicationWillEnterForeground:(UIApplication *)application
[self showStatusView];
应用启动后,您可以在一段时间内显示实际的初始屏幕,然后显示您通常的应用状态。
【讨论】:
【参考方案11】:首先在didFinishLaunchingWithOptions
函数中创建您的启动屏幕或图像。
这样写你的代码-
【讨论】:
【参考方案12】:根视图控制器并不总是呈现的视图控制器。这可能会导致您的初始屏幕隐藏在一堆其他视图控制器下。尝试使用类似(swift syntex)的东西:
func getTopViewController() -> UIViewController?
if var topController = UIApplication.sharedApplication().keyWindow?.rootViewController
while ((topController.presentedViewController) != nil)
topController = topController.presentedViewController!
return topController
return nil
并将您的启动视图添加到顶部视图控制器
【讨论】:
【参考方案13】:每次正常启动您的应用程序,在applicationBecomeActive中调用您的方法,然后在Appdelegate.window上添加您的图像视图,并在一段时间后通过计时器将其删除。
[self.window addSubview: splashScreen];
【讨论】:
【参考方案14】:您应该使用以下行:
[self.window addSubview: splashScreen];
而不是
[self.window.rootViewController.view addSubview: splashScreen];
【讨论】:
【参考方案15】:您可以重复使用您的launchScreen
来显示而不是显示图像视图。当您有复杂的启动屏幕而不是单个图像作为启动屏幕时,这会很方便。
func applicationWillResignActive(_ application: UIApplication)
guard let window = UIApplication.shared.windows.last,
let launchScreen = UIStoryboard(name: "LaunchScreen", bundle: nil).instantiateInitialViewController(),
let launchView = launchScreen.view else return
launchView.tag = 8888
launchView.frame = window.bounds
launchView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
window.addSubview(launchView)
window.makeKeyAndVisible()
func applicationDidBecomeActive(_ application: UIApplication)
guard let window = UIApplication.shared.windows.last,
let view = window.viewWithTag(8888) else return
view.removeFromSuperview()
【讨论】:
以上是关于每次应用激活时显示启动画面的主要内容,如果未能解决你的问题,请参考以下文章