Adding multiple delegates instead of only one is a quite common task. Suppose we have protocol and a class:
protocol ObserverProtocol
{
...
}
class BroadcasterClass
{
// Error: Type 'ObserverProtocol' does not conform to protocol 'AnyObject'
private var _observers = NSHashTable<ObserverProtocol>.weakObjects()
}
If we try to force ObserverProtocol to conform AnyObject protocol, we will get another error:
Using 'ObserverProtocol' as a concrete type conforming to protocol 'AnyObject' is not supported
Is it even possible to create a set of weak delegates in Swift 3.0?
Sure, it's possible.
AnyObject is the Swift equivalent of id in Objective C. To get your code to compile, you just need to add the #objc annotation to your protocol, to tell Swift that the protocol should be compatible with Objective C.
So:
#objc protocol ObserverProtocol {
}
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>()
}
In addition to this syntax with a protocol extension:
protocol P {}
extension P where Self : UIView {}
... I discovered by accident that you can use the same where clause on the protocol itself:
protocol P where Self : UIView {}
Notice that this is not the same as a where clause constraining a generic protocol, and does not itself make P a generic protocol.
My experiments seem to show that only a colon can be used here, and the thing after the colon must be a class or a protocol (which may be generic).
I became curious: how did this escape my notice? So I went hunting for evidence of when it arose. In Swift 3.0, the former syntax is legal but not the latter. In Swift 3.3, both are legal. So the latter syntax must have been quietly introduced in something like Swift 3.2. I say "quietly" because I can't find anything about it in the release notes.
What is the second syntax for? Is it, as it appears, just a convenient way of making sure no other type can adopt this protocol? The Swift headers do not seem to make any use of it.
The ability to put superclass constraints on protocols declarations (that is, being able to define protocol P where Self : C where C is the type of a class) was a premature consequence of SE-0156, and the syntax should have been rejected in Swift 4.x until the feature was implemented. Attempting to use this feature in Swift 4.x can cause miscompilation and crashes, so I would avoid using it until Swift 5.
In Swift 5 (Xcode 10.2) the feature has now been implemented. From the release notes:
Protocols can now constrain their conforming types to those that
subclass a given class. Two equivalent forms are supported:
protocol MyView: UIView { /*...*/ }
protocol MyView where Self: UIView { /*...*/ }
Swift 4.2 accepted the second form, but it wasn’t fully implemented
and could sometimes crash at compile time or runtime. (SR-5581)
(38077232)
This syntax places a superclass constraint on MyView which restricts conforming types to those inheriting from (or being) UIView. In addition, the usage of MyView is semantically equivalent to a class existential (e.g UIView & MyView) in that you can access both members of the class and requirements of the protocol on the value.
For example, expanding upon the release notes' example:
protocol MyView : UIView {
var foo: Int { get }
}
class C : MyView {} // error: 'P' requires that 'C' inherit from 'UIView'
class CustomView : UIView, MyView {
var foo: Int = 0
}
// ...
let myView: MyView = CustomView(frame: .zero)
// We can access both `UIView` members on a `MyView` value
print(myView.backgroundColor as Any)
// ... and `MyView` members as usual.
print(myView.foo)
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 {
}
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.
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
}
}