Документация Apple показывает тревожный пробел под разделом 'Creating a Dictionary' ссылки UIKit здесь.
Имеет любого, нашел замену для NSDictionaryOfVariableBindings
макрос, или мы, как ожидают, просто запишем наше собственное?
РЕДАКТИРОВАНИЕ - Согласно этому, возможно, правильный подход должно записать глобальную функцию для обработки этого? Похож на сложные макросы, отсутствуют полностью.
Таким образом, я взломал что-то вместе, которое, кажется, работает:
func dictionaryOfVariableBindings(container: Any, views:UIView...) -> Dictionary<String, UIView> {
var d = Dictionary<String, UIView>()
let mirror = Mirror(reflecting: container)
let _ = mirror.children.compactMap {
guard let name = [110].label, let view = [110].value as? UIView else { return }
guard views.contains(view) else { return }
d[name] = view
}
return d
}
Использование:
let views = dictionaryOfVariableBindings(container: self, views: imageView)
На основе https://stackoverflow.com/a/55086673/1058199 cherpak-evgeny, это расширение UIViewController предполагает, что контейнер self
, текущий viewController экземпляр.
extension UIViewController {
// Alex Zavatone 06/04/2019
// Using reflection, get the string name of the UIView properties passed in
// to create a dictionary of ["viewPropertyName": viewPropertyObject…] like
// Objective-C's NSDictionaryForVariableBindings.
func dictionaryOfBindings(_ arrayOfViews:[UIView?]) -> Dictionary<String, UIView> {
var bindings = Dictionary<String, UIView>()
let viewMirror = Mirror(reflecting: self)
let _ = viewMirror.children.compactMap {
guard let name = [110].label, let view = [110].value as? UIView else { return }
guard arrayOfViews.contains(view) else { return }
bindings[name] = view
}
return bindings
}
}
Использование это как так из Вашего viewController:
let viewArray = [mySwitch, myField, mySpinner, aStepper, someView]
let constraintsDictionary = dictionaryOfBindings(viewArray)
Протестированный в XCode 10.2.1 и Swift 4.2.
Большое спасибо Cherpak Evgeny для записи его во-первых.
Время выполнения ObjC к спасению!
я создал альтернативное решение, но оно только работает, если каждое из представлений является переменными экземпляра того же объекта.
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))
}
}
, к сожалению, все еще необходимо ввести имя переменной в как строка, но оно будет, по крайней мере, утверждать, существует ли опечатка. это определенно не будет работать во всех ситуациях, но полезный, тем не менее
После того как Вы сохранили все свои представления как свойства, Вы могли также использовать отражение как так:
extension ViewController {
func views() -> Dictionary<String, AnyObject> {
var views = dictionaryOfProperties()
views.forEach {
if !($1 is UIView) {
views[[110]] = 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
}
}