Using “Next” as a Return Key

前端 未结 4 1147
深忆病人
深忆病人 2020-11-30 03:21

I use the \"Next\" value for the \"Return Key\" to get the Next button in place of the Done button, but (obviously) pressing it doesn\'t automatically move to the next UITex

4条回答
  •  暗喜
    暗喜 (楼主)
    2020-11-30 03:48

    There is nothing wrong with the other answers, this is just a different approach with the benefit of being more focused on OOP - imho (although this is a bit more work up front, it can be reused). In the storyboard, I start off adding tags with a distinct range (e.g 800-810) that define the specific order of the fields I want to move between. This has the benefit of working across all subviews in the main view so that one can navigate between UITextField's and UITextView's (and any other control) as needed.

    Generally - I typically try to have view controllers message between views and custom event handler objects. So I use a message (aka, NSNotification) passed back to the view controller from a custom delegate class.

    (TextField Delegate Handler)

    Note: In AppDelegate.swift: let defaultCenter = NSNotificationCenter.defaultCenter()

    //Globally scoped
    struct MNGTextFieldEvents {
        static let NextButtonTappedForTextField = "MNGTextFieldHandler.NextButtonTappedForTextField"
    }
    
    class MNGTextFieldHandler: NSObject, UITextFieldDelegate {
    
        var fields:[UITextField]? = []
    
        func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
            return true
        }
        func textFieldDidBeginEditing(textField: UITextField) {
            textField.backgroundColor = UIColor.yellowColor()
        }
        func textFieldDidEndEditing(textField: UITextField) {
            textField.backgroundColor = UIColor.whiteColor()
        }
        func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
            return true
        }
        func textFieldShouldClear(textField: UITextField) -> Bool {
            return false
        }
        func textFieldShouldEndEditing(textField: UITextField) -> Bool {
            return true
        }
        func textFieldShouldReturn(textField: UITextField) -> Bool {
    
            //passes the message and the textField (with tag) calling the method
            defaultCenter.postNotification(NSNotification(name: MNGTextFieldEvents.NextButtonTappedForTextField, object: textField))
    
            return false
        }
    }
    

    This allows my view controller to remain focused on it's main job of handling the messaging between objects, model and view.

    (View Controller receives a message from the delegate and passes instructions using the advanceToNextField function)

    Note: In my storyboard my custom handler classes are defined using an NSObject and that object is linked into the storyboard as a delegate for the controls that I need monitored. Which causes the custom handler class to be initialized automatically.

    class MyViewController: UIViewController {
        @IBOutlet weak var tagsField: UITextField! { didSet {
            (tagsField.delegate as? MNGTextFieldHandler)!.fields?.append(tagsField)
            }
        }
        @IBOutlet weak var titleField: UITextField!{ didSet {
            (titleField.delegate as? MNGTextFieldHandler)!.fields?.append(titleField)
            }
        }
        @IBOutlet weak var textView: UITextView! { didSet {
         (textView.delegate as? MNGTextViewHandler)!.fields?.append(textView)
    
            }
        }
    
        private struct Constants {
         static let SelectorAdvanceToNextField = Selector("advanceToNextField:")
    }
        override func viewWillAppear(animated: Bool) {
            super.viewWillAppear(animated)
            registerEventObservers()
        }
        override func viewDidDisappear(animated: Bool) {
            super.viewDidDisappear(animated)
            deRegisterEventObservers()
        }
    
        func advanceToNextField(notification:NSNotification) {
            let currentTag = (notification.object as! UIView).tag
    
            for aView in self.view.subviews {
                if aView.tag == currentTag + 1 {
                    aView.becomeFirstResponder()
                }
            }
        }
    
        func registerEventObservers () {
    
            defaultCenter.addObserver(self, selector: Constants.SelectorAdvanceToNextField, name: MNGTextFieldEvents.NextButtonTappedForTextField, object: nil)
        }
    
        func deRegisterEventObservers() {
    
            defaultCenter.removeObserver(self, name: MNGTextFieldEvents.NextButtonTappedForTextField, object: nil)
        }
    
        ....
    }
    

提交回复
热议问题