在AnyObject或Any上键入约束(任何符合协议的AnyObject或Any)

时间:2014-06-05 17:09:46

标签: swift

我试图将Objective-C代码转换为swift。 在Objective-C中,我有以下协议:

@protocol RWOverlaySelectionDelegate <NSObject>
    -(void)areaSelected:(UIView *)view allPoints:(NSArray *)points;
@end

以下类具有引用协议的弱属性(显然它被定义为弱以防止强引用循环)。

@interface RWMapSelectionLayer : UIView
    @property(weak, nonatomic) id <RWOverlaySelectionDelegate> delegate;
@end

现在是Swift的等价物:

协议:

protocol RWOverlaySelectionDelegate {
    func areaSelected(view:UIView,points:CGPoint[])
}

以及具有符合该协议的属性的类:

class RWMapSelectionLayer:NSObject {
    weak var delegate:RWOverlaySelectionDelegate?
}

但我在此行中收到'weak' cannot be applied to non-class type 'RWOverlaySelectionDelegate'编译时错误:weak var delegate:RWOverlaySelectionDelegate?

然后我尝试使用以下语法将我的属性转换为符合AnyObject的{​​{1}}:

RWOverlaySelectionDelegate

现在我干扰了Generics和编译器显示:weak var delegate: AnyObject<RWOverlaySelectionDelegate>? 错误。

在另一次失败的尝试中,我将其更改为

Cannot specialize non-generic type 'AnyObject'

将其读作&#34; Delegate的类型为AnyObject,其中AnyObject应符合RWOverlaySelectionDelegate&#34;

由于单个语句中有两个冒号(:),这又是不正确的。

如果有人可以帮我weak var delegate: AnyObject:RWOverlaySelectionDelegate?

,我们将不胜感激

4 个答案:

答案 0 :(得分:9)

我已经在this answer找到了更好的方法。

针对最近的Swift版本进行了更新

正如我在对CjCoax答案的评论中提到的,在协议前加上@objc会阻止将Swift对象类型(例如枚举和结构)传递给委托方法。

然而,使用@class_protocol使用: class 为协议添加前缀将允许此行为,同时允许在弱变量中使用协议,尽管此方法并非没有限制。您只能使类符合任何前缀为@class_protocol 且标有: class的协议(因此名称)。我相信这是一个比@objc提供的更好的权衡。

protocol MyProtocol : class {
    ...
}

答案 1 :(得分:9)

我认为推荐的解决方案是仅限课程的协议(仅适用于最新的Xcode 6测试版,我目前正在使用GM版本)。从Swift Programming Language协议页面:

  

通过将class关键字添加到协议的继承列表,可以将协议采用限制为类类型(而不是结构或枚举)。在任何继承的协议之前,class关键字必须始终首先出现在协议的继承列表中:

因此,在您的示例中,您的协议定义如下所示:

protocol RWOverlaySelectionDelegate: class {
    func areaSelected(view:UIView,points:NSArray)
}

通过添加class关键字,编译器不应再抱怨了。

答案 2 :(得分:1)

由于swift 4而不是class,我们应该使用AnyObject。来自Swift编程语言protocol page

  

您可以将协议采用限制为类类型(而不是结构或类型)   枚举)通过将AnyObject协议添加到协议的   继承清单。

protocol SomeClassOnlyProtocol: AnyObject, SomeInheritedProtocol {
    // class-only protocol definition goes here
}

答案 3 :(得分:0)

找到解决方案: 我只需要声明我的协议如下:

@objc protocol RWOverlaySelectionDelegate {
    func areaSelected(view:UIView,points:NSArray)
}

然后该类只使用协议名称而不是符合协议的AnyObject

class RWMapSelectionLayer:NSObject {
    weak var delegate: RWOverlaySelectionDelegate?;
}

@objc protocol RWOverlaySelectionDelegate的协议声明要求RWOverlaySelectionDelegate的对象成为一个类。 以下是Apple提供的The Swift Programing Language指南的参考资料

  

@objc协议只能由类

采用