Swift Scroll to UITextField via UiscrollView only acts first time 错误

标签 swift uiscrollview uitextfield uitextfielddelegate uiscrollviewdelegate

我在这里发布我的完整代码。问题是最初加载应用程序和 View Controller 时。它完全有效。点击两个文本字段, ScrollView 向上推,键盘位于当前文本字段下方。但是如果点击文本字段.. 向上移动 View 并在文本字段上重新点击它就不再这样做了。此外,如果通过导航 Controller 返回然后再次加载此 View Controller ,它不会执行任何操作。它不再滚动了..(不再将文本字段向上推并且键盘不再位于其下方)...

import UIKit
import Parse
import Alamofire
import SwiftyJSON

class VCreservacion: UIViewController,UITextFieldDelegate,UIScrollViewDelegate {

    var SUCURSALID = 0
    var EMP_NOMBRE = ""
    var DIRECCION = ""
    var PROVINCIA = ""
    var RESTID = 20556

    @IBOutlet var lbl_empresa: UILabel!
    @IBOutlet var lbl_direccion: UILabel!
    @IBOutlet var lbl_step: UILabel!
    @IBOutlet var cantidadView: UIView!
    @IBOutlet var datePicker: UIDatePicker!
    @IBOutlet var btn_reservar: UIButton!
    @IBOutlet var stackView: UIStackView!
    @IBOutlet var scrollView: UIScrollView!
    @IBOutlet var txtComentario: UITextField!
    @IBOutlet weak var txtCelular: UITextField!
    var activeField: UITextField?

    var steps = 2


    // MARK: RESERVE ACTION
    @IBAction func ReserveAction(_ sender: UIButton) {
        print("Reservando...")

        // For date formater
        var dateformated = ""
        var dateformated2 = ""
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
        //formatter.timeZone = NSTimeZone(forSecondsFromGMT: 0) as TimeZone!


        dateformated = formatter.string(from: datePicker.clampedDate)
        dateformated2 = formatter.string(from: datePicker.date)
        print(dateformated)
        print(dateformated2)
        let cart = Cart.sharedInstance

        guard let user = PFUser.current()  else {
            cart.showAlertView("Login", message: "Debes estar logeado para poder reservar.")
            return
        }

        Alamofire.request("URL String", parameters: ["qty": "\(steps)","sucursalid":"\(self.SUCURSALID)","restid":"\(RESTID)","comment":"\(txtComentario.text!)","phone":"\(txtCelular.text!)","datetime":"\(dateformated)","action":"request","userid":"\(user.objectId!)"]).authenticate(usingCredential: cart.credential).responseJSON() {

            response in

            if (response.error != nil ) {

                print(response.error.debugDescription)
                print(response.request)
                cart.showAlertView("Error", message: "there was an error.")

            }

            if(response.result.value != nil) {

                let json = JSON(response.result.value!);

                print(json);


                let success:Bool = json["success"].boolValue
                let error: Bool = json["error"].boolValue

                if(success) {
                    print("con exito")
                    let alert = UIAlertController(title: "Reserva Enviada", message: "Tu reserva ha sido enviada y será revisada por el establecimiento", preferredStyle: .alert)
                    let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.default) {
                        UIAlertAction in

                        // Get the previous Controller.
                        let targetController: UIViewController = (self.navigationController?.viewControllers[self.navigationController!.viewControllers.count - 3])!

                        // And go to that Controller
                        self.navigationController?.popToViewController(targetController, animated: true)

                    }

                    alert.addAction(okAction)
                    self.present(alert,animated:true)


                }
            }

        }



    }



    @IBAction func stepperValue(_ sender: UIStepper) {

        self.lbl_step.text = Int(sender.value).description
        steps = Int(sender.value)

    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        registerForKeyboardNotifications()
        self.scrollView.delegate = self
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        deregisterFromKeyboardNotifications()
        self.scrollView.delegate = nil
    }


    // MARK: Viewdidload
    override func viewDidLoad() {
        super.viewDidLoad()
        // enable scroll on scrollview
         self.scrollView.isScrollEnabled = true

        // step label initial value 2
        self.lbl_step.text = "2"

        // Get celular or phone

        if ( Cart.sharedInstance.User_celular != "") {
            txtCelular.text = Cart.sharedInstance.User_celular
        } else {
            txtCelular.text = Cart.sharedInstance.User_phone
        }


        let nearesthour = Date().nearestHour()
        self.datePicker.minimumDate = nearesthour
        self.txtComentario.delegate = self
        self.txtCelular.delegate = self
        self.txtCelular.tag = 20
        self.scrollView.delegate = self


        // tap gesture recognizer

        let tap = UITapGestureRecognizer(target: self, action: #selector(handleTap(_:)))
        self.scrollView.addGestureRecognizer(tap)


        print("el enarest hour es \(nearesthour as Date?) y el date normal es \(Date())")

        self.btn_reservar.layer.cornerRadius = 10
        self.cantidadView.layer.cornerRadius = 10

        self.lbl_empresa.text = EMP_NOMBRE
        self.lbl_direccion.text = DIRECCION

        /*
        print("VC Reservacion")
        print("SUCURSAL \(SUCURSALID) ")
        print("EMP NOMBRE " + EMP_NOMBRE)
        print("DIRECCION " + DIRECCION)
        */


    }

    // MARK: TEXTFIELD STUFF

    func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
        self.activeField = textField
        return true
    }
    /*
    func textFieldDidBeginEditing(_ textField: UITextField) {
        self.activeField = textField
    }
    */


    func textFieldDidEndEditing(_ textField: UITextField) {

        activeField = nil

    }




    func registerForKeyboardNotifications(){
        //Adding notifies on keyboard appearing
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWasShown(notification:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillBeHidden(notification:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
    }

    func deregisterFromKeyboardNotifications(){
        //Removing notifies on keyboard appearing
        NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: nil)
        NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil)
    }

    @objc  func keyboardWasShown(notification: NSNotification){
        //Need to calculate keyboard exact size due to Apple suggestions

        print(" Keyboaard shown")


        var info = notification.userInfo!
        let keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size
        print(" el keyboardsize is \(keyboardSize)")
        let contentInsets : UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardSize!.height + 80, 0.0)

        self.scrollView.contentInset = contentInsets
        self.scrollView.scrollIndicatorInsets = contentInsets

        var aRect : CGRect = self.view.frame
        print("VIEW COMPLETE FRAME IS \(aRect)")
        print("KEYBOARD FRAME HEIGHT \(keyboardSize!.height)")
        aRect.size.height -= keyboardSize!.height
        print("FRAME MENOS KEYBOARD ES \(aRect)")

        print("SCROLLVIEW CONTENT \(self.scrollView.contentSize)")
        if let activeField = self.activeField {

            print("ACTIVEFIELD FRAME ORIGIN \(activeField.frame.origin) ")
            print("Active field is textfield tag is \(activeField.tag)")

            // if (!aRect.contains(activeField.frame.origin)){
            print("arect Does Not contains activeField")
            self.scrollView.scrollRectToVisible(activeField.frame, animated: true)
            print("TEXTFIELD FRAME ES \(activeField.frame)")
            print(" SCROLLVIEW CONTENT \(self.scrollView.contentSize)")
            //}
        }


    }

    @objc  func keyboardWillBeHidden(notification: NSNotification){
        //Once keyboard disappears, restore original positions
        var info = notification.userInfo!
        let keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size

        let contentInsets : UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, -keyboardSize!.height, 0.0)
        self.scrollView.contentInset = contentInsets
        self.scrollView.scrollIndicatorInsets = contentInsets
        self.activeField = nil
        self.view.endEditing(true)
        self.scrollView.isScrollEnabled = false

    }


    @objc func handleTap(_ sender: UITapGestureRecognizer) {
        self.view.endEditing(true)
        print("Tap")

    }


    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        self.view.endEditing(true)
        return false
    }


    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        scrollView.contentSize = CGSize(width: view.frame.width, height: view.frame.height)
        print(" SCROLLVIEW CONTENT AFTER SUBVIEWS \(self.scrollView.contentSize)")
    }


    /*  // NOT WORKING BECAUSE OF UISCROLLVIEW IN PLACE, MUST USE UITAPGESTURE RECOGNIZER
     override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
     self.view.endEditing(true)
     self.activeField?.resignFirstResponder()
     }
     */


}

