2016-08-12 2 views
3

Swift에서 유형 지우기를 몇 번 사용해야했지만 항상 일반 프로토콜이 필요했습니다. 이 경우 일반 전화 번호 과 일반 프로토콜이 모두 포함되어 있습니다.일반 열거 형 및 일반 프로토콜을 사용하는 신속한 유형 삭제

enum UIState<T> { 
    case Loading 
    case Success([T]) 
    case Failure(ErrorType) 
} 

protocol ModelsDelegate: class { 
    associatedtype Model 
    var state: UIState<[Model]> { get set } 
} 

extension ModelsDelegate { 

    func getNewState(state: UIState<[Model]>) -> UIState<[Model]> { 
     return state 
    } 

    func setNewState(models: UIState<[Model]>) { 
     state = models 
    } 
} 

그리고 여기가 내 타입이 삭제 제네릭 클래스입니다 :

class AnyModelsDelegate<T>: ModelsDelegate { 
    var state: UIState<[T]> { 

     get { return _getNewState(UIState<[T]>) } // Error #1 
     set { _setNewState(newValue) } 
    } 

    private let _getNewState: ((UIState<[T]>) -> UIState<[T]>) 
    private let _setNewState: (UIState<[T]> -> Void) 

    required init<U: ModelsDelegate where U.Model == T>(_ models: U) { 
     _getNewState = models.getNewState 
     _setNewState = models.setNewState 
    } 
} 

나는 다음과 같은 오류를 받고 있어요 (그들이 여기

필요한 확장자를 가진 나의 일반적인 열거 및 일반 프로토콜입니다) 코드 샘플에 표시 :

오류 # 1 :

Cannot convert value of type '(UIState<[T]>).Type' (aka 'UIState<Array<T>>.Type') to expected argument type 'UIState<[_]>' (aka 'UIState<Array<_>>')

나는 잠시 동안이 작업을 해왔으며이 코드에 "거의 효과가 있었다"는 변형이 많이있었습니다. 항상은 getter와 관련이 있습니다.

+1

당신은 그 유형 – dan

+0

I의 인스턴스를 소요하는 방법에 유형을 전달하는 :

위의 제안 된 변경과 함께 모두 모두를, 당신은 이런 식으로 뭔가를보고 코드를 할 것입니다 'getNewState' 함수가 왜 입력을 받는지 조금 혼란 스럽 습니다만, 분명히'() -> UIState <[Model]>'이어야합니까? getNewState와 setNewState 함수가 get과 setting을 당신의 타입 지우기로 포워딩하기 위해서만 존재한다면, 그것들은 꼭 필요하지 않습니다. 당신이 closure를 가진 타입 지우기 (즉,'_getNewState = {models. state}'&'_setNewState = {models.state = $ 0}'). – Hamish

+0

그래, 나도 조금 혼란스러워. :). 원래 입력을받지 않았을 때 원래 오류가 발생했기 때문에 입력이 필요합니다. 내가 리팩토링을 시도하겠습니다. – damianesteban

답변

2

, @dan has pointed out,이 오류를 발생시키는 문제는이 라인에서 대신 해당 유형의 인스턴스의 인수로 유형을 전달하는 데 노력하고 있다는 점이다 : 그러나

get { return _getNewState(UIState<[T]>) } 

, 내가 것 첫 번째 장소에서이 함수에 대한 인수 사용에 대해 질문하십시오. 확실히 함수를 가져 오는 함수에는 인수가 없어야합니다.

get { return _getNewState() } 

을 또한, 당신의 프로토콜 확장에 getNewStatesetNewState(_:) 기능 만 받고 전달하기 위해 존재하는 경우 :이 경우는 단순히 서명 () -> UIState<[T]>을 가지고, 그래서 같이 호출하기 위해 _getNewState 기능을 할 것입니다 및 유형 - 삭제로 state 재산의 설정은 - 당신은 완전히 그들을 제거하기로 코드를 단순화하고 유형 소거의 init 대신에 폐쇄 식을 사용할 수 있습니다

_getNewState = { models.state } 
_setNewState = { models.state = $0 } 

(목 더 많은 정보를위한 models 인수에 대한 참조를 캡처하여 ESE 작품의 요소를 의미

마지막으로, 나는 당신이이 경우에 T으로, 코드를 통해 UIState<T>보다는 UIState<[T]>을 참조하는 의미 의심) Closures: Capturing Values 참조 (여기에 2D 배열을 원한다면) .Success 케이스가 연결된 값으로 갖는 배열.

enum UIState<T> { 
    case Loading 
    case Success([T]) 
    case Failure(ErrorType) 
} 

protocol ModelsDelegate: class { 
    associatedtype Model 
    var state: UIState<Model> { get set } 
} 

class AnyModelsDelegate<T>: ModelsDelegate { 
    var state: UIState<T> { 
     get { return _getNewState() } 
     set { _setNewState(newValue) } 
    } 

    private let _getNewState:() -> UIState<T> 
    private let _setNewState: (UIState<T>) -> Void 

    required init<U: ModelsDelegate where U.Model == T>(_ models: U) { 
     _getNewState = { models.state } 
     _setNewState = { models.state = $0 } 
    } 
} 
+0

우수. 고맙습니다. 그리고 네, 저는 2D 배열을 원하지 않았습니다. 오류를 해결하기 위해 노력하면서 실수가되었습니다. – damianesteban

+0

@damianesteban 도와 드리겠습니다. :) – Hamish