尝试设置窗口出口时,从两个 UIApplicationDelegate 实现中提取公共超类会导致崩溃

Posted

技术标签:

【中文标题】尝试设置窗口出口时,从两个 UIApplicationDelegate 实现中提取公共超类会导致崩溃【英文标题】:Extracting a common superclass from two UIApplicationDelegate implementations leads to a crash when trying to set the window outlet 【发布时间】:2013-10-08 22:18:17 【问题描述】:

我们有一个项目构建两个独立的目标,这些目标具有实现UIApplicationDelegate 的特定于目标的类。从两个特定于应用程序的应用程序委托中提取超类后,我们发现应用程序在启动时崩溃,并出现错误,通常表明连接的IBOutlet 没有有效的实现:

[...YYYAppDelegate... setValue:forUndefinedKey:]: 这个类不是键 键窗口的值编码兼容。

堆栈跟踪和崩溃时间是这个问题的典型特征 - 显然,我们所做的事情破坏了 window 属性。

在执行重构之前,我们的应用委托接口和实现如下所示:

@interface YYYAppDelegate : NSObject <UIApplicationDelegate>
...
@property (nonatomic, strong) IBOutlet UIWindow *window;
...
@end

@implementation YYYAppDelegate

// No @synthesize of window
...
@end

@interface ZZZAppDelegate : NSObject <UIApplicationDelegate>
...
@property (nonatomic, strong) IBOutlet UIWindow *window;
...
@end

@implementation ZZZAppDelegate

// No @synthesize of window
...
@end

window 属性是自动合成的,因为我们在每个类的 @interface 块中从 UIApplicationDelegate 重新声明了 window 属性。

重构之后的样子是这样的:

@interface XXXAppDelegate : NSObject <UIApplicationDelegate>
...
@end

@implementation XXXAppDelegate
...
@end

@interface YYYAppDelegate : XXXAppDelegate
...
@property (nonatomic, strong) IBOutlet UIWindow *window;
...
@end

@implementation YYYAppDelegate
// No @synthesize of window
...
@end

@interface ZZZAppDelegate : XXXAppDelegate
...
@property (nonatomic, strong) IBOutlet UIWindow *window;
...
@end

@implementation ZZZAppDelegate
// No @synthesize of window
...
@end

这里发生了什么?为什么以这种方式提取超类会破坏window 属性?

【问题讨论】:

【参考方案1】:

属性自动合成不会自动合成在协议中声明的属性 - 必须在类的 @interface 中重新声明它们或添加显式 @synthesize。但是,在继承自声明符合此协议的类的类的@interface 中重新声明协议属性不会导致自动合成该属性。我找不到关于这一点的官方声明,但该行为在多次测试中似乎是一致的。

必须在声明符合协议的基类中重新声明属性,或者在超类或每个子类中添加@synthesize 语句。在我们的例子中,我们通过向XXXAppDelegate 添加显式合成来解决它,如下所示:

@interface XXXAppDelegate : NSObject <UIApplicationDelegate>
...
@end

@implementation XXXAppDelegate

@synthesize window;

@end

为了整洁,我们还删除了子类中的属性重新声明。

【讨论】:

以上是关于尝试设置窗口出口时,从两个 UIApplicationDelegate 实现中提取公共超类会导致崩溃的主要内容,如果未能解决你的问题,请参考以下文章

_UIApplicationHandleEventFromQueueEvent 中出现意外的 nil 窗口

AppDelegate (OSX) 中主 NSWindow 的引用出口

从 xib 加载 UITableViewCell 会导致加载 nib 但未设置视图出口

ViewController 的出口视图首先是非零,然后从包加载时为零

海关单一窗口申报怎么设置(海关单一窗口申报系统)

NSUnknownKeyException 即使定义了出口