// Create a globally-accessible variable of some kind (global
// variable, static property, property of a singleton, etc.) that
// references this current scene (itself).
var currentScene: UIScene?
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let scene = scene as? UIWindowScene else {
return
}
// Save the reference when the scene is born.
currentScene = scene
}
func borat() {
print("great success")
}
}
// Here is a convenient view controller extension.
extension UIViewController {
var sceneDelegate: SceneDelegate? {
for scene in UIApplication.shared.connectedScenes {
if scene == currentScene,
let delegate = scene.delegate as? SceneDelegate {
return delegate
}
}
return nil
}
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
sceneDelegate?.borat() // "great success"
}
}
9条答案
按热度按时间oug3syen1#
从iOS 13开始,
UIApplication
拥有connectedScenes
属性Set<UIScene>
。每个场景都拥有delegate
属性UISceneDelegate
。因此,您可以通过这种方式访问所有代理。一个场景可以管理一个或多个窗口(
UIWindow
),您可以从窗口的windowScene
属性获取窗口的UIScene
。如果你想要一个特定视图控制器的场景代理,请注意以下几点:从
UIViewController
你可以从它的视图得到它的窗口,从窗口你可以得到它的场景,当然从场景你也可以得到它的代理。简而言之,从视图控制器中,您可以执行以下操作:
但是,视图控制器没有窗口的情况也有很多。当视图控制器显示另一个全屏视图控制器时会发生这种情况。当视图控制器位于导航控制器中,并且视图控制器不是顶部可见的视图控制器时,会发生这种情况。
这需要一种不同的方法来找到视图控制器的场景,最终你需要使用遍历响应器链和视图控制器层次结构的组合,直到你找到一条通往场景的路径。
下面的扩展将(可能)从视图或视图控制器中获取UIScene。一旦你有了场景,你就可以访问它的代理。
添加UIResponder+场景.swift:
这可以从任何视图或视图控制器调用以获取其场景。但请注意,只有在调用
viewDidAppear
至少一次后,才能从视图控制器获取场景。如果您尝试在此之前调用,则视图控制器可能尚未成为视图控制器层次结构的一部分。即使视图控制器的视图的窗口为空,只要视图控制器是视图控制器层次结构的一部分,并且在该层次结构之上的某个地方,它被附加到窗口,这也将起作用。
以下是UIResponder扩展的Objective-C实现:
UI响应器+场景h:
UI响应器+场景。m:
cld4siwp2#
如果您的应用程序将永远只有一个场景,那么我能够让它工作使用这个:
vjhs03f73#
JoeGalind谢谢你我也解决了类似的方式。
ffscu2ro4#
如果只是试图查找窗口,则不需要引用
SceneDelegate
:只有当您的应用只有一个场景和一个窗口时,才应使用此方法。
busg9geu5#
iOS 13及更高版本、Swift
场景代表应用程序用户界面的示例,每个场景都保持着自己的完全独立的状态。应用程序本身永远不会超过一个示例,它维护着对所有这些相连场景的引用。场景是类,因此它们是引用类型。因此,当场景被连接时,简单地保持对场景本身的引用,然后在
UIApplication.shared
内的一组连接的场景中找到该场景。svdrlsy46#
我将SceneDelegate的引用存储在
static weak
属性中,并在scene(:willConnectTo:options)
中对其进行初始化稍后,可使用
SceneDelegate.shared
访问场景a2mppw5e7#
我在我的
MasterViewController
中使用这个:此时
self.view.window
为nil,因此我必须访问其视图已经加载并添加到窗口中的父视图。如果你使用的是分割视图控制器,并且场景代理是分割代理,那么你可以完全避开窗口/场景,只需要:
SceneDelegate *sceneDelegate = (SceneDelegate *)self.splitViewController.delegate;
我在我的
DetailViewController
中使用这个。wn9m85ua8#
有时窗口是空的,你可以检查plist下的故事板名称,请参考图片-x1c 0d1x
cnh2zyt39#
Objective-C版本: