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: Array property with elements conforming to a class and multiple protocols simultaneously
I just came across this old question of mine and because the Swift language evolved since accepting the partial answer I decided to post another answer which actually solves the problem I originally asked.
From version 4, Swift supports protocol composition using the &
sign which can also be composed with one class type.
class BaseClass {}
protocol Protocol1 {}
protocol Protocol2 {}
class ConformingClass1: BaseClass, Protocol1, Protocol2 {}
class ConformingClass2: BaseClass, Protocol1, Protocol2 {}
// It works for a variable holding a single object.
let object: BaseClass & Protocol1 & Protocol2 = ConformingClass1()
// And it also works for a variable holding an array of objects.
let array: [BaseClass & Protocol1 & Protocol2] = [ConformingClass1(), ConformingClass2()]
Swift class conformance of multiple protocols (XCode 7, iOS 9, Swift 2.1)
You have to implments the protocol function in the class
For example
protocol Protocol_A {
func someFunc()
}
protocol Protocol_B {
func someFuncB()
}
protocol Protocol_C {
}
protocol Protocol_D {
}
class ViewController: UIViewController, Protocol_A, Protocol_B, Protocol_C, Protocol_D {
func someFunc() {
}
func someFuncB() {
}
}
If you want function to be optional
@objc protocol Protocol_A {
optional func someFunc()
}
var defined in protocol doesn't conform to multiple protocol
You have two issues: firstly, the property name must match that declared in the protocol, secondly you need to type annotate the variable to be of type BProtocol
as Hamish explained in the comment.
protocol AProtocol {
var aProperty : BProtocol {get set}
}
protocol BProtocol {}
class BClass: BProtocol {}
class AClass: AProtocol {
var aProperty: BProtocol = BClass()
}
You should also conform to the Swift naming convention, which is lowerCamelCase for variable names, so I changed AProperty
to its correct form, aProperty
.
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.
Implement a public method that rely on a private property in Swift using protocols
Following this discussion from Swift forum, there are two ways to solve the issue.
First one is straightforward:
/// The publically visible capabilities.
public protocol SameModifierProtocol {
func modifier(x: Int) -> SameModifierProtocol
}
/// The internal requirements on which the default implementation relies.
internal protocol SynthesizedSameModifierProtocolConformance:
SameModifierProtocol {
var x: Int { get set }
}
/// The default implementation.
extension SynthesizedSameModifierProtocolConformance {
public func modifier(x: Int) -> SameModifierProtocol{
var s = self
s.x = x
return s
}
}
/// Conforms to the public protocol
/// and requests the default implementation from the internal one.
/// Clients can only see the public protocol.
public struct Component: SynthesizedSameModifierProtocolConformance {
internal var x: Int = 0
public init() {}
}
The second involves an unofficial feature @_spi, that allows to make implementation details unexposed in a public protocol:
public protocol SameModifierProtocol {
@_spi(SameModifier) var x: Int { get set }
}
extension SameModifierProtocol {
public func modifier(x: Int) -> Self {
var s = self
s.x = x
return s
}
}
public struct Component: SameModifierProtocol {
@_spi(SameModifier) public var x: Int = 0
public init() {}
}
How to declare a property of a particular class which is also protocol conformant?
Answering my own question 3 years later, Swift 4 supports combined class and protocol types:
let delegate: UIViewController & MyDelegateProtocol
Related Topics
Get Button Pressed Id on Swift Via Sender
Swift - Custom Setter on Property
How to Stop Timer in Text View
Can Associated Values and Raw Values Coexist in Swift Enumeration
Do Swift Inner Classes Have Access to Self of Outer Class
Using Foreach Loop with Binding Causes Index Out of Range When Array Shrinks (Swiftui)
How to Convert Range in Nsrange
Self' Used Before All Stored Properties Are Initialized
Ios13 Navigation Bar Large Titles Not Covering Status Bar
Default Value For Optional Generic Parameter in Swift Function
Swift Alternative to Performselectoronmainthread
How to Create an Instance of a Class from a String in Swift
Is There a Prefix Header (Or Something with This Functionality) in Swift