具有存储属性的扩展

Posted

技术标签:

【中文标题】具有存储属性的扩展【英文标题】:Extensions with stored properties 【发布时间】:2017-05-22 13:08:32 【问题描述】:

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

我的想法是创建 2 个 UITextView,一个以文本作为占位符,当用户开始编辑文本时,它实际上是隐藏的,用户正在修改另一个 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 扩展中的问题。

注意:不要使用上面的代码来解决占位符问题,因为它不能完美运行。

【问题讨论】:

查看***.com/questions/25426780/… Lazy loading property in Extension (Swift)的可能重复 【参考方案1】:

你可以这样做:

extension UITextView 

    private struct AssociatedKeys 
        static 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)
        
    

【讨论】:

【参考方案2】:

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

【讨论】:

以上是关于具有存储属性的扩展的主要内容,如果未能解决你的问题,请参考以下文章

在 Swift 中继承具有自己类型和存储属性的数组

如何使用 multer 存储具有文件扩展名的文件?

扩展可能不包含存储的属性

如何从 Firebase 存储下载具有原始扩展名的文件?

收到错误:“扩展可能不包含存储的属性”

如何将具有特定扩展名的文件添加到化石存储库中?