尝试设置窗口出口时,从两个 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 但未设置视图出口