Reputation: 9637
I'm trying to convert my Objective-C code to swift. In Objective-C I have the following protocol:
@protocol RWOverlaySelectionDelegate <NSObject>
-(void)areaSelected:(UIView *)view allPoints:(NSArray *)points;
@end
and following class has a weak property that reference the protocol (obviously it's defined as weak to prevent strong reference cycle).
@interface RWMapSelectionLayer : UIView
@property(weak, nonatomic) id <RWOverlaySelectionDelegate> delegate;
@end
Now the Swift equivalent:
the protocol:
protocol RWOverlaySelectionDelegate {
func areaSelected(view:UIView,points:CGPoint[])
}
and the class that has a property which conforms to that protocol:
class RWMapSelectionLayer:NSObject {
weak var delegate:RWOverlaySelectionDelegate?
}
But I'm getting 'weak' cannot be applied to non-class type 'RWOverlaySelectionDelegate'
compile time error in this line : weak var delegate:RWOverlaySelectionDelegate?
Then I tried to convert my property to an AnyObject
that conforms to RWOverlaySelectionDelegate
using following syntax:
weak var delegate: AnyObject<RWOverlaySelectionDelegate>?
Now I'm interfering with Generics and compiler showing: Cannot specialize non-generic type 'AnyObject'
error.
In another unsuccessful try I changed it to
weak var delegate: AnyObject:RWOverlaySelectionDelegate?
read it as "Delegate is on type AnyObject where AnyObject should conform to RWOverlaySelectionDelegate"
This is again incorrect because of two colons(:) in a single statement.
Would appreciate if someone can help me to enforce conformance to a protocol on AnyObject or Any
Upvotes: 10
Views: 13431
Reputation: 5178
I believe the recommended solution would be a class-only protocol. From the Swift Programming Language protocol page:
You can limit protocol adoption to class types (and not structures or enumerations) by adding the AnyObject protocol to a protocol’s inheritance list.
So in your example, your protocol definition would look like:
protocol RWOverlaySelectionDelegate: AnyObject {
func areaSelected(view: UIView, points: NSArray)
}
With the addition of the AnyObject
keyword, the compiler should no longer complain.
Upvotes: 9
Reputation: 9012
I have since found a better way of doing this in this answer.
Updated for recent Swift versions
As I mentioned in my comment on CjCoax's answer, prefixing the protocol with @objc
prevents passing Swift object types (such as enums and structs) to delegate methods.
However, using : AnyObject
will allow this behaviour while allowing the protocol to be used in a weak variable, though this method is not without its limitations. You can only make classes conform to any protocol that is marked with : AnyObject
. I believe that this is a better trade-off than @objc
provides.
protocol MyProtocol: AnyObject {
...
}
Upvotes: 9
Reputation: 1627
Since swift 4 instead of class we should use AnyObject. From the Swift Programming Language protocol page:
You can limit protocol adoption to class types (and not structures or enumerations) by adding the AnyObject protocol to a protocol’s inheritance list.
protocol SomeClassOnlyProtocol: AnyObject, SomeInheritedProtocol {
// class-only protocol definition goes here
}
Upvotes: 2
Reputation: 9637
Found the solution: I just need to declare my protocol as follow:
@objc protocol RWOverlaySelectionDelegate {
func areaSelected(view:UIView,points:NSArray)
}
and then the class just uses protocol name rather than an AnyObject that conforms to a protocol
class RWMapSelectionLayer:NSObject {
weak var delegate: RWOverlaySelectionDelegate?;
}
Protocol declaration which is @objc protocol RWOverlaySelectionDelegate
require object of RWOverlaySelectionDelegate
to be a class.
Here is the reference from The Swift Programing Language
guide provided by apple
@objc protocols can be adopted only by classes
Upvotes: 0