我以编程方式创建了几个表,并且代码已经运行了好几年.两周前我上次运行时没有发出任何警告.我已经更新到iOS 8.3,现在我为每个UITableViewController收到三个警告.
超类'-initWithStyle:'的指定初始值设定项的方法覆盖未找到.
超类'-initWithCoder的指定初始值设定项的方法覆盖:'未找到.
超类"-initWithNibName:bundle:"的指定初始值设定项的方法覆盖:未找到.
初始化表的代码对于我的所有表都是类似的:
- (instancetype)initInManagedObjectContext:(NSManagedObjectContext *)context
withScoreKeeper:(ScoreKeeper *)scorer
withWordList:(WordList *)wordlist {
self = [super initWithStyle:UITableViewStyleGrouped];
if (self) {
_mObjContext = context;
_scoreKeeper = scorer;
_wordList = wordlist;
}
return self;
}
Run Code Online (Sandbox Code Playgroud)
而.h看起来像这样:
@interface SettingsTableViewController : UITableViewController {
UIPopoverController *popover;
}
- (instancetype)initInManagedObjectContext:(NSManagedObjectContext *)context
withScoreKeeper:(ScoreKeeper *)scorer
withWordList:(WordList *)wordlist NS_DESIGNATED_INITIALIZER;
Run Code Online (Sandbox Code Playgroud)
我以为我通过调用self = [super initWithStyle:UITableViewStyleGrouped];来覆盖指定的初始化程序,但我想编译器现在有其他想法.
那么如何覆盖指定的初始化程序?
Cœu*_*œur 54
NS_DESIGNATED_INITIALIZER
您可以将它们描述为不可用,并使用例外实现它们.
对于您的示例,在SettingsTableViewController.h中:
@interface SettingsTableViewController : UITableViewController
- (instancetype)initWithStyle:(UITableViewStyle)style NS_UNAVAILABLE;
- (instancetype)initWithNibName:(nullable NSString *)nibNameOrNil bundle:(nullable NSBundle *)nibBundleOrNil NS_UNAVAILABLE;
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder NS_UNAVAILABLE;
- (instancetype)initInManagedObjectContext:(NSManagedObjectContext *)context
withScoreKeeper:(ScoreKeeper *)scorer
withWordList:(WordList *)wordlist NS_DESIGNATED_INITIALIZER;
//...your class interface here
@end
Run Code Online (Sandbox Code Playgroud)
在SettingsTableViewController.m中:
@interface SettingsTableViewController ()
- (instancetype)initWithStyle:(UITableViewStyle)style NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithNibName:(nullable NSString *)nibNameOrNil bundle:(nullable NSBundle *)nibBundleOrNil NS_DESIGNATED_INITIALIZER;
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER;
@end
@implementation SettingsTableViewController
- (instancetype)initWithStyle:(UITableViewStyle)style { @throw nil; }
- (instancetype)initWithNibName:(nullable NSString *)nibNameOrNil bundle:(nullable NSBundle *)nibBundleOrNil { @throw nil; }
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder { @throw nil; }
//...your class implementation here
@end
Run Code Online (Sandbox Code Playgroud)
您还可以NSAssert(NO, nil);
在之前添加@throw nil;
以了解日志中的异常文件和行号.
NS_DESIGNATED_INITIALIZER
你必须明确地实现它们.但好的做法是删除NS_DESIGNATED_INITIALIZER
潜在子类的公共多余宏,并且只能私下重新引入它.
对于您的示例,在SettingsTableViewController.h中:
@interface SettingsTableViewController : UITableViewController
- (instancetype)initWithStyle:(UITableViewStyle)style;
- (instancetype)initWithNibName:(nullable NSString *)nibNameOrNil bundle:(nullable NSBundle *)nibBundleOrNil;
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder;
- (instancetype)initInManagedObjectContext:(NSManagedObjectContext *)context
withScoreKeeper:(ScoreKeeper *)scorer
withWordList:(WordList *)wordlist NS_DESIGNATED_INITIALIZER;
//...your class interface here
@end
Run Code Online (Sandbox Code Playgroud)
在SettingsTableViewController.m中:
@interface SettingsTableViewController ()
- (instancetype)initWithStyle:(UITableViewStyle)style NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithNibName:(nullable NSString *)nibNameOrNil bundle:(nullable NSBundle *)nibBundleOrNil NS_DESIGNATED_INITIALIZER;
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER;
@end
@implementation SettingsTableViewController
- (instancetype)initWithStyle:(UITableViewStyle)style { return [super initWithStyle:style]; }
- (instancetype)initWithNibName:(nullable NSString *)nibNameOrNil bundle:(nullable NSBundle *)nibBundleOrNil { return [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; }
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder { return [super initWithCoder:aDecoder]; }
//...your class implementation here
@end
Run Code Online (Sandbox Code Playgroud)
在这两种情况下(允许或禁止),无需更改其余的实现.
Rob*_*ier 13
您已声明initInManagedObjectContext:withScoreKeeper:withWordList:
是唯一的指定初始值设定项SettingsTableViewController
.这意味着所有其他初始值设定项必须调用它.但是你继承了initWithStyle:
等等,那些那些不会叫你指定的初始化程序.这意味着如果您的对象是通过调用initWithStyle:
(或更重要的是)创建的initWithCoder:
,那么它将无法正确初始化.Clang正在警告你.
看起来你通过删除来解决它NS_DESIGNATED_INITIALIZER
,这在Cocoa开发中很常见.我没见过很多经常使用那个宏的开发者.但它留下了潜在的错误.更完整的解决方案是覆盖超类的指定初始化器并将它们实现为调用[self initInManagedObjectContext:withScoreKeeper:withWordList:]
或实现它们NSAssert()
以确保它们正确地失败而不是默默地执行默认操作(可能就在这里,但可能不是).
请注意,Swift使这种情况出错.它只是回到ObjC作为警告.
调用[super initWithStyle:UITableViewStyleGrouped]
不会覆盖超类中的方法; 你只是叫它.
我怀疑iOS 8.3现在会在Objective-C中向您显示这些警告(我们已经在Swift中获得了一些警告).
我只是简单地覆盖这样的方法来摆脱警告:
- (instancetype)initWithStyle:(UITableViewStyle)style
{
return [super initWithStyle:style];
}
Run Code Online (Sandbox Code Playgroud)
在你的情况下,你看起来不需要做更多的事情.
更新:
尝试将便利初始化程序更改为:
- (instancetype)initInManagedObjectContext:(NSManagedObjectContext *)context
withScoreKeeper:(ScoreKeeper *)scorer
withWordList:(WordList *)wordlist {
self = [self initWithStyle:UITableViewStyleGrouped]; // <-- self instead of super
if (self) {
_mObjContext = context;
_scoreKeeper = scorer;
_wordList = wordlist;
}
return self;
}
Run Code Online (Sandbox Code Playgroud)
该方法是一个便利初始化程序,应始终调用当前类中的一个指定初始值设定项.那个人可以调用superview的指定初始化程序.
归档时间: |
|
查看次数: |
17098 次 |
最近记录: |