如何在初始化期间将值从 subclass 传递给 super class
How to pass value from subclass to super class during initialization
假设我有两个视图控制器。 ViewController1 是 ViewController2 的子 class。从 subclass (ViewController1),我调用了 superclass init 方法并通过参数传递了一个值并将该值分配给 superclass 变量。但是在 superclass (ViewController2) 的 viewDidLoad 方法中,该值始终为 null。为什么 ?我怎样才能将该值从 sub 传递到 super,以便我可以在 super class 的 viewDidLoad 方法中获取该值?
ViewController1.h
@interface ViewController : ViewController2
@end
ViewController1.m
@implementation ViewController
- (instancetype)init
{
self = [super initWithName:@"Hello"];
if (self) {
NSLog(@"1 :");
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
ViewController2.h
@interface ViewController2 : UIViewController
@property (nonatomic, strong) NSString *name;
-(instancetype)initWithName:(NSString *)name;
@end
ViewController2.m
- (instancetype)initWithName:(NSString *)name
{
self = [super init];
if (self) {
self.name = name;
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
NSLog(@"2 : %@", self.name);
}
@end
更新 - 2016 年 3 月 16 日
示例:
ViewController1.h
#import <UIKit/UIKit.h>
#import "ViewController2.h"
@interface ViewController1 : ViewController2
@end
ViewController1.m
#import "ViewController1.h"
@interface ViewController1 ()
@end
@implementation ViewController1
-(instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
//self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil andUserName:@"Ramesh Annadurai"];
// we can use above init method or below method, both will work
self = [super initWithName:@"Test Name"];
if (self) {
[self.view setBackgroundColor:[UIColor brownColor]];
}
return self;
}
-(instancetype)initWithCoder:(NSCoder *)aDecoder
{
//self = [super initWithCoder:aDecoder];
// If you are using storyboard use this initWithCoder method.
self = [super initWithName:@"Test Name"];
if (self) {
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
@end
ViewController2.h
#import <UIKit/UIKit.h>
@interface ViewController2 : UIViewController
- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil andUserName:(NSString *) userName;
- (instancetype)initWithName:(NSString *) userName;
@end
ViewController2.m
#import "ViewController2.h"
@interface ViewController2 ()
@property (strong, nonatomic) NSString *userName;
@end
@implementation ViewController2
- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil andUserName:(NSString *) userName
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.userName = userName;
}
return self;
}
- (instancetype)initWithName:(NSString *) userName
{
self = [super initWithNibName:nil bundle:nil];
if (self) {
self.userName = userName;
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"User Name : %@", self.userName);
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
@end
我厌倦了你的代码,但它工作得很好。我怀疑您没有直接实例化 ViewController 。你在你的项目中使用故事板吗?如果是 - 您应该覆盖 ViewController 中的 initWithCoder:
。
但是,在 init
-family 方法期间设置视图控制器的任何属性是个坏主意。根据 Apple 的建议,所有自定义都应在 -viewDidLoad
或 -viewWill
/DidAppear
方法中完成。
如果您绝对需要从外部设置 name
属性,最好直接赋值,而不是通过向 init
方法传递参数。
还有一件事 - initWithNibName:bundle:
是 指定的初始化程序。这意味着,你的子类最终必须在初始化链中调用它。
假设我有两个视图控制器。 ViewController1 是 ViewController2 的子 class。从 subclass (ViewController1),我调用了 superclass init 方法并通过参数传递了一个值并将该值分配给 superclass 变量。但是在 superclass (ViewController2) 的 viewDidLoad 方法中,该值始终为 null。为什么 ?我怎样才能将该值从 sub 传递到 super,以便我可以在 super class 的 viewDidLoad 方法中获取该值?
ViewController1.h
@interface ViewController : ViewController2
@end
ViewController1.m
@implementation ViewController
- (instancetype)init
{
self = [super initWithName:@"Hello"];
if (self) {
NSLog(@"1 :");
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
ViewController2.h
@interface ViewController2 : UIViewController
@property (nonatomic, strong) NSString *name;
-(instancetype)initWithName:(NSString *)name;
@end
ViewController2.m
- (instancetype)initWithName:(NSString *)name
{
self = [super init];
if (self) {
self.name = name;
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
NSLog(@"2 : %@", self.name);
}
@end
更新 - 2016 年 3 月 16 日
示例:
ViewController1.h
#import <UIKit/UIKit.h>
#import "ViewController2.h"
@interface ViewController1 : ViewController2
@end
ViewController1.m
#import "ViewController1.h"
@interface ViewController1 ()
@end
@implementation ViewController1
-(instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
//self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil andUserName:@"Ramesh Annadurai"];
// we can use above init method or below method, both will work
self = [super initWithName:@"Test Name"];
if (self) {
[self.view setBackgroundColor:[UIColor brownColor]];
}
return self;
}
-(instancetype)initWithCoder:(NSCoder *)aDecoder
{
//self = [super initWithCoder:aDecoder];
// If you are using storyboard use this initWithCoder method.
self = [super initWithName:@"Test Name"];
if (self) {
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
@end
ViewController2.h
#import <UIKit/UIKit.h>
@interface ViewController2 : UIViewController
- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil andUserName:(NSString *) userName;
- (instancetype)initWithName:(NSString *) userName;
@end
ViewController2.m
#import "ViewController2.h"
@interface ViewController2 ()
@property (strong, nonatomic) NSString *userName;
@end
@implementation ViewController2
- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil andUserName:(NSString *) userName
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.userName = userName;
}
return self;
}
- (instancetype)initWithName:(NSString *) userName
{
self = [super initWithNibName:nil bundle:nil];
if (self) {
self.userName = userName;
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"User Name : %@", self.userName);
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
@end
我厌倦了你的代码,但它工作得很好。我怀疑您没有直接实例化 ViewController 。你在你的项目中使用故事板吗?如果是 - 您应该覆盖 ViewController 中的 initWithCoder:
。
但是,在 init
-family 方法期间设置视图控制器的任何属性是个坏主意。根据 Apple 的建议,所有自定义都应在 -viewDidLoad
或 -viewWill
/DidAppear
方法中完成。
如果您绝对需要从外部设置 name
属性,最好直接赋值,而不是通过向 init
方法传递参数。
还有一件事 - initWithNibName:bundle:
是 指定的初始化程序。这意味着,你的子类最终必须在初始化链中调用它。