我有几个不同的 viewController 需要继承相同的属性,但不是同一类型的 viewController。例如,一个 VC 是常规的 UIViewController,而另一个是 UISplitViewController。我有什么方法可以有效地使用继承来确保它们都具有这些特定属性?还是我只需要给每个人自己单独的声明?
4 回答
您可以使用 上的类别来实现您想要的UIViewController
。您可以使用关联对象实现类别中的属性。
有关详细信息,请参阅Objective-C:类别中的属性/实例变量。
您可以向 UIViewController 添加一个类别。由于 UISplitViewController 继承自 UIViewController,因此它也将具有类别中定义的所有属性和方法。但是,类别有两个限制:
您不能添加支持实例变量。您可以创建属性,但它们不能有支持它们的实例变量。这意味着如果您覆盖 getter(和 setter,如果是读写),以便它以某种方式读取(或写入)已经存在的属性,那么您很好。如果没有,您可以查看关联对象。
在一个类别中覆盖方法是禁止的。虽然没有什么能阻止您这样做,但如果另一个类别也覆盖了该方法,您将有未定义的行为。你只是不知道哪个方法会被执行。如果你需要重写方法,子类化 UIViewController 会更好。但是,UISplitViewController 将不知道这些属性,除非您也将其子类化并添加相同的属性(在这种情况下,您需要维护这些属性两次)。
我不确定你到底需要什么。如果您不想(或不能)将公共超类与公共属性一起使用,您可以随时编写协议。唯一的区别是,协议不给你通用的实现,而是强迫你写一个(所以你可以确定它在那里,正如你所要求的那样)。
为什么不使用共享基类设置继承并在 init 中设置这些共享属性?
//MyBaseVC.h
@interface MyBaseVC : UIViewController
@property (nonatomic, strong) NSString *myString;
@end
//VC1.h
@interface VC1 : MyBaseVC
@end
//VC2.h
@interface VC2 : MyBaseVC
@end
-----
//(MyBaseVC.m)
-(id) init {
self = [super init];
if(self){
self.myString = @"Hello world!";
}
return self;
}
// VC1.m
-(id) init {
self = [super init];
NSLog(@"%@", self.myString); // "Hello world!"
return self;
}
// VC2.m
-(id) init {
self = [super init];
NSLog(@"%@", self.myString); // "Hello world!"
return self;
}
此时,您可以直接引用子类对象上的属性:
NSLog(@"%@",myVc1.myString); //"Hello world!"
否则,当您以更通用的方式引用 VC 时,您始终可以引用它们的超类 (MyBaseVC) - 例如,如果您需要将它们作为方法参数传递。
//-(void)doSomethingWithVC:(MyBaseVC *)vc;
[someObj doSomethingWithVc: vc1];