Amir
Amir

Reputation: 9637

Type constraint on AnyObject or Any (AnyObject or Any that conforms to a protocol)

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

Answers (4)

chris838
chris838

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

Steve Wilford
Steve Wilford

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

Istvan
Istvan

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

Amir
Amir

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

Related Questions