NSDictionaryOfVariableBindings, быстро эквивалентный?

Документация Apple показывает тревожный пробел под разделом 'Creating a Dictionary' ссылки UIKit здесь.

Имеет любого, нашел замену для NSDictionaryOfVariableBindings макрос, или мы, как ожидают, просто запишем наше собственное?

РЕДАКТИРОВАНИЕ - Согласно этому, возможно, правильный подход должно записать глобальную функцию для обработки этого? Похож на сложные макросы, отсутствуют полностью.

62
задан 6 June 2014 в 20:09

4 ответа

Таким образом, я взломал что-то вместе, которое, кажется, работает:

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)

1
ответ дан 31 October 2019 в 14:18

На основе 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 для записи его во-первых.

0
ответ дан 31 October 2019 в 14:18

Время выполнения 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))

    }

}

, к сожалению, все еще необходимо ввести имя переменной в как строка, но оно будет, по крайней мере, утверждать, существует ли опечатка. это определенно не будет работать во всех ситуациях, но полезный, тем не менее

1
ответ дан 31 October 2019 в 14:18

После того как Вы сохранили все свои представления как свойства, Вы могли также использовать отражение как так:

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
    }
}
0
ответ дан 31 October 2019 в 14:18

Другие вопросы по тегам:

Похожие вопросы: