2009-03-14 12 views
26

나는 사용자 정의 UIViewController 및 사용자 정의 UIView 있습니다. MyCustomUIView를 반환하려면 viewcontroller.view 속성을 재정의하고 싶습니다.UIViewController의 "보기"속성을 어떻게 재정의합니까?

는 지금은이 :

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

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

이 컴파일하지만 경고를 얻을 : 부동산의 '보기'형 슈퍼 클래스 '의 UIViewController'속성 유형과 일치하지 않습니다.

이 경고는 어떻게 완화합니까?

+2

난 당신이 아니라'@의 dynamic'를 사용한다고 생각합니다. 제발 [이 질문] (http://stackoverflow.com/questions/1160498/synthesize-vs-synthesize-vs-dynamic-what-are-the-differences), 거기에 대한 답변은 내게 정말 도움이되었다 : – Ondrej

+3

아주 좋은 기사가있다 [UIViewController의 View 속성 재정의, 완료] (http://travisjeffery.com/b/2012/12/overriding-uiviewcontrollers-view-property-done-right/). – lambdas

답변

18

짧은 대답은 당신이하지 않는다는 것입니다. 그 이유는 속성이 실제로는 메서드이기 때문에 반환 형식을 변경하려고하면 다음과 같이 나타납니다.

  • (UIView *) view;
  • (MyView *)보기;

목표 -C는 이 아니며은 반환 유형 공분산을 허용합니다.

"myView"라는 새 속성을 추가하고 단순히 "view"속성을 유형 변환하도록 할 수 있습니다. 이렇게하면 코드 전체에서 타입 변환이 완화됩니다. 뷰 하위 클래스를 뷰 속성에 할당하면 모든 것이 잘 작동합니다.

+0

+1 내가 대답 한 부분이 정확히 빠져있는 것을주는 +1 : –

4

UIViewController의 view 속성/메서드는보기를 자동으로 반환합니다. 난 그냥 MYVIEW에 결과를 주조 (또는 아이디 유형을 사용)해야합니다 생각 :

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

난 당신이 위의 게시 한 코드가 당신에게 문제를 일으킬 것이라 생각합니다. 아마도 뷰어 멤버를 직접 만들고 싶지 않을 것입니다 (컨트롤러가 2 개의 뷰를 저장하고 내부적으로 올바른 뷰를 사용하지 못하기 때문에 UIViewController가 특수한 처리를하기 때문에 뷰 속성을 무시합니다). (this question 후자에 대한 자세한 내용은

4

죄송 합니다만 짧은 대답은 잘못되었습니다.

이 올바른 구현은 @property를 반환 형식의 헤더 파일에 추가하는 것입니다. 그리고 대신 수동으로 getter와 setter를 추가하고 [슈퍼 볼] 예를 들어

내 클래스는 PlayerViewController

PlayerViewController.h

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

PlayerViewController이다에서 캐스트 형식을 반환 @synthesize의 . m

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

중요한 것은 올바른 클래스를보기에 넣는 것입니다.

PlayerView가있는 UIView를 Interface Builder에서 사용할 수는 있지만 코드에서 올바르게 작동하지는 않습니다.

현재이 구현을 사용하고 있습니다.lpaul7 @

+0

나는이 질문이 오래되었다는 것을 알고있다. 그러나 나는 이것을 발견하고 내 자신의 대답을 내놓았다. 희망이 미래의 사용자에게 도움이됩니다. –

+0

재산이 강해야한다고 생각하십니까? 즉, 'UIView'에는 이미 동일한 값을 유지하는 강력한 속성'view'가 있습니다. 읽기 전용 수정자가 더 적절하지 않습니까? – lambdas

+0

+1 : 나는 이것이 가능하다고 생각했다. 그것을 확인해 주셔서 감사합니다. @ lpaul7 - 아니요,'readonly'는 의미가 없습니다. 왜냐하면'view' 속성, 즉'readonly'의 의미를 설정할 수 없기 때문입니다. 슈퍼 클래스의'view' 속성 (속성 선언이'strong')을 오버라이드하려면이 속성을'strong'으로 설정해야합니다. –

23

이미 주석으로 트래비스 제프리의 블로그에 링크를 게시하지만, 훨씬 더 올바른 모든 다른 답변보다 정말 대답 할 코드를 필요로이다 :

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을 참조하십시오. 사람이 스위프트 2.0 이상에있는 경우

+0

"UIViewController"에서 상속 된 'UIView *'속성 유형 'MyScrollView *'과 호환되지 않습니다. " – Koen

+0

@Koen MyScrollView는 UIView의 하위 클래스입니까? MyScrollView 대신 UIScrollView를 사용하면 컴파일러 경고 메시지가 표시됩니까? – JosephH

+0

MyScrollView는'UIScrollView'의 서브 클래스입니다. 나는 scrollView를 모든 드로잉을 수행하는 MyCustomView의 컨테이너로 만듦. 모든 드로잉을 수행하는 것과는 대조적으로 MyScrollView. – Koen

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