How to create generic protocols in Swift?
To expound on Lou Franco's answer a bit, If you wanted to create a method that used a particular ApiMapperProtocol
, you do so thusly:
protocol ApiMapperProtocol {
associatedtype T
associatedtype U
func mapFromSource(T) -> U
}
class UserMapper: NSObject, ApiMapperProtocol {
// these typealiases aren't required, but I'm including them for clarity
// Normally, you just allow swift to infer them
typealias T = NSDictionary
typealias U = UserModel
func mapFromSource(data: NSDictionary) -> UserModel {
var user = UserModel()
var accountsData: NSArray = data["Accounts"] as NSArray
// For Swift 1.2, you need this line instead
// var accountsData: NSArray = data["Accounts"] as! NSArray
return user
}
}
class UsesApiMapperProtocol {
func usesApiMapperProtocol<
SourceType,
MappedType,
ApiMapperProtocolType: ApiMapperProtocol where
ApiMapperProtocolType.T == SourceType,
ApiMapperProtocolType.U == MappedType>(
apiMapperProtocol: ApiMapperProtocolType,
source: SourceType) -> MappedType {
return apiMapperProtocol.mapFromSource(source)
}
}
UsesApiMapperProtocol
is now guaranteed to only accept SourceType
s compatible with the given ApiMapperProtocol
:
let dictionary: NSDictionary = ...
let uses = UsesApiMapperProtocol()
let userModel: UserModel = uses.usesApiMapperProtocol(UserMapper()
source: dictionary)
It's a little different for protocols. Look at "Associated Types" in Apple's documentation.
This is how you use it in your example
protocol ApiMapperProtocol {
associatedtype T
associatedtype U
func MapFromSource(_:T) -> U
}
class UserMapper: NSObject, ApiMapperProtocol {
typealias T = NSDictionary
typealias U = UserModel
func MapFromSource(_ data:NSDictionary) -> UserModel {
var user = UserModel()
var accountsData:NSArray = data["Accounts"] as NSArray
// For Swift 1.2, you need this line instead
// var accountsData:NSArray = data["Accounts"] as! NSArray
return user
}
}