在 Swift 中导入扩展文件

Posted

技术标签:

【中文标题】在 Swift 中导入扩展文件【英文标题】:Import Extension file in Swift 【发布时间】:2014-06-03 17:22:12 【问题描述】:

我在 Swift 中为 UIView 创建了一个扩展。任何人都知道如何将该文件导入我的 UIViewController?

我想在控制器文件中导入扩展文件,这样我可以重复使用扩展文件。例如这样的结构:

UIViewExtension.swift

import UIKit

extension UIView 
    var myVar : Float 
        get 
            return myVar
        
        set (newMyVar) 
            myVar = newMyVar
        
    

ViewController.swift

import UIKit

class ViewController: UIViewController 

    override func viewDidLoad() 
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        var squareView: UIView = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 200))

        squareView.myVar = 50

        self.view.addSubview(squareView)
        println("Offset: \(squareView.myVar)")
    

这是编译器给出的错误:

Command /Applications/Xcode6-Beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift failed with exit code 254

【问题讨论】:

这看起来像是编译器中的一个错误。它对我也不起作用,除非我将扩展引入到类定义上方的“ViewController.swift”中。 没错,我在发帖前已经检查了与ViewController.swift 相同的文件中的扩展名,所以它工作正常。 import 的自动建议也不起作用,即使对于 UIKit 您可以尝试将类声明添加到带有扩展名的文件中吗?例如。 class TestClass 。也许它会帮助编译器找到扩展... 【参考方案1】:

这里发生了几件事。

    不需要像 Objective-C 那样导入扩展,因为同一模块中的所有内容都可以在 Swift 中自动使用。这意味着您的扩展实际上对视图控制器中的编译器是成功可见的。

    您只能将计算属性添加到扩展。这意味着您实际上没有要分配或读取的 myVar。因此,当您访问 myVar 时,您实际上是在无限递归。这实际上是警告所暗示的内容(尽管方式含糊):

    warning: attempting to access 'myVar' within its own getter
      return myVar
             ^
    

    据我所知,无法使用扩展将非计算属性添加到类型中。 Objective-C 也是如此,其中使用类扩展实际存储添加到类的属性的唯一方法是通过 objc_getAssociatedObjectobjc_setAssociatedObject 中的 objc/runtime.h 使用 Objective-C 对象关联。

    最后,如果你的扩展的计算属性有一个 setter,那么编译器肯定会有一个错误。重现该错误的最小工作示例是:

    import UIKit
    
    extension UIView 
      var myVar : Float 
      get 
        return 0
      
      set 
      
      
    
    

【讨论】:

我的问题是关于 3 点和 4 点。如何在没有 getter 的情况下将新属性作为 objC 添加到扩展中?但即使从 ViewController 调用扩展程序时仍然会出现错误 我所知道的实现您想要做的事情的唯一方法是使用 Objective-C,参见。 nshipster.com/associated-objects Re 4. 您绝对应该通过bugreport.apple.com 向Apple 报告该错误 我已经用 objC 完成了,这就是我尝试使用 Swift 的原因;) 不管它是否有一个setter,或者它是否是一个正确的computed-only-var。我得到同样的错误1.While emitting IR SIL function @_TFC16<appname>13EPAppDelegate11applicationfS0_FTCSo13UIApplication29didFinishLaunchingWithOptionsGSqCSo12NSDictionary__Sb for 'application' at filename.swift:21:5 <unknown>:0: error: unable to execute command: Segmentation fault: 11 <unknown>:0: error: swift frontend command failed due to signal (use -v to see invocation) Command /Applications/Xcode6-Beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift failed with exit code 254【参考方案2】:

我也遇到过这个问题。看来这是一个编译器错误。如果您在独立的扩展文件中计算了属性,编译器似乎会崩溃。我发现的解决方法是在非独立文件中创建扩展名。所以在这种情况下,你可以将你的扩展移动到你的 ViewController.swift 文件中。像这样:

import UIKit

extension UIView 
    var myVar : Float 
        get 
            return myVar
        
        set (newMyVar) 
            myVar = newMyVar
        
    


class ViewController: UIViewController 

    override func viewDidLoad() 
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        var squareView: UIView = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 200))

        squareView.myVar = 50

        self.view.addSubview(squareView)
        println("Offset: \(squareView.myVar)")
    

【讨论】:

不错的发现!您是否向 Apple (bugreport.apple.com) 报告了该错误,还是已知问题? 请将此报告给 Apple! 在属性声明前使用 static 似乎可以解决问题。我添加了一个代码示例作为答案!【参考方案3】:

在左侧 Project navigator 中选择 Xcode 中的文件后,请确保在右侧 Inspector 视图的 Target Membership 部分检查应用程序和测试。

如果不勾选则不会包含在项目中,因此会出现编译错误。

【讨论】:

为我工作,允许我在单元测试中使用源代码编写的扩展。【参考方案4】:

在属性声明前使用 static 似乎可以解决问题。

extension UIView 
    static var myVar : Float 
        get 
            return myVar
        
        set (newMyVar) 
            myVar = newMyVar
        
    

希望对你有帮助!

【讨论】:

这将创建一个由所有实例共享的类变量,而不是实例变量。如果您知道自己永远不会有多个实例,但您没有在回答中指出这一主要缺陷,那么这可能会很有效。

以上是关于在 Swift 中导入扩展文件的主要内容,如果未能解决你的问题,请参考以下文章

如何在 play 框架模型中导入 java 扩展?

如何构建 Python C 扩展,以便我可以从模块中导入它

在 Objective C 文件中导入 ViewController.swift

如何在swift中导入Objective c文件

如何在swift中导入Objective c文件

在桥接头中导入头文件导致的 Swift 编译器错误