Подтвердить что ты не робот

Как переопределить свойство "view" в UIViewController?

У меня есть пользовательский UIViewController и пользовательский UIView. Я хотел бы переопределить свойство viewcontroller.view, чтобы вернуть MyCustomUIView.

Сейчас у меня есть:

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

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

Это компилируется, но я получаю предупреждение: свойство 'view' типа не соответствует типу свойства суперкласса 'UIViewController'.

Как мне смягчить это предупреждение?

4b9b3361

Ответ 1

Короткий ответ заключается в том, что вы этого не делаете. Причина в том, что свойства - это действительно просто методы, и если вы попытаетесь изменить тип возвращаемого значения, вы получите следующее:

  • (UIView *);
  • (MyView *);

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