每次应用程序激活时显示启动画面

Show splash screen each time app becomes active

我希望每次应用程序激活时都显示启动画面。我创建了一个函数 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];
}

但是没有出现启动画面。请指正。

请确保您的 window 根视图控制器主视图在您想要显示启动画面的那一刻是您应用程序中最顶层的视图...

检查 splashScreen (UIImageView) 的框架。将其框架设置为根视图控制器的边界。

您可以尝试 寻找 像这样的递归顶视图控制器:

- (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] 应该 return 您应用的当前 visible/top VC,您可以这样做:

[[self findTopViewController].view addSubview:splashScreen];
...

如果您希望应用程序在您每次返回时都有一个全新的开始,您还可以禁用后台执行,如 Apple Documentation 中所述(最后一节标题为 "Opting Out of Background Execution"):

If you do not want your app to run in the background at all, you can explicitly opt out of background by adding the UIApplicationExitsOnSuspend key (with the value YES) to your app’s Info.plist file.

你可以这样做:

#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

您应该使用以下行:

[self.window addSubview: splashScreen];

而不是

[self.window.rootViewController.view addSubview: splashScreen];

每次正常启动您的应用程序,在 applicationBecomeActive 中调用您的方法,并在 Appdelegate.window 上添加您的图像视图,并在一段时间后通过计时器将其删除。

[self.window addSubview: splashScreen];

这个解决方案有点麻烦,但效果很好。这个想法是在所有控制器

之上添加新的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];
    }];
}

请在下方找到此问题的解决方案。

将启动画面代码拆分为两个方法; showSplashhideSplash.

在方法applicationWillResignActive中调用showSplash。在方法中,创建并添加 imageViewrootViewController;将它的 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];
}

希望对您有所帮助! :-)

添加

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");
                     }
     ];
}

实现此目的的最佳方法是在 AppDelegate's window 中添加图像。 在下面的代码中,statusView 是视图之一,由一些图像组成。所以将它作为 subView

添加到您的 AppDelegate's window
[[[[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];
}

应用启动后,您可以在一段时间内显示实际的启动画面,然后显示您通常的应用状态。

首先在 didFinishLaunchingWithOptions 函数中创建您的启动屏幕或图像。

之后像这样写你的代码-

添加初始视图后 - 将其置于最前面

改变

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

根视图控制器并不总是呈现的视图控制器。这可能会导致您的启动画面隐藏在一堆其他视图控制器下。尝试使用类似 (swift syntex):

func getTopViewController() -> UIViewController?{
    if var topController = UIApplication.sharedApplication().keyWindow?.rootViewController{
        while ((topController.presentedViewController) != nil) {
            topController = topController.presentedViewController!
        }
        return topController
    }
    return nil
}

并将启动视图添加到顶视图控制器

您可以重复使用 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()
    }