Created
May 4, 2017 15:06
-
-
Save khanlou/bcb3589e78877c232058fa6646fbca6b to your computer and use it in GitHub Desktop.
Protocols with associatedtypes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
protocol JSONInitializable { | |
init?(data: Data) | |
} | |
protocol Request { | |
associatedtype OutputType: JSONInitializable | |
var url: URL { get } | |
} | |
class NetworkClient { | |
// Note that this function is generic over `RequestType`. This means that *at compile time*, it is known what RequestType (and therefore OutputType) will be. This is the crucial bit for making this technique work. | |
func send<RequestType> | |
(request: RequestType, // Here we use `RequestType` the new type that we defined for this function specifically, instead of the PAT `Request` | |
successBlock: @escaping (RequestType.OutputType) -> (), // The parameters can reference the types defined for this function. | |
failureBlock: @escaping (Error) -> ()) | |
where RequestType: Request // Here, we're "constraining" `RequestType` to conform to `Request`. More complex contraints are also possible. | |
{ | |
let urlRequest = URLRequest(url: request.url) | |
URLSession.shared.dataTask(with: urlRequest, completionHandler: { data, response, error in | |
if let error = error { | |
failureBlock( | |
} else if let data = data, | |
// We can freely refer to `RequestType.OutputType` here. | |
let output = RequestType.OutputType(data: data) { | |
successBlock(output) | |
} | |
}).resume() | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
protocol JSONInitializable { | |
init?(data: Data) | |
} | |
protocol Request { | |
associatedtype OutputType: JSONInitializable | |
var url: URL { get } | |
} | |
class NetworkClient { | |
func send(request: Request, | |
successBlock: @escaping (RequestType.OutputType) -> (), // Without the generic constraint, we have no way to refer to the OutputType of the *specific* Request that we're working with. | |
failureBlock: @escaping (Error) -> ()) { | |
let urlRequest = URLRequest(url: request.url) | |
URLSession.shared.dataTask(with: urlRequest, completionHandler: { data, response, error in | |
if let error = error { | |
failureBlock( | |
} else if let data = data, | |
// Same issue here. How can I specify that the OutputType I want is the one associated with the Request that I passed in? | |
let output = RequestType.OutputType(data: data) { | |
successBlock(output) | |
} | |
}).resume() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment