emerog
emerog

Reputation: 79

UITextField without get property swift 4

I have custom control which contains textField. Sample code looks like this:

@IBDesignable
class MyTextField: UIView {
  private var _text: String?
  private var textField: UITextField?

@IBInspectable var text: String? {
    get {
        return _text
    } set (newValue) {
        guard let txt = newValue else { return }
        self._text = txt
        //updateView()
    }
}

override func awakeFromNib() {
    super.awakeFromNib()
    updateView()
}

override func prepareForInterfaceBuilder() {
    super.prepareForInterfaceBuilder()
    updateView()
}

func updateView() {
    textField = UITextField(frame: CGRect(x: 0, y: 0, width: 97, height: 30))
    self.addSubview(textField!)
    textField!.text = self._text
}}

When I create an outlet to my custom control in code I can set text property, but I can't get it. What am I doing wrong ? I'm new in this so I don't understand...

EDIT:

  1. Add MyTextField to Main.storyboard and standard textField
  2. Create an outlets ​@IBOutlet var myTextField: MyTextField! and

    standardTextField

  3. Set Text property of my control in Object Inspector enter image description here

  4. My control on storyboard updates correctly and "test text" is visible
  5. Add a button and create an action outlet

    case 1: works fine

    @IBAction func click(_ sender: UIButton) { myTextField.text = standardTextField.text }

    case 2: doesn't work

    @IBAction func click(_ sender: UIButton) { standardTextField.text = myTextField.text }

    After case 2, in standardTextField is only value which i set from object inspector. If i change value of myTextField.text, standardTextField still shows a orginal value from object inspector

Upvotes: 0

Views: 1112

Answers (2)

emerog
emerog

Reputation: 79

A simple solution for not working getter is change text property from:

@IBInspectable var text: String? {
    get {
        return _text
    } set (newValue) {
        guard let txt = newValue else { return }
        self._text = txt
        updateView()
    }
}

to

@IBInspectable var text: String? {
    get {
        return textField!.text
    } set (newValue) {
        guard let txt = newValue else { return }
        self._text = txt
        updateView()
    }
}

But I don't know if this is correct... Does it make any sense ?

Upvotes: 0

invisible squirrel
invisible squirrel

Reputation: 3008

I replicated your setup in Xcode. Case 2 does work — the standardTextField displays MyTextField's text when the button is clicked.

Note: in MyTextField I assumed that you want to create textField once, instead of recreating it each time the text updates. Case 2 was working without this change, though.

import UIKit

class ViewController: UIViewController {
    @IBOutlet var myTextField: MyTextField!
    @IBOutlet var standardTextField: UITextField!
    @IBOutlet weak var button: UIButton!

    override func viewDidLoad() {
        super.viewDidLoad()
        button.addTarget(self, action: #selector(click(_:)), for: .touchUpInside)
    }

    @IBAction func click(_ sender: UIButton) {
        // myTextField.text = standardTextField.text // Case 1 works
        standardTextField.text = myTextField.text // Case 2 works
    }
}

MyTextField control:

import UIKit

@IBDesignable
class MyTextField: UIView {
    private var _text: String?
    private var textField = UITextField(frame: CGRect(x: 0, y: 0, width: 97, height: 30))

    @IBInspectable var text: String? {
        get {
            return _text
        } set (newValue) {
            guard let txt = newValue else { return }
            self._text = txt
            updateView()
        }
    }

    override func awakeFromNib() {
        super.awakeFromNib()
        self.addSubview(textField)
        updateView()
    }

    override func prepareForInterfaceBuilder() {
        super.prepareForInterfaceBuilder()
        self.addSubview(textField)
        updateView()
    }

    func updateView() {
        textField.text = self._text
    }
}

Upvotes: 0

Related Questions