在Swift中导入扩展文件

14

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

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

UIViewExtension.swift

import UIKit

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

视图控制器.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)")
    }
}

这是编译器给出的错误信息:

/Applications/Xcode6-Beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift命令退出代码为254


1
这看起来像编译器中的一个错误。除非我将扩展程序带入“ViewController.swift”文件,在类定义之上,否则它对我也不起作用。 - Nate Cook
没错,我在发布之前已经检查了与 ViewController.swift 相同文件中的扩展名,所以它可以正常工作。另外,即使是对于 UIKit,import 的自动建议也不起作用。 - javienegas
你能否尝试在带有该扩展名的文件中添加一个类声明呢?例如:class TestClass {}。也许这会帮助编译器找到该扩展名... - Sulthan
4个回答

8
这里有几件事情需要处理。
  1. There is no need to import extensions as you have to for Objective-C, as everything in the same module is automatically available to you in Swift. This means that your extension is actually successfully visible to the compiler in your view controller.
  2. You can only add computed properties to an extension. This means that you do not actually have a myVar to assign to or read from. So when you access myVar you are actually recursing infinitely. That is actually what the warning is alluding to (albeit in vague way):

    warning: attempting to access 'myVar' within its own getter
      return myVar
             ^
    
  3. As far as I know, there is no way to add non-computed properties to a type using an extension. This is also true of Objective-C where the only way to actually store a property added to a class using a class extension is to use Objective-C object association via objc_getAssociatedObject and objc_setAssociatedObject from objc/runtime.h.

  4. Finally there is definitely a bug in the compiler if your extension's computed property has a setter. The minimum working example to reproduce the bug, which does not include recursion (by eliminating the access to myVar) and just ignore the value is:

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

我的问题是关于第三点和第四点。如何在没有getter的情况下将新属性添加为objC扩展?但即使如此,当从ViewController调用扩展时仍然会出现错误。 - javienegas
  1. 你应该向苹果报告这个漏洞,网址是https://bugreport.apple.com/。
- Nicholas H.
我已经用 objC 做过了,所以现在想尝试用 Swift 做 ;) - javienegas
无论它是否有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 - Roland
在属性声明前使用 static 似乎可以解决问题。 - Roger Fernandez Guri
显示剩余2条评论

2

我也遇到了这个问题。看起来这是一个编译器的bug。如果你在一个独立的扩展文件中有计算属性,编译器似乎会崩溃。我找到的解决方法是在非独立文件中创建扩展。所以在这种情况下,你可以将你的扩展移动到你的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)")
    }
}

发现得不错!你是否向苹果报告了这个 bug(https://bugreport.apple.com),还是已知问题? - John Difool
请向苹果公司报告此问题! - aleclarson
在属性声明前面使用 static 似乎可以解决问题。我已经添加了一个代码示例作为答案! - Roger Fernandez Guri

0
在 Xcode 的项目导航器中选择文件后,确保在右侧的检查器视图中的目标成员资格部分中检查应用程序和测试。如果没有选中,则不会包含在项目中,因此会出现编译错误。

enter image description here


对我很有用,允许我在单元测试中使用源代码编写的扩展。 - TinyTimZamboni

-1
在属性声明前面使用static似乎能解决问题。
extension UIView {
    static var myVar : Float {
        get {
            return myVar
        }
        set (newMyVar) {
            myVar = newMyVar
        }
    }
}

希望能对你有所帮助!

5
这将创建一个类变量,它将被所有实例共享,而不是实例变量。如果你知道你永远不会有多个实例,这也许可以工作,但你没有在回答中指出这个主要的漏洞。 - Nicholas H.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接