How to Use Multiple Protocols in Swift with Same Protocol Variables

How to use multiple protocols in Swift with same protocol variables?

The simple answer is that you can't.

Maybe one protocol depends on another, in which case you would use the dependent protocol for the type of your delegate.

Types conforming to multiple protocols in swift

This should work:

var identityToken: NSObjectProtocol & NSCopying & NSCoding 

Note you have to use NSObjectProtocol instead of NSObject in swift.

Here are some additional examples:

Array of objects conforming to multiple protocols:

var array: [NSObjectProtocol & NSCopying & NSCoding]

Function with a parameter that conforms to multiple protocols:

func foo(param: NSObjectProtocol & NSCopying & NSCoding) {

}

For Swift version before 3.1, use:

var identityToken: (NSObjectProtocol, NSCopying, NSCoding)

Casting type conforming to multiple protocols as a single protocol

Swift cant perform a full collection type conversion (only available for some behind-the-hood automatically Objective-C-bridgeable objects, or between collections of super- and subclass elements) where the elements of the collection themselves are associated in the sense that one can be assigned to the other. You need to explicitly help out the compiler to show that element-by-element conversion is valid, e.g. using a .map operation prior to calling printNames

printNames(identifiableAndNamableItems.map{ $0 })
/* 0: Jeff
1: Fido */

Note also that you needn't go all out with multiple protocols to see this behaviour; it is likewise apparent for e.g. the following more minimal example

protocol Foo { }
struct Bar: Foo {}

let bar = Bar()
let foo: Foo = bar // ok

let barArr: [Bar] = [Bar(), Bar()]
let fooArr: [Foo] = barArr // cannot convert value of type '[Bar]' to specified type '[Foo]'
// let fooArr: [Foo] = barArr.map{ $0 } // OK

Swift: Property conforming to a specific class and in the same time to multiple protocols

You can do this with a generic class using a where clause:

A where clause enables you to require that an associated type conforms
to a certain protocol, and/or that certain type parameters and
associated types be the same.

To use it, make the class your property is defined in a generic class with a type constraint to check if the type parameter for your property matches your desired base class and protocols.

For your specific example, it could look something like this:

class MyViewController<T where T: UIView, T: Protocol1, T: Protocol2>: UIViewController {
var myView: T

// ...
}

Swift: Make two types with the same shape conform to a common protocol

The name properties of the generated structs have type Name, not NameRepresenting as required by the protocol. Covariant returns are not supported in Swift just yet :(

What you can do is to add an associated type requirement:

protocol UserRepresenting {
associatedtype Name : NameRepresenting
var email: String { get }
var name: Name { get }
}

This requires that the conformers to have a type that conforms to NameRepresenting and is the type of the name property.

However, now that it has an associated type requirement, you cannot use UserRepresenting as the type of a variable/function parameter. You can only use it in generic constraints. So if you have a function that takes a UserRepresenting, you need to write it like this:

func someFunction<UserType: UserRepresenting>(user: UserType) {

}

and if one of your classes/structs need to store a property of type UserRepresenting, you need to make your class/struct generic too:

class Foo<UserType: UserRepresenting> {
var someUser: UserType?
}

This may or may not work for your situation. If it doesn't, you can write a type eraser:

struct AnyUserRepresenting : UserRepresenting {
var email: String
var name: Name
struct Name : NameRepresenting {
var givenName: String
var familyName: String
}

init<UserType: UserRepresenting>(_ userRepresenting: UserType) {
self.name = Name(
givenName: userRepresenting.name.givenName,
familyName: userRepresenting.name.familyName)
self.email = userRepresenting.email
}
}

Now you can convert any UserRepresenting to this AnyUserRepresenting, and work with AnyUserRepresenting instead.

How to create implement multi protocol in one ViewController?

You don't need a separate type for this in Swift. Your Java interface can be represented with a closure in Swift. Specifically, it is a closure of type (Int) -> Void.

You can declare joinDay and birthday like this in Swift:

var joinDay: ((Int) -> Void)?
var birthday: ((Int) -> Void)?

To assign an "implementation", do:

joinDay = { value in
// do something with the parameter "value"
print(value)
}

And the equivalent of calling joinDay.didChanged(someValue) in Swift would be:

joinDay?(someValue)

For more info on how to use closures, see Closures in the Swift Guide.



Related Topics



Leave a reply



Submit