ios - 如何从 UIView 访问 UI 元素

标签 ios swift

我刚刚开始从 Interface Builder 转向 100% 代码。

作为概念验证,我已经成功创建了一个自动布局单屏应用程序。问题是,我觉得好像有一种更有效的方法可以做到这一点。

从 UIView 类获取对象然后在 UIViewController 中访问的正确方法是什么?

这是我整个项目的代码

AppDelegate.swift

import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?


    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        window = UIWindow(frame: UIScreen.main.bounds)
        window?.rootViewController = ViewController()
        window?.makeKeyAndVisible()
        return true
    }
}

ViewControllerView.swift

import UIKit

public enum ViewControllerTextFields: String {
    case username = "usernameField"
    case password = "passwordField"
}

public enum ViewControllerButtons: String {
    case login = "loginButton"
}

class ViewControllerView: UIView {

    private var views = [String: UIView]()

    override init(frame: CGRect) {
        super.init(frame: frame)
        backgroundColor = .lightGray
        createScreenComponents()
        createConstraints()
    }

    func makeTextField(withPlaceholder text: String, textColor color: UIColor) -> UITextField {
        let textField = UITextField()
        textField.attributedPlaceholder =  NSAttributedString(string: text, attributes: [.foregroundColor : color.withAlphaComponent(0.5)])
        textField.textColor = color
        textField.translatesAutoresizingMaskIntoConstraints = false
        return textField
    }

    func makeButton(withTitle title: String) -> UIButton {
        let button = UIButton()
        button.translatesAutoresizingMaskIntoConstraints = false
        button.setTitle(title, for: .normal)
        return button
    }

    func createScreenComponents() {
        let usernameField = makeTextField(withPlaceholder: "Username", textColor: .white)
        let passwordField = makeTextField(withPlaceholder: "Password", textColor: .white)

        let loginButton = makeButton(withTitle: "Login")

        views["usernameField"] = usernameField
        views["passwordField"] = passwordField
        views["loginButton"] = loginButton
    }

    func createConstraints() {
        for (key, val) in views {
            addSubview(val)
            addConstraints(NSLayoutConstraint.constraints(
                withVisualFormat: "H:|[\(key)]|",
                options: [],
                metrics: nil,
                views: views)
            )
        }

        addConstraints(NSLayoutConstraint.constraints(
            withVisualFormat: "V:|[usernameField]",
            options: [],
            metrics: nil,
            views: views)
        )

        addConstraints(NSLayoutConstraint.constraints(
            withVisualFormat: "V:[usernameField][passwordField(==usernameField)]",
            options: [],
            metrics: nil,
            views: views)
        )

        addConstraints(NSLayoutConstraint.constraints(
            withVisualFormat: "V:[passwordField][loginButton(==passwordField)]|",
            options: [],
            metrics: nil,
            views: views)
        )

    }

    public func getTextFieldWithId(_ identifier: ViewControllerTextFields) -> UITextField {
        return views["\(identifier.rawValue)"] as! UITextField
    }

    public func getButtonWithID(_ identifier: ViewControllerButtons) -> UIButton {
        return views["\(identifier.rawValue)"] as! UIButton
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

ViewController.swift

import UIKit

class ViewController: UIViewController {

    var username: UITextField!
    var password: UITextField!

    override func loadView() {
        let viewObject = ViewControllerView()
        view = viewObject

        username = viewObject.getTextFieldWithId(.username)
        password = viewObject.getTextFieldWithId(.password)

        viewObject.getButtonWithID(.login).addTarget(self, action: #selector(test), for: .touchUpInside)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    @objc func test() {
        print("Hello")
    }
}

有没有一种方法可以访问 ViewControllerView 对象,例如 UITextFields 和 UIButtons,而不必使用 viewObject 变量并使用函数返回 View ?

最佳答案

我的建议是在 ViewController View 中保存文本字段和按钮的私有(private)变量,但提供可以在 Controller 中访问的只读变量,

在 ViewControllerView.swift 中:

private var _username: UITextField!
private var _password: UITextField!
private var _login: UIButton!

var username: UITextField! { get { return _username } }
var password: UITextField! { get { return _password } }
var login: UIButton! { get { return _login } }

然后在 ViewController.swift 中,您可以替换以下行:

username = viewObject.getTextFieldWithId(.username)
password = viewObject.getTextFieldWithId(.password)

viewObject.getButtonWithID(.login).addTarget(self, action: #selector(test), for: .touchUpInside)

与:

username = viewObject.username
password = viewObject.password

viewObject.login.addTarget(self, action: #selector(test), for: .touchUpInside)

如果您愿意,您甚至可以将这些变量作为实例变量存储在 ViewController 类中。

关于ios - 如何从 UIView 访问 UI 元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45057671/

相关文章:

ios - obj-c 类中未知的 swift 属性

ios - 如何在 IOS 7 的 xcode 中加载新图标?

ios - 将重新排序符号放在 UITableViewCell 的左侧

ios - 让 Xcode SVN 在更新之前显示更新

ios - 如何使用扩展更新类中的数组?

ios - 如何以编程方式为 iPhone SE 和 iPhone 5S 编写自动布局?

ios - iOS 中的 URL 解码

ios - 如何在底部插入带有动画的 UITableViewCell?

swift - 如何快速编译着色器,位置总是返回-1

ios - 如何在选择 tableView 的行单元格(作为 Collection View 单元格)时显示 View Controller ?