I'm using Swift 2.2 and I declared a protocol with associated type as follow:
protocol CollectionViewModeling {
associatedtype CellType
func cellAtIndexPath(indexPath: NSIndexPath) -> CellType
}
Now I have a view model protocol conform to the above protocol :
enum MyItemCell {
case MyItemCell1, MyItemCell2
}
protocol ItemsListViewModeling: CollectionViewModeling {
associatedtype CellType = MyCell
}
Finally, somewhere else, I want to declare a var that is conform to le protocol ItemsListViewModeling :
var viewModel: ItemsListViewModeling
And I'm getting this error :
Protocol 'ItemsListViewModeling' can only be used as a generic constraint because it has Self or associated type requirements
But I can easily create a class that implements this protocol.
Is it possible to declare a var to an associated typed protocol ? As I'm giving the final type of the associated type in the protocol ItemsListViewModeling, I don't understand why am I seeing this error from the compiler.
Thanks
See there stackoverflow.com
You can't treat protocols with associated types like regular protocols
and declare them as standalone variable types.
Related
I am trying to create a Dictionary (actually a HashSet) keyed on a custom protocol in Swift, but it is giving me the error in the title:
Protocol 'myProtocol' can only be used as a generic constraint because it has Self or associated type requirements
and I can't make heads nor tails of it.
protocol Observing: Hashable { }
var observers = HashSet<Observing>()
Protocol Observing inherits from protocol Hashable, which in turn inherits from protocol Equatable. Protocol Equatable has the following requirement:
func ==(lhs: Self, rhs: Self) -> Bool
And a protocol that contains Self somewhere inside it cannot be used anywhere except in a type constraint.
Here is a similar question.
To solve this you could use generics. Consider this example:
class GenericClass<T: Observing> {
var observers = HashSet<T>()
}
I'm trying to build a protocol for a NSXPCInterface and I'm facing a weird issue.
I created a protocol :
public protocol AProtocol {
//functions in here
}
and when I want to add it to the exportedInterface of NSXPCConnection,
let newConnection: NSXPCConnection
newConnection.exportedInterface = NSXPCInterface(with: AProtocol.self)
I get this strange error :
Cannot convert value of type 'AProtocol.Protocol' to expected argument type 'Protocol'
I don't know the reason but its working try this. Add #objc before protocol
#objc public protocol AProtocol {
//functions in here
}
don't forget to initialise NSXPCConnection
Edit: found reason from here
"#objc" that exposes the protocol to the objective c runtime and allows us to pass any "Protocol Type" as a parameter
The protocol you pass to an instance of NSXPCInterface has to be an Objective-C protocol as described in the documentation:
protocol: The Objective-C protocol that this interface is based on.
So all you have to do is mark AProtocol with #objc
#objc public protocol AProtocol {
}
How I can create a protocol variable. My goal is a protocol will be have a function with a generic type and I'm using associatedtype which is accessing to Class and the function will be return generic type. Example declaration below:
public protocol ComponentFactory {
associatedtype T // A class and that class can be inherit from another so I need define generic type here
func create() -> T
}
I want to declare a variable for this protocol like that:
fileprivate var mComponentFactoryMap = Dictionary<String, ComponentFactory>()
At this line I receive a error:
Protocol 'ComponentFactory' can only be used as a generic constraint because it has Self or associated type requirements
I see from Android, actually from kotlin they have a declare for interface like:
private val mComponentFactoryMap = mutableMapOf<String, ComponentFactory<*>>()
Any guys can help me, how I can declare this from Swift?
I've solved this from few months ago with descriptions below. Please check it and give me another solution if you have.
Firstly, make some change for Protocol. At associatedtype T should be change to associatedtype Component and Component is a class which will be inherited from another class (important step).
public protocol ProComponentFactory {
associatedtype Component
func create() -> Component?
}
Second, I will make a Generic Struct with inheritance from ProComponentFactory:
public struct ComponentFactory<T>: ProComponentFactory {
public typealias Component = T
public func create() -> T? { return T.self as? T }
}
Well done, for now you can define a variable as I example in my question above:
fileprivate var mComponentFactoryMap = Dictionary<String, ComponentFactory<Component>>()
As well for any class was inherit from Component and variable mComponentFactoryMap can using extension inside.
I'm trying to use Protocol-Oriented Pgrogramming for model layer in my application.
I've started with defining two protocols:
protocol ParseConvertible {
func toParseObject() -> PFObject?
}
protocol HealthKitInitializable {
init?(sample: HKSample)
}
And after implementing first model which conforms to both I've noticed that another model will be basically similar so I wanted to create protocol inheritance with new one:
protocol BasicModel: HealthKitInitializable, ParseConvertible {
var value: AnyObject { get set }
}
A you can see this protocol has one additional thing which is value but I want this value to be type independent... Right now I have models which use Double but who knows what may show up in future. If I leave this with AnyObject I'm sentenced to casting everything I want to use it and if I declare it as Double there's no sense in calling this BasicModel but rather BasicDoubleModel or similar.
Do you have some hints how to achieve this? Or maybe I'm trying to solve this the wrong way?
You probably want to define a protocol with an "associated type",
this is roughly similar to generic types.
From "Associated Types" in the Swift book:
When defining a protocol, it is sometimes useful to declare one or
more associated types as part of the protocol’s definition. An
associated type gives a placeholder name (or alias) to a type that is
used as part of the protocol. The actual type to use for that
associated type is not specified until the protocol is adopted.
Associated types are specified with the typealias keyword.
In your case:
protocol BasicModel: HealthKitInitializable, ParseConvertible {
typealias ValueType
var value: ValueType { get set }
}
Then classes with different types for the value property can
conform to the protocol:
class A : BasicModel {
var value : Int
func toParseObject() -> PFObject? { ... }
required init?(sample: HKSample) { ... }
}
class B : BasicModel {
var value : Double
func toParseObject() -> PFObject? { ... }
required init?(sample: HKSample) { ... }
}
For Swift 2.2/Xcode 7.3 and later, replace typealias in the
protocol definition by associatedtype.
Can anyone please explain class only protocols to me in Swift. I understand what protocols are and why we use them. I also understand that its recommended to use class only protocols when we use reference type objects in it and want to limit the protocol conformation to classes only. However, I can't find any good answer to support that recommendation. Why is it recommended? What is the drawbacks of using normal protocols in that case.
One use case:
You have a "delegate" protocol and someone wants to have a weak property of that protocol type. weak can only be used on reference types; therefore, the protocol must be class-only.
Another use case used to be to extend reference types to adopt protocols. You can't extend AnyObject itself (to inherit from another protocol, or for any other reason) but you have any reference types you want adopt a protocol inherited from AnyObject.
For example, having class equality based on unique identity is often a perfectly fine solution, so you could adopt EquatableObject:
public protocol EquatableObject: AnyObject, Equatable { }
public extension EquatableObject {
static func == (class0: Self, class1: Self) -> Bool {
class0 === class1
}
}
But now, we have protocol extension constraints (using where clauses), so instead of extending AnyObject, we can extend the protocol, and use AnyObject as a constraint. It looks backwards but operates identically, and removes the need for our own protocol. 🥳
public extension Equatable where Self: AnyObject {
static func == (class0: Self, class1: Self) -> Bool {
class0 === class1
}
}