【iOS】iOS13后新增的Scene Delegate和不使用工程自帶的Main.storyboard


一、Scene Delegate
在之前我們對AppDelegate已經很熟悉,它是iOS app的入口,application(_:didFinishLaunchingWithOptions:)是我們app啟動后系統調用的第一個函數。AppDelegate類實現了UIKit庫中的UIApplicationDelegate 協議。而到了iOS13 AppDelegate的角色將會發生變化,后面我們會詳細討論。

在iOS13之前我們一般會在AppDelegate中做的事情:
1.創建app的第一個view controller也就是 rootViewController
2.配置並啟動一些像日志記錄和雲服務之類的組件
3.注冊推送通知處理程序,並響應發送到app的推送通知
4.響應應用程序生命周期事件,例如進入后台,恢復應用程序或退出應用程序(終止)
但是在iOS13后,AppDelegate文件結構也發生變化,在AppDelegate.h文件中沒有了window屬性,而是在sceneDelegate.h中,可見AppDelegate不管理window而是交給SceneDelegate。

#pragma mark - UISceneSession lifecycle

/*
1.如果沒有在APP的Info.plist文件中包含scene的配置數據,或者要動態更改場景配置數據,需要實現此方法。 UIKit會在創建新scene前調用此方法。
2.方法會返回一個UISceneConfiguration對象,其包含其中包含場景詳細信息,包括要創建的場景類型,用於管理場景的委托對象以及包含要顯示的初始視圖控制器的情節提要。 如果未實現此方法,則必須在應用程序的Info.plist文件中提供場景配置數據。

總結下:默認在info.plist中進行了配置, 不用實現該方法也沒有關系。如果沒有配置就需要實現這個方法並返回一個UISceneConfiguration對象。
配置參數中Application Session Role 是個數組,每一項有三個參數:
Configuration Name:   當前配置的名字;
Delegate Class Name:  與哪個Scene代理對象關聯;
StoryBoard name: 這個Scene使用的哪個storyboard。
注意:代理方法中調用的是配置名為Default Configuration的Scene,則系統就會自動去調用SceneDelegate這個類。這樣SceneDelegate和AppDelegate產生了關聯。
*/

//參數options是一個UISceneConnectionOptions類,官方解釋:它包含了為什么要創建一個新的scene的信息。根據參數信息判斷是否要創建一個新的scene
- (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options {
    // Called when a new scene session is being created.
    // Use this method to select a configuration to create the new scene with.
    return [[UISceneConfiguration alloc] initWithName:@"Default Configuration" sessionRole:connectingSceneSession.role];
}

// 在分屏中關閉其中一個或多個scene時候回調用
- (void)application:(UIApplication *)application didDiscardSceneSessions:(NSSet<UISceneSession *> *)sceneSessions {
    // Called when the user discards a scene session.
    // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
    // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
}

SceneDelegate 生命周期

- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
    NSLog(@"場景加載完成");
// iOS 12上的 application(_:didFinishLaunchingWithOptions:) 函數的作用最相似。當將場景添加到app中時scene(_:willConnectTo:options:)函數會被調用的。
}
- (void)sceneDidDisconnect:(UIScene *)scene {
    NSLog(@"場景已經斷開連接");
// (注意,以后它可能被重新連接)
}
- (void)sceneDidBecomeActive:(UIScene *)scene {
    NSLog(@"已經從后台進入前台 ");
//(例如從應用切換器中選擇場景)
}
- (void)sceneWillResignActive:(UIScene *)scene {
    NSLog(@"即將從前台進入后台");
//(例如通過切換器切換到另一個場景)
}
- (void)sceneWillEnterForeground:(UIScene *)scene {
    NSLog(@"即將從后台進入前台");
}
- (void)sceneDidEnterBackground:(UIScene *)scene {
    NSLog(@"已經從前台進入后台");
}

綜合上面所述,我們發現這個新代理只在iOS13之后才會出現,而且也只在iPad中才會用到。如果我們不支持多窗口,所以我們可以移除這個新的代理,並按照之前的習慣進行開發。

1.直接刪除Scene Delegate.h/.m文件
2.在AppDelegate.h添加@property (strong, nonatomic) UIWindow * window;屬性 
3移除Appdelegate中的UIScene代理
4.在info.plist文件中移除Application Scene Manifest

但是如果支持的話,那么老的AppDelegate管理生命周期的方法將不會有效,需要使用SceneDelgate中的UIScene提供的生命周期方法。

如何開啟分屏多窗口顯示?
1.第一步:Xcode的配置-開啟支持多屏scene

2.info.plist文件進行修改,勾選分屏,enable Multipe Windows 設置為YES.

參考:文章一
文章二

二、不使用工程自帶的Main.storyboard
在Xcode中新建工程,一般都會帶有默認的Main.storyboard方便我們進行快捷開發。但是在日常開發中,我們很少使用它。那么如何刪除呢?
步驟如下:
(1)在工程配置中移除main的關聯

(2)移除main.storuboard中的關聯

(3)刪除main.storyboard文件
(4)在info.plist中的查看是否有main的殘留和刪除在scene中的storyboardname
(5)如果是不支持scene就在AppDelegate中添加代碼。如果支持就在SceneDelegate中添加代碼。

// app delegate
 self.window = [[UIWindow alloc]initWithFrame:[UIScreen mainScreen].bounds];
    self.window.rootViewController = [[MainTabBarController alloc] init];
    [self.window makeKeyAndVisible];


// secnedelegate
if (scene) {
        UIWindowScene *windowSecne = (UIWindowScene*)scene;
        self.window = [[UIWindow alloc] initWithWindowScene:windowSecne];
        self.window.frame = windowSecne.coordinateSpace.bounds;
        self.window.rootViewController = [ViewController new];
        [self.window makeKeyAndVisible];
    }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM