如何覆盖UIViewController中的“view”属性?

时间:2009-03-14 19:13:05

标签: iphone cocoa-touch uiview uiviewcontroller

我有一个自定义的UIViewController和自定义UIView。我想重写viewcontroller.view属性以返回MyCustomUIView。

现在我有:

@interface MyViewController : UIViewController {    
    IBOutlet MyView* view;
}

@property (nonatomic, retain) IBOutlet MyView* view;

这个编译但我得到一个警告:属性'view'类型与超类'UIViewController'属性类型不匹配。

如何缓解此警告?

5 个答案:

答案 0 :(得分:23)

@ lpaul7已经发布了一条链接到Travis Jeffery的博客作为评论,但它比所有其他答案更正确,它确实需要代码作为答案:

<强> ViewController.h:

@interface ViewController : UIViewController

@property (strong, nonatomic) UIScrollView *view;

@end

<强> ViewController.m:

@implementation ViewController

@dynamic view;

- (void)loadView {
  self.view = [[UIScrollView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
}

@end

如果使用xib,而不是覆盖loadView,请更改视图控制器根视图的类型,并将IBOutlet添加到属性中。

有关详细信息,请参阅Overriding UIViewController's View Property, Done Right

答案 1 :(得分:18)

简短的回答是你没有。原因是属性实际上只是方法,如果你试图改变返回类型,你得到这个:

  • (UIView *)view;
  • (MyView *)视图;

Objective-C 允许返回类型协方差。

您可以做的是添加一个新属性“myView”,并简单地将其视为“view”属性。这将减轻整个代码中的类型转换。只需将视图子类分配给view属性,一切都可以正常工作。

答案 2 :(得分:4)

UIViewController的view属性/方法将自动返回您的视图。我想你只需要将结果转换为MyView(或者只是使用id类型):

MyView *myView = (MyView*)controller.view;
id myView = controller.view;

我认为您上面发布的代码会给您带来麻烦。您可能不希望自己创建一个视图成员(因为控制器将存储2个视图,并且可能不会在内部使用正确的视图)或覆盖视图属性(因为UIViewController对它有特殊处理。)(参见{ {3}}有关后者的更多信息。)

答案 3 :(得分:4)

很抱歉,但您的简短回答是错误的。

正确的实现方法是使用返回类型将@property添加到头文件中。 然后代替@synthesize,手动添加getter和setter,并从[super view]返回一个强制转换类型

例如我的类是一个PlayerViewController

PlayerViewController.h

@property (strong, nonatomic) IBOutlet PlayerView *view;

PlayerViewController.m

- (PlayerView *)view{
    return (PlayerView*)[super view];
}
- (void)setView:(PlayerView *)view{
    [super setView:view];
}

重要的是将正确的类放入视图中。

将UIView置于PlayerView所在的位置可能会在Interface Builder中起作用,但在代码中无法正常运行。

我目前正在使用此实现。

答案 4 :(得分:0)

如果有人使用Swift 2.0+,您可以使用协议扩展来实现可重用的实现:

margin-right: 1%