Xcode 26还没有适配SceneDelegate的app建议尽早适配

Xcode 26之前不需要多窗口的很多app没有适配SceneDelegate,升级到Xcode 26后运行没有问题,但是控制台有以下输出:

swift 复制代码
`UIScene` lifecycle will soon be required. Failure to adopt will result in an assert in the future.

UIApplicationDelegate 中的相关生命周期函数也有弃用标记:

scss 复制代码
/// Tells the delegate that the application has become active 
/// - Note: This method is not called if `UIScene` lifecycle has been adopted. 
- (void)applicationDidBecomeActive:(UIApplication *)application API_DEPRECATED("Use UIScene lifecycle and sceneDidBecomeActive(_:) from UISceneDelegate or the UIApplication.didBecomeActiveNotification instead.", ios(2.0, 26.0), tvos(9.0, 26.0), visionos(1.0, 26.0)) API_UNAVAILABLE(watchos);

建议尽早适配

方案举例

以下是我的适配方案,供大家参考

  • 兼容iOS13以下版本;
  • app只有单窗口场景。

1. 配置Info.plist

Delegate Class Name和Configuration Name 可自定义

2. 配置SceneDelegate

  • 创建SceneDelegate class 类名要和Info.plist中配置一致
  • appDelegate中实现代理
objectivec 复制代码
- (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options  API_AVAILABLE(ios(13.0)){
   //  name要和Info.plist中配置一致
  return [[UISceneConfiguration alloc] initWithName:@"Default Configuration" sessionRole:connectingSceneSession.role];
}

- (void)application:(UIApplication *)application didDiscardSceneSessions:(NSSet<UISceneSession *> *)sceneSessions  API_AVAILABLE(ios(13.0)){
  // 释放资源,单窗口app不用关注
}

3. 新建单例 AppLifecycleHelper 实现AppDelegate和SceneDelgate共享的方法

  • iOS 13 及以上需要在scene: willConnectToSession: options: 方法中创建Window,之前仍然在 didFinishLaunchingWithOptions:

AppDelegate:

less 复制代码
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [AppLifecycleHelper sharedInstance].launchOptions = launchOptions;
     // ... 自定义逻辑
    if (@available(iOS 13, *)) {
 
    } else {
        [[AppLifecycleHelper sharedInstance] createKeyWindow];
    }
}

SceneDelgate:

URL冷启动APP时不调用openURLContexts方法,这里保存URL在DidBecomeActive处理

objectivec 复制代码
- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions  API_AVAILABLE(ios(13.0)){
    [[AppLifecycleHelper sharedInstance] createKeyWindowWithScene:(UIWindowScene *)scene];
    // 通过url冷启动app,一般只有一个url 
    for (UIOpenURLContext *context **in** connectionOptions.URLContexts) {
        NSURL *URL = context.URL;
        if (URL && URL.absoluteString.length > 0) {
            self.launchUrl = URL;
        }
    }
}

AppLifecycleHelper:

AppLifecycleHelper 复制代码
- (void)createKeyWindow {
    UIWindow *window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    [self setupMainWindow:window];
}

- (void)createKeyWindowWithScene:(UIWindowScene *)scene API_AVAILABLE(ios(13.0)) {
    UIWindow *window = [[UIWindow alloc] initWithWindowScene:scene];
    [self setupMainWindow:window];
}

- (void)setupMainWindow:(UIWindow *)window {
}
  • 实现SceneDelegate后appDelegate 中失效的方法

在AppLifecycleHelper中实现,共享给两个DelegateClass

AppDelegate 复制代码
- (void)applicationDidBecomeActive:(UIApplication *)application {
    [[AppLifecycleHelper sharedInstance] appDidBecomeActive];
}

- (void)applicationWillResignActive:(UIApplication *)application {

}

- (void)applicationDidEnterBackground:(UIApplication *)application {

}

- (void)applicationWillEnterForeground:(UIApplication *)application {

}
  
 /// URL Scheme
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey, **id**> *)options {

}

/// 接力用户活动
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray<**id**<UIUserActivityRestoring>> * _Nullable))restorationHandler {

}

/// 快捷方式点击
- (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL))completionHandler API_AVAILABLE(ios(9.0)) {
}

SceneDelegate部分代码示例:

SceneDelegate 复制代码
- (void)sceneDidBecomeActive:(UIScene *)scene  API_AVAILABLE(ios(13.0)){
    [[AppLifecycleHelper sharedInstance] appDidBecomeActiveWithLaunchUrl:self.launchUrl];
    // 清空冷启动时的url
    self.launchUrl = nil;
}

这个方法总结下来就是求同存异,由Helper提供SceneDelegate与AppDelegate相同或类似的方法,适合单窗口、且支持iOS 13以下的app;

另外注意URL Scheme冷启动app不会执行openURL需要记录URL,在合适的时机(一般是DidBecomeActive)处理。

相关推荐
茶底世界之下16 小时前
iPhone Duo 适配实战,Awaking 踩过的 8 个坑
ios·swiftui·swift
跨境数据猎手17 小时前
HTTP 响应体编码与压缩:识别、解码
网络协议·http·ios
也非非也17 小时前
iPhone 中国区 AI 落地:Apple 与阿里千问合作的技术观察
大数据·人工智能·ios·agent·iphone·智子
茶底世界之下19 小时前
同一片泳池,清透还是奶油胶片?用 Awaking 做两版成片
ios
2501_9160088921 小时前
iOS App 图标、启动屏和多语言搭配 方法,上架前使用KXBuild一次做好 App 图标
ide·vscode·ios·objective-c·个人开发·swift·敏捷流程
2501_9159184121 小时前
iOS 推送通知怎么实现,从 APNs p8 密钥到 iOS 真机收到第一条推送
vscode·ios·objective-c·个人开发·swift·敏捷流程
茶底世界之下2 天前
雨夜街角裁成方图,人物与冷暖光还能共存吗?
ios
youdexiang2 天前
IOS录音APP拍照记录能和音频同步吗
ios·音视频
2501_915909062 天前
Windows 打开 Xcode 工程,编译调试 Xcode 项目并和 Mac 同事协作
ide·windows·vscode·macos·ios·个人开发·xcode
互联网江湖2 天前
iPhone Duo跌倒,国产折叠屏手机吃饱?
ios·智能手机·iphone