扩展 NSLayoutAnchor 中的编译错误

Posted

技术标签:

【中文标题】扩展 NSLayoutAnchor 中的编译错误【英文标题】:Compile error in extension NSLayoutAnchor 【发布时间】:2017-02-24 16:51:56 【问题描述】:

我正在尝试在 NSLayoutAnchor 上创建一个扩展方法来接受乘数。我得到一个奇怪的 Swift 编译错误(Swift 3,XCode 8.2.1),不是在扩展文件中,而是在模块的相应 .h 文件(该文件由编译器自动生成)中:

@interface NSLayoutAnchor (SWIFT_EXTENSION(MYMODULENAME))
- (NSLayoutConstraint * _Nonnull)constraintTo:(NSLayoutAnchor</* AnchorType */> * _Nonnull)anchor multiplier:(CGFloat)m;
@end

错误指向/* AnchorType */ 并说:“预期类型”。嗯,这是有道理的,因为 /* AnchorType */ 不是类型而是注释。但是我在方法签名中使用了AnchorType 类型参数。

扩展源码如下:

extension NSLayoutAnchor 
  open func constraint(to anchor: NSLayoutAnchor<AnchorType>, multiplier m: CGFloat) -> NSLayoutConstraint 
  // ...
  

【问题讨论】:

此扩展位于我的主项目的单独模块中。当我在我的主项目中移动扩展代码时,一切正常。这一定是构建模块接口时的某种混淆。 【参考方案1】:

注意:自 Swift 4 起已修复,请参阅下面 benrudhart 的回答。

这是目前 swift 和 objc 的问题。不允许在 swift 中扩展 objc 泛型然后桥接回 objc。即使添加 @nonobjc 也不能解决问题。查看此处提交的错误:https://bugs.swift.org/browse/SR-2708 了解更多信息。

一个潜在的解决方法是对NSLayoutAnchor 的每个具体类型进行扩展。具体类型为NSLayoutXAxisAnchorNSLayoutYAxisAnchorNSLayoutDimension

extension NSLayoutDimension 
    open func constraint(to anchor: NSLayoutDimension, 
             multiplier m: CGFloat) -> NSLayoutConstraint


extension NSLayoutXAxisAnchor 
    open func constraint(to anchor: NSLayoutXAxisAnchor, 
             multiplier m: CGFloat) -> NSLayoutConstraint


extension NSLayoutYAxisAnchor 
    open func constraint(to anchor: NSLayoutYAxisAnchor, 
             multiplier m: CGFloat) -> NSLayoutConstraint

【讨论】:

【参考方案2】:

从 Swift 4 开始,现在可以通过使用 @objc 注释扩展来实现。以下代码将编译:

@objc extension NSLayoutAnchor 
    func constraint(to anchor: NSLayoutAnchor<AnchorType>, multiplier: CGFloat) -> NSLayoutConstraint 
        // ...
    

【讨论】:

以上是关于扩展 NSLayoutAnchor 中的编译错误的主要内容,如果未能解决你的问题,请参考以下文章

NSLayoutAnchor 的类型

使用 NSLayoutAnchor 不好吗?

Java源文件和编译后的文件扩展名分别为

使用 NSLayoutAnchor 在两个标签之间创建约束?

使用 NSLayoutAnchor.constraintEqualToSystemSpacingAfter 时的控制台警告

使用 NSLayoutAnchor 时清除约束