2014-12-06 3 views
2

나는 performRequest()이라는 메서드가있는 메서드가 있습니다. JSONRequest 매개 변수가 필요합니다.Swift의 일반 완료 처리기

func convertJSONData<T where T: Entity>(jsonData: AnyObject, _: T.Type) -> [T] { 
     // Convert the data into Swift collection classes, enumerate over them, and create model objects 
     var json = JSON(data: jsonData as NSData, options: nil, error: nil) 
     var entities = [T]() 

     for obj in json { 
      let book = T(json: obj) 
      entities.append(book) 
     } 

    return entities 

법인이 프로토콜 : 당신이 볼 수 있듯이

public func performJSONRequest<T where T: Entity>(jsonRequest: JSONRequest, _: Type) { 
     // Make a request which returns a data object 
     var entities = self.convertJSONData(data, jsonKey: jsonRequest.jsonKey, T.self) 
     // Error: 'T' is not identical to 'Entity' 
     jsonRequest.completionHandler(entities, error) 
} 

, 그것은 다음과 같습니다 convertJSONData()를 호출

public typealias JSONCompletionHandler = ([Entity]?, NSError?) -> Void 

public class JSONRequest: Request { 
    public var completionHandler: JSONCompletionHandler 
    public var endPoint: String 
} 

그리고 performRequest()은 다음과 같습니다 JSONRequest이 같이 보입니다 모든 모델 클래스는 예를 들어 AuthorBook과 같습니다.

하나의 방법을 정의합니다 : init(json: JSON). TT:Entity으로 정의되었으므로 T:(json: obj)을 호출하여 Entity에 부합하는 모든 클래스의 인스턴스를 만들 수 있습니다.

에 대한 요청을 수행하려면 performJSONRequest()을 사용하고 싶습니다. 어떤 개체도 엔터티에 맞는 개체입니다. 예를 들어,이 같은 예약 인스턴스에 대한 요청을 구축하려는 :

var request = JSONRequest(endPoint: "books") { (let object: [Entity]?, let error: NSError?) -> Void in 
    // Cast object to [Book] and have fun 
} 

performJSONRequest<Book>(request) 

나는 내 인생은 내가 이것을 구현하는 것이 방법을 찾을 수 없기 때문. 지금은 performJSONRequest() 메서드에서 'T' is not identical to 'Entity'이라는 오류가 발생합니다. 완성 처리기의 배열을 [AnyObject]으로 정의하면 같은 오류가 발생합니다 : 'T' is not identical to 'AnyObject'.

도움 주셔서 감사합니다.

답변

8

해결 방법은 JSONRequest 클래스로 일반 유형을 이동하는 것입니다. 즉, Entity 프로토콜 대신에 JSONCompletionHandler을 요청하는 제네릭 유형으로 정의 할 수 있습니다. (코드 중 일부는 약간 사이비 듯 그래서 이것은 구현에 다시 맞게 일부 조정이 필요할 수 있습니다.)

JSONRequest 이제 일반적인 Entity 형의 억제와 클래스 :

public class JSONRequest<T: Entity>: Request { 
    // completion handler defined in terms of `T` 
    public typealias JSONCompletionHandler = ([T]?, NSError?) -> Void 

    // no further changes   
    public var completionHandler: JSONCompletionHandler 
    public var endPoint: String 
    public init(endPoint: String, completionHandler: JSONCompletionHandler) { 
     self.endPoint = endPoint 
     self.completionHandler = completionHandler 
    } 
} 

performJSONRequest 아무튼 더 이상 별도의 매개 변수로 전달 된 유형이 필요하지 않습니다.

public func performJSONRequest<T: Entity>(jsonRequest: JSONRequest<T>) { 
    // create array of `T` somehow 
    var entities: [T] = [] 
    var error: NSError? 

    // completionHandler expects [T]? and NSError? 
    jsonRequest.completionHandler(entities, error) 
} 

당신의 JSONRequest 인스턴스를 생성, 완료 핸들러에 주어진 유형 (예를 들어, [Book]?가) 일반 JSONRequest의 유형을 설정하고 개최한다 : jsonRequest 전문이기 때문에, 해당 매개 변수의 형식 정보를 가져옵니다 전체 과정 :

var request = JSONRequest(endPoint: "books") { (books: [Book]?, error) in 
    println(books?.count) 
} 
performJSONRequest(request) 
+0

환상적입니다. 나는'JSONCompletionHandler'를'JSONRequest' 내에 정의하면'T' 형 플레이스 홀더를 사용할 수 있다는 것을 깨닫지 못했습니다. 당신의 완전한 대답을 위해 정말 고마워요! – wander