在 iOS 13 中,UIWindowSceneDelegate
对象不在响应者链中(我通过打印响应者链来验证这一点)。但是 Xcode 提供的模板代码使场景委托类继承自UIResponder
. 如果我让场景委托类继承自NSObject
,代码仍然可以编译并运行没有问题。
那么让场景委托类符合的意义UIResponder
何在?
我在操作遇到问题时也注意到了这一点,NSToolbarItem
在与Hopper进行调查后,我发现原因是虽然UIWindow
'snextResponder
是UIWindowScene
,但它没有nextResponder
转发给它的委托(我们的SceneDelegate
类符合UIWindowSceneDelegate
)的覆盖,它是超类 -UIScene
的下一个是UIApplication
下一个应用程序委托的那个。
我的猜测是要求符合场景委托的类作为下一个响应者,应用程序在语法上很棘手,即使在 ObjC 中实现它也可能在 Swift 中更难或不可能。也许苹果只是认为不值得麻烦。使用 Catalyst,任何NSToolbarItem
窗口场景的工具栏都可以将其目标设置为自场景委托,而不是搜索响应者链,甚至系统项目也可以toolbarWillAddItem
在示例中更改其目标。如果他们至少在某处记录了窗口场景委托不在响应者链中的警告,那就太好了,特别是因为正如您所说,它是UIResponder
.
如果您希望它在链中,那么我创建了一个解决方法(请参见下面的代码)。首先创建一个UIWindowScene
带有nextResponder
返回方法的子类self.delegate
。其次,在场景委托中添加一个nextResponder
返回UIApplication.sharedApplication
(将转发给应用委托)。最后在 Scene Manifest (in Info.plist
) 在默认配置下添加一行并从下拉列表中选择 Class Name 并输入您的子类的名称。
我想这对于需要访问窗口的操作可能很有用,因为一旦操作到达应用程序委托,就很难确定它来自哪个场景窗口。但是正如我所说,在这种情况下,搜索链的意义何在。
我的窗口场景.h
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface MyWindowScene : UIWindowScene
@end
NS_ASSUME_NONNULL_END
我的窗口场景.m
#import "MyWindowScene.h"
@implementation MyWindowScene
- (UIResponder *)nextResponder{
return self.delegate;
}
@end
场景委托.m
@implementation SceneDelegate
...
- (UIResponder *)nextResponder{
return UIApplication.sharedApplication;
}