Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UiTextField: canPerformAction, caretRectForPosition, selectionRectsForRange are not called (Swift 3)

I have done a lot of research and ran out of ideas to solve this. Can someone please tell me why the canPerformAction, caretRectForPosition, selectionRectsForRange are not called for the MyTextField Object.

I have read that these functions are only called if the class inherits from UITextField and not from UITextFieldDelegate.

I also tried to put override in front of the function definition. But Swift 3 does not like this:

Method does not override any method from its superclass ViewController.swift

This should not be a problem because the override can be removed like stated here: Swift protocols: method does not override any method from its superclass

import Foundation
import UIKit

class ViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate
    //, UITextFieldDelegate
{
    @IBOutlet var my_text_field: MyTextField!
    @IBOutlet var my_text_field_delegate: MyTextFieldDelegate!

    var pickerView = UIPickerView()
    var pickOption = ["test1",
                      "test2",
                      "test3",
                      "test3",
                      "test4",
                      "test5"]

    override func viewDidLoad()
    {
        super.viewDidLoad()

        //let pickerView = UIPickerView()
        pickerView.delegate = self
        pickerView.showsSelectionIndicator = true

        my_text_field.inputView = pickerView
        my_text_field_delegate.inputView = pickerView

        //my_text_field_delegate.delegate = self
    }

    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        return pickOption.count
    }
    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        return pickOption[row]
    }
    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        my_text_field_delegate.text = pickOption[row]
        print("ViewController picker hit \(row)")
    }

    // number of columns to display
    func numberOfComponents(in pickerView: UIPickerView) -> Int {
        return 1
    }
}

/////////////////////////////////////////////////////
class MyTextField: UITextField//, UITextFieldDelegate
{
    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)!

        // this is only needed if class inherits from UITextFieldDelegate
        //delegate = self
    }
    required override init(frame: CGRect) {
        super.init(frame: frame)

        // this is only needed if class inherits from UITextFieldDelegate
        //delegate = self
    }

    // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    // why these functions are not called?
    // they should because the class inherits form UITextField and not from UITextFieldDelegate
    func caretRectForPosition(position: UITextPosition!) -> CGRect {
        print("MyTextField caretRectForPosition")
        return CGRect.zero
    }
    func selectionRectsForRange(range: UITextRange) -> [AnyObject] {
        print("MyTextField selectionRectsForRange")
        return []
    }
    func canPerformAction(action: Selector, withSender sender: AnyObject?) -> Bool {
        print("MyTextField canPerformAction")

        UIMenuController.shared.isMenuVisible = false
        if action == #selector(UIResponderStandardEditActions.paste(_:)) {
            print("no paste")
            return false
        }
        return super.canPerformAction(action, withSender:sender)
    }
    // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

    // these functions are only called if class inherits from UITextFieldDelegate
    func textFieldDidBeginEditing(_ textField: UITextField) {
        print("MyTextField focused")
    }
    func textFieldDidEndEditing(_ textField: UITextField) {
        print("MyTextField lost focus")
    }
    func textFieldShouldBeginEditing(_ state: UITextField) -> Bool {
        print("MyTextField textFieldShouldBeginEditing")
        return true
    }
}

///////////////////////////////////////////////////////////
class MyTextFieldDelegate: UITextField, UITextFieldDelegate
{
    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)!
        delegate = self
        createBorder()
    }
    required override init(frame: CGRect) {
        super.init(frame: frame)
        delegate = self
        createBorder()
    }
    func createBorder(){
        let border = CALayer()
        let width = CGFloat(2.0)
        border.borderColor = UIColor(red: 55/255, green: 78/255, blue: 95/255, alpha: 1.0).cgColor
        border.frame = CGRect(x: 0, y: self.frame.size.height-width, width: self.frame.size.width, height: self.frame.size.height)
        border.borderWidth = width
        self.layer.addSublayer(border)
        self.layer.masksToBounds = true
        //print("border created")
    }
    func textFieldDidBeginEditing(_ textField: UITextField) {
        print("MyTextFieldDelegate focused")
    }
    func textFieldDidEndEditing(_ textField: UITextField) {
        print("MyTextFieldDelegate lost focus")
    }
    func textFieldShouldBeginEditing(_ state: UITextField) -> Bool {
        print("MyTextFieldDelegate textFieldShouldBeginEditing")
        return true
    }


    // these functions are not called
    func caretRectForPosition(position: UITextPosition!) -> CGRect {
        print("MyTextFieldDelegate caretRectForPosition")
        return CGRect.zero
    }
    func selectionRectsForRange(range: UITextRange) -> [AnyObject] {
        print("MyTextFieldDelegate selectionRectsForRange")
        return []
    }
    func canPerformAction(action: Selector, withSender sender: AnyObject?) -> Bool {
        print("MyTextFieldDelegate canPerformAction")

        // Disable copy, select all, paste
        if action == #selector(UIResponderStandardEditActions.copy(_:)) ||
            action == #selector(UIResponderStandardEditActions.selectAll(_:)) ||
            action == #selector(UIResponderStandardEditActions.paste(_:))
        {
            return false
        }

        // Default
        return super.canPerformAction(action, withSender: sender)
    }
}
like image 403
cylov Avatar asked Mar 11 '23 19:03

cylov


1 Answers

The problem is that your methods do not have the proper signature under Swift 3.

Example:

func canPerformAction(action: Selector, withSender sender: AnyObject?) -> Bool {

should be:

func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {

See the reference documentation for the other methods and update your code to use the proper signatures.

func caretRect(for position: UITextPosition) -> CGRect

func selectionRects(for range: UITextRange) -> [Any]
like image 61
rmaddy Avatar answered Apr 26 '23 10:04

rmaddy