【问题标题】:Type constraint on AnyObject or Any (AnyObject or Any that conforms to a protocol)AnyObject 或 Any(符合协议的 AnyObject 或 Any)上的类型约束
【发布时间】:2014-06-05 17:09:45
【问题描述】:

我正在尝试将我的 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?

然后我尝试使用以下语法将我的属性转换为符合RWOverlaySelectionDelegateAnyObject

weak var delegate: AnyObject<RWOverlaySelectionDelegate>?

现在我正在干扰泛型和编译器显示:Cannot specialize non-generic type 'AnyObject' 错误。

在另一个不成功的尝试中,我将其更改为

weak var delegate: AnyObject:RWOverlaySelectionDelegate?

将其读作“Delegate 属于 AnyObject 类型,其中 AnyObject 应符合 RWOverlaySelectionDelegate”

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

如果有人可以帮助我enforce conformance to a protocol on AnyObject or Any,将不胜感激

【问题讨论】:

    标签: swift


    【解决方案1】:

    我后来在this answer 中找到了更好的方法。

    更新了最新的 Swift 版本

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

    但是,使用: AnyObject 将允许这种行为,同时允许在弱变量中使用协议,尽管这种方法并非没有局限性。您只能使类符合任何标有: AnyObject 的协议。我相信这是比@objc 提供的更好的权衡。

    protocol MyProtocol: AnyObject {
        ...
    }
    

    【讨论】:

    • 在 2015 年 1 月的 swift 中,这是作为 protocol MyProtocolName: class { ... } 完成的,而不是使用 @class_protocol 声明。
    【解决方案2】:

    我相信推荐的解决方案是类协议。来自Swift Programming Language协议页面:

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

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

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

    加上AnyObject 关键字,编译器应该不再抱怨了。

    【讨论】:

    • 这应该是现在公认的答案(从 Xcode 6.1 GM 开始)
    【解决方案3】:

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

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

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

    【讨论】:

      【解决方案4】:

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

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

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

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

      协议声明 @objc protocol RWOverlaySelectionDelegate 要求 RWOverlaySelectionDelegate 的对象是一个类。 这是苹果提供的The Swift Programing Language指南的参考

      @objc 协议只能被类采用

      【讨论】:

      • 这样做的问题是您不能将 Swift-only 类型传递给委托方法(例如枚举和结构)。
      • @SteveWilford,同意,只需要坚持这一点,直到我找到一种方法来声明一个仅限于实现协议的属性。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-11-17
      • 2014-10-23
      • 2015-01-02
      • 2016-07-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多