最佳答案

我遇到了同样的问题。显然,获取键盘的大小发生了变化。我将 UIKeyboardFrameBeginUserInfoKey 更改为 UIKeyboardFrameEndUserInfoKey 并让它再次工作。

这是我在按下文本字段时移动 View 的确切代码

@objc func keyboardWasShown(notification: NSNotification){
    self.scrollView.isScrollEnabled = true
    var info = notification.userInfo!
    let keyboardSize = (info[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue.size
    let contentInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardSize!.height, 0.0)

    self.scrollView.contentInset = contentInsets
    self.scrollView.scrollIndicatorInsets = contentInsets

    var aRect : CGRect = self.view.frame
    guard let kbHeight = keyboardSize?.height else{return}
    aRect.size.height -= kbHeight
    if let activeField = self.activeTextField {
        if (!aRect.contains(activeField.frame.origin)){
            self.scrollView.scrollRectToVisible(activeField.frame, animated: true)
        }
    }
}

关于Swift Scroll to UITextField via UiscrollView only acts first time 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46746490/

相关文章:

iphone - 如何让图像在我双击的地方缩放?

iPhone 拉动以刷新移动图标位置

ios - 布局 UITextField 无论清除按钮 X

ios - 在不重新加载单元格的情况下在 UITableViewCell 上设置编辑样式

swift - Swift 中的动态字符串格式化

ios - 部分错误 Swift 中的行数

objective-c - XCode 8 - 如何解决 XCode 8.0 版的自动调整大小问题?

ios - 将 Objective-C block 转换为 Swift

Swift Generics - 调用哪个方法?

ios - 导航 Controller 之间的segue