存储属性的扩展程序

时间:2017-05-22 13:08:32

标签: ios swift swift3 class-extensions

我还在学习Swift,我正在尝试创建一个扩展来为UITextView添加占位符。

我的想法是创建2个UITextViews,一个用文本作为占位符,当用户开始编辑文本时,它实际上是隐藏的,用户正在修改另一个UITextView。

但是,我的问题不是在UITextView中有占位符,而是关于如何使用扩展来解决这个问题。
我的问题是,我在实施中需要更改哪些内容,以创建一个从调用者方面看作的扩展名:
myTextView.placeholder("a placeholder text..")

到目前为止,我已经在我的UIViewController中创建了它,并且需要将它移动到扩展名,但是我有很多存储属性,所以它不会工作。

这是我的代码:

import UIKit

class ViewController: UIViewController, UITextViewDelegate {


    let myTextView: UITextView = {
        let textView = UITextView()
        textView.tag = 0
        textView.backgroundColor = UIColor.yellow
        textView.layer.cornerRadius = 8
        textView.translatesAutoresizingMaskIntoConstraints = false
        return textView
    }()

    let textViewPlaceHolder: UITextView = {
        let textViewPlaceHolder = UITextView()
        textViewPlaceHolder.tag = 1
        textViewPlaceHolder.text = "Placeholder text.."
        textViewPlaceHolder.textColor = UIColor.lightGray
        textViewPlaceHolder.backgroundColor = UIColor.clear
        textViewPlaceHolder.translatesAutoresizingMaskIntoConstraints = false
        return textViewPlaceHolder
    }()


    func textViewDidChange(_ textView: UITextView) {
        myTextView.becomeFirstResponder()
        if textView.tag == 1 && (myTextView.text != nil || myTextView.text != "") {
            textView.isHidden = true
            textViewPlaceHolder.resignFirstResponder()
        } else if textView.tag == 0 {
            if myTextView.text == nil || myTextView.text == "" {
                textViewPlaceHolder.becomeFirstResponder()
                myTextView.resignFirstResponder()
                textViewPlaceHolder.isHidden = false
                textViewPlaceHolder.text = "Placeholder text.."

            }
        }
    }

    func textViewDidBeginEditing(_ textView: UITextView) {
        DispatchQueue.main.async {
            self.textViewPlaceHolder.selectedRange = NSMakeRange(0, 0)
        }
    }


    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = UIColor.lightGray
        view.addSubview(myTextView)
        textViewConstraints()
        view.addSubview(textViewPlaceHolder)
        myTextViewPHConstraints()

        myTextView.delegate = self
        textViewPlaceHolder.delegate = self

    }

    func textViewConstraints() {
        myTextView.widthAnchor.constraint(equalTo: self.view.widthAnchor, constant: -16).isActive = true
        myTextView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
        myTextView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
        myTextView.heightAnchor.constraint(equalToConstant: 200).isActive = true
    }

    func myTextViewPHConstraints() {
        textViewPlaceHolder.widthAnchor.constraint(equalTo: self.view.widthAnchor, constant: -16).isActive = true
        textViewPlaceHolder.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
        textViewPlaceHolder.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
        textViewPlaceHolder.heightAnchor.constraint(equalToConstant: 200).isActive = true
    }

}

正如我上面提到的,我仍然在学习Swift,这个问题不是为了解决一个非常具体的问题,更重要的是,它要学习如何解决问题。 Swift扩展。

注意:不要使用上面的代码解决占位符问题,因为它没有完美的工作。

2 个答案:

答案 0 :(得分:3)

您可以这样做:

extension UITextView {

    private struct AssociatedKeys {
        struct var placeholder = "placeholder"
    }

    var placeholder: String! {
        get {
            guard let placeholder = objc_getAssociatedObject(self, &AssociatedKeys.placeholder) as? String else {
                return String()
            }

            return placeholder
        }

        set(value) {
            objc_setAssociatedObject(self, &AssociatedKeys.placeholder, value, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
}

答案 1 :(得分:0)

不可能直接在扩展名中访问存储的属性。 除了创建全局类,在视图控制器和扩展中调用全局类。在那里,您可以在扩展程序中看到所有存储的变量。