How to Pass Protocol with Associated Type (Generic Protocol) as Parameter in Swift

How to pass protocol with associated type (generic protocol) as parameter in Swift?

If you use typealias in a protocol to make it generic-like, then you cannot use it as a variable type until the associated type is resolved. As you have probably experienced, using a protocol with associated type to define a variable (or function parameter) results in a compilation error:

Protocol 'MyProtocol' can only be used as a generic constraint because it has Self os associated type requirements

That means you cannot use it as a concrete type.

So the only 2 ways I am aware of to use a protocol with associated type as a concrete type are:

  • indirectly, by creating a class that implements it. Probably not what you have planned to do
  • making explicit the associated type like you did in your func

See also related answer https://stackoverflow.com/a/26271483/148357

How to pass generic protocol as function parameter

You must use Datatype as a generic constraint:

func set<T: Datatype>(key: String, type: T ,value: T.dataType)

Note how you also need to change the type of the value parameter to T.dataType, for this to be type safe. That is, the value you pass in must be the same type as the dataType of the type parameter.

Swift: How to pass the Generic protocol as a parameter for another protocol

protocol OperationDelegate {
associatedtype T
func onOperationFinished(result:Array<T>)
func onOperationError(error: Error, errorMessage:String)
}

protocol ResultDelegate {
func findResult<OpDelegate: OperationDelegate>(query: String, odelegate: OpDelegate)
}

//Added few PlayGround works

    class ResultsFinder: ResultDelegate {

func findResult<OpDelegate>(query: String, odelegate: OpDelegate) where OpDelegate : OperationDelegate {

print(#function)
// Do some operations
let s1 = Student()
s1.name = "one"
let s2 = Student()
s2.name = "two"

let addressList = [s1,s2]
odelegate.onOperationFinished(result: addressList as! [OpDelegate.T])

}
}

also

class ResultDisplay: OperationDelegate {

typealias T = Student

func onOperationFinished(result: [Student]) {
// Display address
print(#function)
}

func onOperationError(error: Error, errorMessage: String) {
// Display error
print(#function)
}

}

class Mainfunction {

let resultDisplay = ResultDisplay()
let finder = ResultsFinder()
func start() {

print(#function)
finder.findResult(query: "Sridhar", odelegate: resultDisplay)

}

}

let main = Mainfunction()
main.start()

Swift protocol with associatedtype as a parameter type

You cannot use protocols with associated type as a field.

You have to use them only as an implementation of classes. In most cases, those classes should are generic.

For instance, this code is allowed:

public struct CreateNewAccount<T, K>: UseCase {
public typealias ResponseType = T
public typealias Parameters = K
}

and so,

private let createNewAccount: CreateNewAccount<YouClass1,YouClass2>

or wrap it somehow by another protocol.

SwifT: Generic function that gets generic protocol as parameter not working

I'm not sure why you say "the protocol only demands that Element implements CustomStringConvertible." The protocol demands that echo accept and return its Element, which may or may not be String. For example, I can implement this conforming type:

struct AnotherFoo: FooProtocol {
func echo(element: Int) -> Int { fatalError() }
}

So what should happen if I then call:

callEcho(container: AnotherFoo())

This would try to pass a string literal to a function that requires an Int.

How to implement to a generic protocol, which has a function using the Type of associatedtype?

This isn't how associated types work. get should be generic over its response type, but the network manager itself isn't generic over some specific response type. I believe what you meant to here is this:

protocol NetworkManager {
func get<ResponseObject>(url: String,
ofType: ResponseObject.Type,
completion: (Result<ResponseObject, Error>) -> Void)
where ResponseObject: Decodable
}

class TrivialNetworkManager: NetworkManager {
func get<ResponseObject>(url: String,
ofType: ResponseObject.Type,
completion: (Result<ResponseObject, Error>) -> Void)
where ResponseObject: Decodable {
completion(.success(SomeObject(id: "1", name: "hello"))
}
}

For a more worked-out version of this specific problem you can read my protocol series, but the important concept here is that NetworkManager doesn't vary over its ResponseType, so there's no reason to make its ResponseType an associated type.

What you wrote is trying to say "some network managers will have a Codable ResponseType, and other network managers will have some other kind of ResponseType." Not "some other specific response type (like User)" but "some other protocol that its response types would have to conform to." While it's conceivable to build something like that, it's much more complex, and you'd need to explain your precise use case in order to design it. Specifically, you'd need to show several concrete implementations of your protocol in order to see what kind of shared code you're trying to extract.

Use Protocol with associatedtype as a Type

Since ViewBuilder is a protocol, when you try make T a concrete type, it creates a conflict whether that type T is HeaderTitleBuilder or HeaderButtonBuilder. T cannot be both at the same time.

You can instead make both have a separate generic parameter, e.g,:

struct HeaderBuilder<TitleBuilder: ViewBuilder, ButtonBuilder: ViewBuilder> where TitleBuilder.In == DataSource, TitleBuilder.Out == ViewFactory, ButtonBuilder.In == DataSource, ButtonBuilder.Out == ViewFactory {
private(set) var titleBuilder: TitleBuilder
private(set) var buttonBuilder: ButtonBuilder
}


Related Topics



Leave a reply



Submit