Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strange delay displaying text in input accessory view during push animation.

Tags:

ios

swift

I'm facing problem when string in UILabel is displayed with delay in inputAccessoryView on UIViewController. I have attached gif demonstrating this problem. After pushing SecondViewController to navigation stack inputAccessoryView is missing text for short time. But I want text to be shown right away after opening screen.

enter image description here

Implementation demonstrating this problem is extremely simple.

class SecondViewController: UIViewController {

        @IBOutlet var accessoryView: UIView!

        override var inputAccessoryView: UIView {
            return accessoryView
        }

        override func canBecomeFirstResponder() -> Bool {
            return true
        }
    }

Does any one have solution for this problem?

like image 231
salabaha Avatar asked Dec 11 '15 23:12

salabaha


1 Answers

I have come up with the solution which works on both iOS 8 and 9. Also it address retain cycle issue presented in iOS 9 which prevent view controller from being deallocated when use inputaccessoryview. Check github project for more details.

With lots of experimentation I have found quite hacky solution but works like a charm. Just subclass your implemantation accessory view from AccessoryView listed below.

class AccessoryView: UITextField {
    override var canBecomeFirstResponder: Bool {
        return true
    }
    
    override func awakeFromNib() {
        super.awakeFromNib()
        disableShowingKeyboard()
        hideCursor()
    }
}

extension AccessoryView {
    
    private func disableShowingKeyboard() {
        inputView = UIView()
    }
    
    private func hideCursor() {
        tintColor = UIColor.clear
    }
    
    override func accessibilityActivate() -> Bool {
        return false
    }
    
    override var isEditing: Bool {
        return false
    }
    
    override func caretRect(for position: UITextPosition) -> CGRect {
        return .zero
    }
    
    override func selectionRects(for range: UITextRange) -> [UITextSelectionRect] {
        return []
    }
    
    override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
        if action == #selector(UIResponder.copy(_:)) || action == #selector(UIResponder.selectAll(_:)) || action == #selector(UIResponder.paste(_:)){
            return false
        }
        
        return super.canPerformAction(action, withSender: sender)
    }
    
    override func addGestureRecognizer(_ gestureRecognizer: UIGestureRecognizer) {
        if gestureRecognizer is UILongPressGestureRecognizer {
            gestureRecognizer.isEnabled = false
        }
        
        super.addGestureRecognizer(gestureRecognizer)
    }
}

extension AccessoryView {
    override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        for view in subviews {
            let _point = self.convert(point, to: view)
            if !view.isHidden && view.isUserInteractionEnabled && view.alpha > 0.01 && view.point(inside: _point, with: event) {
                if let _view = view.hitTest(_point, with: event){
                    return _view
                }
            }
        }

        return super.hitTest(point, with: event)
    }
}

 
like image 172
salabaha Avatar answered Oct 28 '22 18:10

salabaha