在 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_getAssociatedObject
和 objc_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 中导入扩展文件的主要内容,如果未能解决你的问题,请参考以下文章