1

我们有一个项目,它构建了两个独立的目标,这些目标具有实现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重新声明window属性,该属性是自动合成的。UIApplicationDelegate@interface

重构之后,事情看起来像这样:

@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属性?

4

1 回答 1

1

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

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

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

@implementation XXXAppDelegate

@synthesize window;

@end

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

于 2013-10-08T22:18:17.690 回答