How to create common protocols in Swift?

I would like to create a protocol with a method that accepts common input and returns a common value.

This is what I have tried so far, but is causing a syntax error.

Using undeclared identifier T.

What am I doing wrong?

protocol ApiMapperProtocol { func MapFromSource(T) -> U } class UserMapper: NSObject, ApiMapperProtocol { func MapFromSource(data: NSDictionary) -> UserModel { var user = UserModel() as UserModel var accountsData:NSArray = data["Accounts"] as NSArray return user } } 
+78
swift
Jun 28 '14 at 18:50
source share
3 answers

This is slightly different for protocols. Look at the “Related Types” in the Apple documentation .

This is how you use this 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 } } 
+121
Jun 30 '14 at 17:14
source share

To clarify Lou Franco, answer a little: if you want to create a method that uses a specific ApiMapperProtocol , you do it like this:

 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 now guaranteed to accept only SourceType compatible with this ApiMapperProtocol :

 let dictionary: NSDictionary = ... let uses = UsesApiMapperProtocol() let userModel: UserModel = uses.usesApiMapperProtocol(UserMapper() source: dictionary) 
+19
Mar 05 '15 at 3:56
source share

You can use template methods with erase type ...

 protocol HeavyDelegate : class { func heavy<P, R>(heavy: Heavy<P, R>, shouldReturn: P) -> R } class Heavy<P, R> { typealias Param = P typealias Return = R weak var delegate : HeavyDelegate? func inject(p : P) -> R? { if delegate != nil { return delegate?.heavy(self, shouldReturn: p) } return nil } func callMe(r : Return) { } } class Delegate : HeavyDelegate { typealias H = Heavy<(Int, String), String> func heavy<P, R>(heavy: Heavy<P, R>, shouldReturn: P) -> R { let h = heavy as! H h.callMe("Hello") print("Invoked") return "Hello" as! R } } let heavy = Heavy<(Int, String), String>() let delegate = Delegate() heavy.delegate = delegate heavy.inject((5, "alive")) 
-3
Aug 16 '15 at 13:34 on
source share



All Articles