UIApplication.shared.delegate是否等效于SceneDelegate xcode11? [英] UIApplication.shared.delegate equivalent for SceneDelegate xcode11?

查看:314
本文介绍了UIApplication.shared.delegate是否等效于SceneDelegate xcode11?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经在我的SceneDelegate中定义了一个let属性.我希望某些ViewController能够在场景中访问它.

I have defined a let property within my SceneDelegate. I would like some of the ViewControllers to be able to access that within the scene.

在UIKit中,我可以访问App Delegate属性,如下所示:

In UIKit I could access App Delegate properties like this:

UIApplication.shared.delegate

然后强制转换并指定属性名称...

then casting and specifying the property name...

是否存在从UIViewController的实例获取对视图控制器所在的SceneDelegate的引用的等效项?

Is there an equivalent to get the a reference to the SceneDelegate the view controller is in from the UIViewController's instance?

推荐答案

从iOS 13开始,UIApplication具有connectedScenes属性,即Set<UIScene>.这些场景中的每一个都有一个delegate,它是一个UISceneDelegate.这样您就可以通过这种方式访问​​所有代表.

As of iOS 13, UIApplication has the connectedScenes property which is Set<UIScene>. Each of those scenes has a delegate which is a UISceneDelegate. So you could access all of the delegates that way.

一个场景可以管理一个或多个窗口(UIWindow),您可以从其windowScene属性中获取窗口的UIScene.

A scene can manage one or more windows (UIWindow) and you can get a window's UIScene from its windowScene property.

如果要特定视图控制器的场景委托,请注意以下几点.在UIViewController中,您可以从其视图中获取其窗口.从窗口中可以获取其场景,当然也可以从场景中获取其委托.

If you want the scene delegate for a specific view controller then note the following. From a UIViewController you can get its window from its view. From the window you can get its scene and of course from the scene you can get its delegate.

简而言之,您可以在视图控制器中执行以下操作:

In short, from a view controller, you can do:

let mySceneDelegate = self.view.window.windowScene.delegate

但是,很多时候视图控制器没有窗口.当视图控制器显示另一个全屏视图控制器时,会发生这种情况.当视图控制器在导航控制器中并且视图控制器不是顶部可见的视图控制器时,会发生这种情况.

However, there are plenty of times where a view controller has no window. This happens when a view controller presents another full screen view controller. This can happened when the view controller is in a navigation controller and the view controller is not the top, visible view controller.

这需要一种不同的方法来查找视图控制器的场景.最终,您需要结合使用响应链和视图控制器层次结构,直到找到通向场景的路径.

This requires a different approach to finding the view controller's scene. Ultimately you need to use a combination of walking the responder chain and the view controller hierarchy until you find a path that leads to the scene.

以下扩展名将(可能)从视图或视图控制器为您提供UIScene.拥有场景后,就可以访问其委托.

The following extension will (may) get you a UIScene from a view or view controller. Once you have the scene, you can access its delegate.

添加UIResponder + Scene.swift:

Add UIResponder+Scene.swift:

import UIKit

@available(iOS 13.0, *)
extension UIResponder {
    @objc var scene: UIScene? {
        return nil
    }
}

@available(iOS 13.0, *)
extension UIScene {
    @objc override var scene: UIScene? {
        return self
    }
}

@available(iOS 13.0, *)
extension UIView {
    @objc override var scene: UIScene? {
        if let window = self.window {
            return window.windowScene
        } else {
            return self.next?.scene
        }
    }
}

@available(iOS 13.0, *)
extension UIViewController {
    @objc override var scene: UIScene? {
        // Try walking the responder chain
        var res = self.next?.scene
        if (res == nil) {
            // That didn't work. Try asking my parent view controller
            res = self.parent?.scene
        }
        if (res == nil) {
            // That didn't work. Try asking my presenting view controller 
            res = self.presentingViewController?.scene
        }

        return res
    }
}

可以从任何视图或视图控制器调用它来获取其场景.但是请注意,只有在至少调用一次viewDidAppear之后,才能从视图控制器获取场景.如果您尽早尝试,那么视图控制器可能还不属于视图控制器层次结构.

This can be called from any view or view controller to get its scene. But note that you can only get the scene from a view controller only after viewDidAppear has been called at least once. If you try any sooner then the view controller may not yet be part of the view controller hierarchy.

即使视图控制器的视图窗口为零,只要该视图控制器是视图控制器层次结构的一部分,并且该层次结构中位于该层次结构的某个位置,它也将附加到窗口.

This will work even if the window of the view of the view controller is nil as long as the view controller is part of a view controller hierarchy and somewhere up that hierarchy, it is attached to a window.

这是UIResponder扩展的Objective-C实现:

Here is an Objective-C implementation of the UIResponder extension:

UIResponder + Scene.h:

UIResponder+Scene.h:

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface UIResponder (Scene)

@property (nonatomic, readonly, nullable) UIScene *scene API_AVAILABLE(ios(13.0));

@end

NS_ASSUME_NONNULL_END

UIResponder + Scene.m:

UIResponder+Scene.m:

#import "ViewController+Scene.h"

@implementation UIResponder (Scene)

- (UIScene *)scene {
    return nil;
}

@end

@implementation UIScene (Scene)

- (UIScene *)scene {
    return self;
}

@end

@implementation UIView (Scene)

- (UIScene *)scene {
    if (self.window) {
        return self.window.windowScene;
    } else {
        return self.nextResponder.scene;
    }
}

@end

@implementation UIViewController (Scene)

- (UIScene *)scene {
    UIScene *res = self.nextResponder.scene;
    if (!res) {
        res = self.parentViewController.scene;
    }
    if (!res) {
        res = self.presentingViewController.scene;
    }

    return res;
}

@end

这篇关于UIApplication.shared.delegate是否等效于SceneDelegate xcode11?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