3

I’m working on an app that uses accessibility. When the user clicks in a UITextField and writes a letter, the textField.shouldChangeCharactersIn method gets called. This happens without problems when voiceOver is switched on or off. But if the users turns on the Braille Screen Input, the method textField.shouldChangeCharactersIn doesn’t get called.

Instead an error gets logged out:

[User Defaults] Couldn't write value for key VoiceOverHandwritingWasNativeAutocorrectEnabled in CFPrefsPlistSource<0x1d4107860> (Domain: com.apple.Accessibility, User: kCFPreferencesCurrentUser, ByHost: No, Container: (null), Contents Need Refresh: Yes): setting preferences outside an application's container requires user-preference-write or file-write-data sandbox access, switching to read-only

Can somebody explain what this means?

It can be reproduced easily with:

import UIKit

    class ViewController: UIViewController, UITextFieldDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()

        let text = UITextField(frame: CGRect(x: 20.0, y: 150.0, width: 200.0, height: 30.0))
        text.delegate = self;
        text.backgroundColor = .gray

        self.view.addSubview(text)
    }

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {

        print("replacementString : \(string)")
        return true

    }
}
Preet
  • 984
  • 2
  • 14
  • 34
M Mayer
  • 31
  • 2

2 Answers2

1

I think it's a bug on apple Api. This solution might not fit your use case but you may try something like this. Here is the alternate temporary solution to keep track of text using custom class inheriting Textfield.

class AccessibilityTextField: UITextField {
    override func accessibilityElementDidLoseFocus() {
        _ = delegate?.textFieldDidEndEditing?(self)
    }
}

Then in your textfield delegate implementation method, validate the text to enable or disable some other button.

extension MyView: UITextFieldDelegate {
    func textFieldDidEndEditing(_ textField: UITextField) {
        //Do you check here
    }
}

Remember this is not live tracking of Text(like char in range) as didLoseFocus is called only once.

navneet
  • 11
  • 3
-1

Make you textField Object global because it gets deallocated right after the execution of the method viewDidLoad

import UIKit

    class ViewController: UIViewController, UITextFieldDelegate {
    var textField: UITextField?
    override func viewDidLoad() {
        super.viewDidLoad()

        textField = UITextField(frame: CGRect(x: 20.0, y: 150.0, width: 200.0, height: 30.0))
        textField?.delegate = self;
        textField?.backgroundColor = .gray

        self.view.addSubview(textField!)
    }

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {

        print("replacementString : \(string)")
        return true

    }
}
Syed Qamar Abbas
  • 3,637
  • 1
  • 28
  • 52
  • Thanks. But this doesn't change the behaviour. textField.shouldChangeCharactersIn still doesn’t get called. – M Mayer Jul 17 '18 at 06:54