Как переопределить свойство "view" в UIViewController?
У меня есть пользовательский UIViewController и пользовательский UIView. Я хотел бы переопределить свойство viewcontroller.view, чтобы вернуть MyCustomUIView.
Сейчас у меня есть:
@interface MyViewController : UIViewController {
IBOutlet MyView* view;
}
@property (nonatomic, retain) IBOutlet MyView* view;
Это компилируется, но я получаю предупреждение: свойство 'view' типа не соответствует типу свойства суперкласса 'UIViewController'.
Как мне смягчить это предупреждение?
Ответы
Ответ 1
Короткий ответ заключается в том, что вы этого не делаете. Причина в том, что свойства - это действительно просто методы, и если вы попытаетесь изменить тип возвращаемого значения, вы получите следующее:
Objective-C не допускает ковариацию возвращаемого типа.
Что вы можете сделать, это добавить новое свойство "myView" и сделать его просто при помощи свойства "view". Это облегчит приведение типов во всем коде. Просто назначьте свой подкласс вида свойству view, и все должно работать нормально.
Ответ 2
@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
в свойство.
См. Переопределение свойства UIViewController View, Done Right для более подробной информации.
Ответ 3
Свойство/метод представления UIViewController автоматически вернет ваше представление. Я думаю, вам просто нужно передать результат в MyView (или просто использовать тип id):
MyView *myView = (MyView*)controller.view;
id myView = controller.view;
Я думаю, что код, который вы опубликовали выше, вызовет у вас проблемы. Вы, вероятно, не хотите сами создавать элемент представления (потому что тогда контроллер будет хранить 2 представления и может не использовать правильный внутренний) или переопределить свойство view (поскольку UIViewController имеет для него специальную обработку.) (См. этот вопрос для получения дополнительной информации о последнем.)
Ответ 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, вероятно, будет работать в построителе интерфейса, но не будет корректно работать в коде.
В настоящее время я использую эту реализацию.
Ответ 5
Если кто-либо находится в Swift 2.0+, вы можете использовать расширения протокола для повторной реализации:
// Classes conforming to this protocol...
protocol CustomViewProvider {
typealias ViewType
}
// ... Will get customView accessor for free
extension CustomViewProvider where Self: UIViewController, Self.ViewType: UIView {
var customView: Self.ViewType {
return view as! Self.ViewType
}
}
// Example:
extension HomeViewController: CustomViewProvider {
typealias ViewType = HomeView
}
// Now, we can do something like
let customView: HomeView = HomeViewController().customView