Swift에서 함수 매개 변수로 프로토콜을 준수하는 클래스


91

Objective-C에서는 프로토콜을 따르는 클래스를 메소드 매개 변수로 지정할 수 있습니다. 예를 들어 다음 UIViewController을 준수하는 a 만 허용하는 메서드를 가질 수 있습니다 UITableViewDataSource.

- (void)foo:(UIViewController<UITableViewDataSource> *)vc;

Swift에서이 작업을 수행하는 방법을 찾을 수 없습니다 (아마 아직 불가능할 수도 있습니다). 을 사용하여 여러 프로토콜을 지정할 수 func foo(obj: protocol<P1, P2>)있지만 객체가 특정 클래스에 속하도록 어떻게 요구합니까?


예를 들어 MyViewControllerClass와 같은 사용자 정의 클래스를 만들고 클래스가 관심있는 프로토콜을 준수하는지 확인할 수 있습니다. 그런 다음 인수가 해당 사용자 정의 클래스를 허용한다고 선언하십시오. 나는 그것이 모든 상황에서 작동하지 않을 것이라는 것을 알고 있지만 그것은 방법입니다 ... 당신의 질문에 대한 대답은 아닙니다. 더 많은 해결 방법.
CommaToast

답변:


132

foo일반 함수로 정의 하고 유형 제약 조건을 사용하여 클래스와 프로토콜을 모두 요구할 수 있습니다.

스위프트 4

func foo<T: UIViewController & UITableViewDataSource>(vc: T) {
    .....
}

Swift 3 (Swift 4에서도 작동)

func foo<T: UIViewController>(vc:T) where T:UITableViewDataSource { 
    ....
}

스위프트 2

func foo<T: UIViewController where T: UITableViewDataSource>(vc: T) {
    // access UIViewController property
    let view = vc.view
    // call UITableViewDataSource method
    let sections = vc.numberOfSectionsInTableView?(tableView)
}

3
이것이 필요한 것이 조금 아쉽다고 생각합니다. 앞으로는 provide와 같은 더 깨끗한 구문이있을 것입니다 protocol<>(하지만 protocol<>비 프로토콜 유형은 포함 할 수 없음).
jtbandes 2014 년

이것은 나를 슬프게 만듭니다.
DCMaxxx

호기심으로 numberOfSectionsInTableView인해에서 필수 기능이기 때문에 명시 적으로 풀 수 UITableViewDataSource없습니까?
rb612 2015

numberOfSectionsInTableView:선택 사항입니다 tableView:numberOfRowsInSection:.을 (를) 생각할 수 있습니다 .
Nate Cook

11
스위프트 3 년이의 설정에 Xcode를 8 베타 6으로 사용되지 않는 것으로 나타납니다 :func foo<T: UIViewController>(vc:T) where T:UITableViewDataSource { ... }
LOP_Luke

29

Swift 4에서는 new & sign으로 이것을 달성 할 수 있습니다.

let vc: UIViewController & UITableViewDataSource

17

Swift 책 문서는 where 절과 함께 유형 제약 조건을 사용하도록 제안합니다.

func someFunction<C1: SomeClass where C1:SomeProtocol>(inParam: C1) {}

이는 "inParam"이 "SomeProtocol"을 준수하는 조건과 함께 "SomeClass"유형임을 보장합니다. 쉼표로 구분 된 여러 where 절을 지정할 수도 있습니다.

func itemsMatch<C1: SomeProtocol, C2: SomeProtocol where C1.ItemType == C2.ItemType,    C1.ItemType: SomeOtherProtocol>(foo: C1, bar: C2) -> Bool { return true }

1
문서에 대한 링크는보기에 좋았을 것입니다.
Raj

4

Swift 3를 사용하면 다음을 수행 할 수 있습니다.

func foo(_ dataSource: UITableViewDataSource) {
    self.tableView.dataSource = dataSource
}

func foo(_ delegateAndDataSource: UITableViewDelegate & UITableViewDataSource) { 
    //Whatever
}

1
이것은 단지 빠른 3에 프로토콜이 아닌 프로토콜 및 클래스에 적용
아르 템 Goryaev에게

2

이 방법은 어떻습니까? :

protocol MyProtocol {
    func getTableViewDataSource() -> UITableViewDataSource
    func getViewController() -> UIViewController
}

class MyVC : UIViewController, UITableViewDataSource, MyProtocol {

    // ...

    func getTableViewDataSource() -> UITableViewDataSource {
        return self
    }

    func getViewController() -> UIViewController {
        return self
    }
}

func foo(_ vc:MyProtocol) {
    vc.getTableViewDataSource() // working with UITableViewDataSource stuff
    vc.getViewController() // working with UIViewController stuff
}

2

스위프트 5 :

func foo(vc: UIViewController & UITableViewDataSource) {
    ...
}

그래서 본질적으로 위의 Jeroen 의 대답.


0

2015 년 9 월 참고 : 이것은 Swift 초기의 관찰입니다.

불가능 해 보인다. Apple은 일부 API에서도 이러한 성가심을 가지고 있습니다. 다음은 iOS 8에 새로 도입 된 클래스의 한 예입니다 (베타 5 기준).

UIInputViewControllertextDocumentProxy재산 :

Objective-C에서 다음과 같이 정의됩니다.

@property(nonatomic, readonly) NSObject<UITextDocumentProxy> *textDocumentProxy;

그리고 Swift에서 :

var textDocumentProxy: NSObject! { get }

Apple의 문서 링크 : https://developer.apple.com/library/prerelease/iOS/documentation/UIKit/Reference/UIInputViewController_Class/index.html#//apple_ref/occ/instp/UIInputViewController/textDocumentProxy


1
이것은 자동 생성 된 것처럼 보입니다 : Swift 프로토콜은 객체로 전달 될 수 있습니다. 이론적으로 그들은 단지 입력 할 수 있습니다var textDocumentProxy: UITextDocumentProxy! { get }
atlex2

@ atlex2 UITextDocumentProxy 프로토콜 유형을 선호하는 NSObject 클래스 유형을 잃었습니다.
titaniumdecoy

@titaniumdecoy 아니, 틀렸어; UITextDocumentProxy 대부분의 프로토콜과 같이 선언 된 경우 당신은 여전히 NSObject의가 있습니까이 있습니다 :@protocol MyAwesomeCallbacks <NSObject>
CommaToast

@CommaToast Not in Swift, 이것이이 질문에 관한 것입니다.
titaniumdecoy

@titaniumdecoy 네, 원래 맞았어요. 나는 혼란 스러웠다! 틀렸다고 죄송합니다. 이 경우에는 여전히 NSObjectProtocol이 있습니다 ...하지만 같은 것이 아님을 압니다.
CommaToast
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.