好吧,我不会假装知道关于Objective-C和iOS编程的所有内容,因为我刚刚开始,但这个让我完全难过。我有一个类ShoppingListViewController,在那个类中,我重写initWithCoder方法来读取:
- (id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
self.title = @"Shopping List";
[self loadItems];
}
return self;
}
在该loadItems方法中,每行都有一行导致应用程序崩溃:
self.items = [NSMutableArray array];
该应用程序因以下错误崩溃:
Terminating app due to uncaught exception 'NSInternalInconsistencyException',
reason: 'Could not load NIB in bundle:
但是,如果我用以下内容替换该行:
_items = [NSMutableArray array];
一切正常。现在我明白我通过这样做来绕过默认的设置器,但我不清楚为什么运行时通常会出现问题,以及为什么它与NIB文件有什么关系呢?谁能开导我?
使用更多信息进行更新:
items属性在类的标题中声明:
@property (nonatomic) NSArray *items;
并且loadItems方法相当稀疏,基本上该行是唯一一个在首次加载时真正重要的行:
- (void)loadItems {
NSString *filePath = [self pathForItems];
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
self.items = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
} else {
_items = [NSMutableArray array];
}
}
答案 0 :(得分:1)
您不应该在init或dealloc中发送自己的消息。请阅读this article以获得更好的解释
这是因为self.whatever会触发其他副作用,例如 键值观察(KVO)通知,或者您的班级 实现(显式)或子类覆盖setWhatever: - 和 这可能会将部分初始化的实例暴露给其他API (包括它自己的),正确地假设他们正在处理一个 完全构造的对象。
您可以参考this answer了解更多信息。
<强> P.S。永远不要忘记self.something调用setter / getter。
答案 1 :(得分:1)
我认为默认属性setter可能有一些你不知道的依赖项。 (虽然我不确定)。
init#系列方法仅用于类初始化。由于iOS dev意味着MVC开发和加载数据正在加载模型依赖项,因此它们不应该在init函数中。
我建议在显示视图之前将加载功能放在viewDidLoad
或暗示就绪状态的类似方法中,从那时起您可以100%确定视图控制器已准备好。
请勿将其放入viewWillAppear
或viewDidAppear
,因为这些可以被多次调用!
答案 2 :(得分:-1)
首先,不建议在init方法中调用属性,因为它们可能还没有准备好。
其次,显示self.items属性的声明和loadItems方法。