Есть ли способ захватить родительский объект из подвида?

#swift

#swift

Вопрос:

Я работаю над приложением-кроссвордом для swift, и у меня возникли проблемы с получением a UIButton из a subview в UIButton том, что является a textfield .

Текстовое поле занимает место, где UIButton должен быть заголовок, но при нажатии на textfield него не нажимается UIButton . UIButton Сам по себе на данный момент выделяет все UIButtons некоторые столбцы и строки.

Я пробовал несколько вещей, таких как гравировка суперкласса вложенного представления

 var myButton: CustomButton = textfield.superclass as? CustomButton

  

и я также пытался использовать

 var myObject : CustomButton? {
  return view.compactMap({$0 as? CustomButton }).first
}

  

В CustomButton.swift

 class CustomButton: UIButton {
    var number: Int = 0
    var letter: Character?
    var textField: UITextField!
    var cornerLabel: UILabel!

    // this init will intialize the button through programatically
    override init(frame: CGRect) {
        super.init(frame: frame)

        textField = UITextField(frame: CGRect(x: 0, y: 0, width: 50, height: 50))
        textField.translatesAutoresizingMaskIntoConstraints = false
        textField.center = .zero
        textField.textAlignment = .center
        textField.text = ""
  

У меня есть ButtonStore.swift , который хранит все пользовательские кнопки в массиве, чтобы я мог управлять ими и извлекать определенные.

И MainController.swift у него есть все ссылки на customb. Я использую UITextFieldDelegate из MainController

 class MainController : UIViewController, UITextFieldDelegate{
    var buttonStore : ButtonStore!

    @IBOutlet var A1 : CustomButton!

    @IBAction func buttonIsPress(sender: CustomButton){
        let button : CustomButton = sender
        let identifier : String = sender.accessibilityIdentifier ?? ""
        // Clear all backgroundbox back to white unless the background is black
        buttonStore.removeHighlights()
        // Highlight the button pressed and its column and row
        buttonStore.highlightRowColumn(identifier: identifier)
    }

    func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool 
    {
        print("something happened")
        // TRIED RECEIVING THE CUSTOMBUTTON HERE
        return true
    }
  

Ожидаемый результат — срабатывание customb-кнопки при нажатии текстового поля или при нажатии пользовательской кнопки текстового поля, поэтому я использую Customb-кнопку в качестве ссылки.

Ответ №1:

Вы можете получить superview

 if let button = textField.superview as? CustomButton {
   // Do what you want to here
}
  

Комментарии:

1. Ого, это было проще, чем я ожидал. Я не знал, что вы можете изменить супервизор как объект. Большое вам спасибо.

2. @RandyLeRandy С удовольствием, пожалуйста, примите ответ, если он решил вашу проблему.

Ответ №2:

Вы можете захватить любой супервизор или любой контроллер родительского представления в общем случае безопасным для типов способом, пройдя вверх по цепочке ответчиков (потому что и UIViewController, и UIView наследуют от UIResponder и реализуют его next метод):

 extension UIResponder {
    func firstParent<T: UIResponder>(ofType type: T.Type ) -> T? {
        return next as? T ?? next.flatMap { $0.firstParent(ofType: type) }
    }
}
  

Используйте как:

 if let button = textField.firstParent(ofType: CustomButton.self) {
  //Do button stuff here
}
  

Преимущество этого метода в том, что вы можете найти следующего родителя определенного типа, даже если он не является непосредственным родителем (т. Е. У вас может быть несколько представлений между текстовым полем и пользовательской кнопкой, и это все еще работает, а вызов superview — нет).

Комментарии:

1. большое вам спасибо, я рассмотрю это, когда у меня будет дополнительное время, когда мне нужно будет управлять большим количеством вложенных представлений.