NSDictionaryOfVariableBindings快速等效?

Apple文档显示了UIKit参考的“创build词典”部分下的一个令人不安的空白。

有没有人findNSDictionaryOfVariableBindingsmacros的替代品,还是我们期望只写自己的?

编辑 – 根据这个或许正确的方法是写一个全局函数来处理这个? 看起来复杂的macros完全没有了。

根据苹果源代码:

NSDictionaryOfVariableBindings(v1,v2,v3)相当于[NSDictionary dictionaryWithObjectsAndKeys:v1,@“v1”,v2,@“v2”,v3,@“v3”,nil];

所以在Swift中,你可以使用以下方法:

 let bindings = ["v1": v1, "v2": v2, "v3": v3] 

正如你所说, NSDictionaryOfVariableBindings是一个macros。 Swift中没有macros。 那么多。

尽pipe如此,您可以轻松编写一个Swift函数,将string名称分配给字典中的视图,然后将该字典传递给constraintsWithVisualFormat 。 不同的是,与Objective-C不同的是,Swift看不到你的名字, 你将不得不让它组成一些新的名字。

[要清楚的是,你的Objective-C 代码不能看到你的variables名; 这就是说,在macros观评估的时候,预处理器是以源代码的forms对文本进行操作并对其进行重写 – 所以它可以只用引号内的variables名(string)和外部的variables名形成一本字典。 但是对于Swift,没有预处理器。]

所以,这就是我所做的:

 func dictionaryOfNames(arr:UIView...) -> Dictionary<String,UIView> { var d = Dictionary<String,UIView>() for (ix,v) in arr.enumerate(){ d["v\(ix+1)"] = v } return d } 

你可以这么称呼它并使用它:

  let d = dictionaryOfNames(myView, myOtherView, myFantasicView) myView.addConstraints( NSLayoutConstraint.constraintsWithVisualFormat( "H:|[v2]|", options: nil, metrics: nil, views: d) ) 

问题在于, 应该认识到在你的可视化格式string中myOtherView的名字是v2 (因为它是传递给dictionaryOfNames()的列表中的第二个)。 但是我可以忍受,只是为了避免每一次手工input字典的麻烦。

当然,你也可以在Objective-C中写或多或less的这个相同的函数。 只是你没有打扰,因为macros已经存在了!

该function基于目前在Swift中不支持的macros扩展。

我认为目前还没有办法在Swift中做类似的事情。 我相信你不能写你自己的替代品。

恐怕你必须手动展开字典定义,即使这意味着重复每个名字两次。

ObjC运行时去救援!

我创build了一个备用解决scheme,但只有在每个视图都是同一个对象的实例variables的情况下才有效。

 func DictionaryOfInstanceVariables(container:AnyObject, objects: String ...) -> [String:AnyObject] { var views = [String:AnyObject]() for objectName in objects { guard let object = object_getIvar(container, class_getInstanceVariable(container.dynamicType, objectName)) else { assertionFailure("\(objectName) is not an ivar of: \(container)"); continue } views[objectName] = object } return views } 

可以这样使用:

 class ViewController: UIViewController { var childA: UIView = { let view = UIView() view.translatesAutoresizingMaskIntoConstraints = false view.backgroundColor = UIColor.redColor() return view }() var childB: UIButton = { let view = UIButton() view.setTitle("asdf", forState: .Normal) view.translatesAutoresizingMaskIntoConstraints = false view.backgroundColor = UIColor.blueColor() return view }() override func viewDidLoad() { super.viewDidLoad() self.view.addSubview(childA) self.view.addSubview(childB) let views = DictionaryOfInstanceVariables(self, objects: "childA", "childB") self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[childA]|", options: [], metrics: nil, views: views)) self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[childB]|", options: [], metrics: nil, views: views)) self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[childA][childB(==childA)]|", options: [], metrics: nil, views: views)) } } 

不幸的是,你仍然必须以string的formsinputvariables名,但是至less会出现错误。 这绝对不会在所有情况下都起作用,但是有帮助

将所有视图存储为属性后,也可以使用如下所示的reflection:

 extension ViewController { func views() -> Dictionary<String, AnyObject> { var views = dictionaryOfProperties() views.forEach { if !($1 is UIView) { views[$0] = nil } } return views } } extension NSObject { func dictionaryOfProperties() -> Dictionary<String, AnyObject> { var result = Dictionary<String, AnyObject>() let mirror = Mirror(reflecting: self) for case let(label?, value) in mirror.children { result[label] = value as? AnyObject } return result } }