2015-01-06 2 views
2

다음은 시나리오입니다. 모델 객체에 따라 사용자에게 보여주고 싶은 여러 가지 다른 뷰가 있습니다. 그래서 프로토콜을 구현 한 모든 뷰를 표시 할 수있는 프로토콜을 설정했습니다. 내가보기 컨트롤러에서 사용하는 갈 때Swift : 프로토콜을 구현하는 UIView 하위 클래스 인 속성

class MyItem { /* some model properties */ } 

protocol ItemView: class { 
    // some protocol methods (e.g. updateWithItem(), etc) 
    func setupItem(item: MyItem) 
} 

class SpecificItemView: UIView, ItemView { /* there will be multiple classes like this */ 
    func setupItem(item: MyItem) { 
     // do item setup 
    } 
} 

class AnotherItemView: UIView, ItemView { 
    func setupItem(item: MyItem) { 
     // do DIFFERENT item setup 
    } 
} 

은 다음, 나는 내 ItemView 클래스 중 하나 주어진했습니다

class MyViewController: UIViewController { 

    var itemView: ItemView? // could be a SpecificItemView or AnotherItemView 

    override func viewDidLoad() { 
     itemView?.setupItem(MyItem()) 
     itemView?.removeFromSuperview() /* this line won't compile */ 
    } 
} 

모든 내가 호출하려고 마지막 라인을 제외하고 작동 UIView 방법 (removeFromSuperview). ItemViewUIView과 아무런 관련이 없으므로 거기에는 놀랄 일이 아닙니다.

은 목표 C에서 나는 그렇게처럼 내 itemView의 바르를 지정하여이 문제를 해결할 :

@property (nonatomic, strong) UIView<ItemView> *itemView; 

하지만 스위프트에 대한 유사한 구문을 찾을 수 없습니다. Swift에서이 패턴을 사용할 방법이 없다고 생각합니다. 신속한 친화적 인 방식으로 UIView 클래스의 전반적인 목표를 어떻게 달성합니까? 내가 지금까지 발견했습니다

해키 솔루션은 내 ItemView 프로토콜 I (예를 들어 removeFromSuperview)를 호출 어떤 UIView 방법을 추가하는 것입니다.

내가 가진 또 다른 제안은,하지에 SO, Maurice Kelly에서, SpecificItemViewAnotherItemView 모두에서 내려 수는 ItemView 프로토콜을 구현하는 UIView 서브 클래스를 만드는 것이 었습니다. 당신은 그것을 implemented in this gist으로 볼 수 있습니다. 이 방법은 클래스 AND 프로토콜을 단일 유형 (예 : var itemView: ItemViewParentClass)으로 캡슐화하는 문제를 해결하지만 기본적으로 프로토콜을 무의미하게 만듭니다. 이제 모든 프로토콜의 메소드를 상위 클래스에 구현하고 하위 클래스에서이를 오버라이드하기 때문입니다. 이 솔루션의 가장 큰 단점은 View Controller에서 참조 할 때 하위 클래스 (SpecificItemView)의 인스턴스를 새로운 hypthetical 상위 클래스()로 캐스팅해야한다는 것입니다.

+0

컴파일러의 오류 메시지는 무엇인가요? – Aggressor

+0

itemview가 UIView를 확장하지 않습니다 – Aggressor

+0

샘플 코드가'var itemView : SpecificItemView?' – Aggressor

답변

-1

ItemViewUIView으로 확장되지 않지만 사용자의 SpecificItemView은 확장되지 않습니다. 당연히 귀하의 ItemView에는 removeFromSuperView이 없습니다. 당신의 ViewController에서

당신이 SpecificItemView

가 당신의 MyViewController 코드를 변경하는 대신, ItemView 타입의 객체를 선언

var itemView:SpecificItemView? 
+0

여기의 목표는 두 개의 다른 'SpecificItemView'클래스를 가지는 것 외에는 작동합니다. 'SongItemView'와'AlbumItemView' –

+0

왜 ItemView가 UIView를 확장하지 않는지 말해 줄 수 있습니까? – Aggressor

+0

나는 현재 좋은 이유가 없다. (하지만 어쩌면 거기에있다!)하지만 가정 할 때 자신 만의 remove() 함수를 만들 수는 없으며 하위 클래스를 인스턴스화 할 때 해당 멤버 변수를 할당하고 remove ? 따라서 ItemView에는 setupItem을 호출 할 때 할당되는 일반 View 멤버 변수가 있습니까? – Aggressor

1

당신이 발견하고 따라이 두 클래스를 지정하는 방법이없고, 객체에 대한 프로토콜.

이 문제를 해결하는 가장 쉬운 방법은 프로토콜에 removeFromSuperview (및 기타 UIView 메쏘드를 추가하는 것)을 추가하는 것입니다.

0

아마도 다음 (스위프트 4에서)이 트릭을 수행할까요?

class MyViewController: UIViewController { 
    typealias T = UIView & ItemView 

    var itemView: T? 
} 
관련 문제