简体   繁体   中英

Swift 4 - Problems with delegate, UITextField returns nil

I'm in need for some help with my code. I have a UITextField in a UICollectionViewCell . And I want to access the data to my UICollectionViewController . The value returns nil .

I'm using the delegate method to pass data between classes but my value returns nil . I can't see where the problem is? Hope you guys can help me out. Thanks!

import UIKit
import Firebase


class EditUserProfileController: UICollectionViewController, UICollectionViewDelegateFlowLayout, UIGestureRecognizerDelegate {

weak var editUserProfileCellDelegate: EditUserProfileCell?

let cellId = "cellId"
    super.viewDidLoad()

    setupSaveButton()


    setupNavigationBar()

    collectionView?.register(EditUserProfileCell.self, forCellWithReuseIdentifier: cellId)


}


fileprivate func setupSaveButton() {
    navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Save", style: .plain, target: self, action: #selector(handleUpdateProfile))

}

    @objc func handleUpdateProfile() {


        editUserProfileCellDelegate?.delegate = self

        guard let name = editUserProfileCellDelegate?.nameTextfield.text, name.count > 0 else { return }
        guard let username = editUserProfileCellDelegate?.usernameTextfield.text, username.count > 0 else { return }
        guard let email = editUserProfileCellDelegate?.emailTextfield.text, username.count > 0 else { return }

        guard let city = editUserProfileCellDelegate?.cityTextfield.text else { return }
        guard let country = editUserProfileCellDelegate?.countryTextfield.text else { return }

        guard let fcmToken = Messaging.messaging().fcmToken else { return }

        guard let uid = Auth.auth().currentUser?.uid else { return }

        let ref = Database.database().reference().child("users")

        let disctionaryValues = ["username": username, "name": name, "email": email, "city": city, "country": country,"fcmToken": fcmToken]

        let values = [uid: disctionaryValues]

        ref.setValue(values) { (err, ref) in
            if let err = err {
                print("Failed to update user:", err)
                return
            }

            print("Succesfully updated user: ", self.user?.username ?? "")

        }

    }

And my UITextField:

import UIKit
import Firebase


class EditUserProfileCell: UICollectionViewCell, 
UINavigationControllerDelegate, UIImagePickerControllerDelegate {

    let nameTextfield: UITextField = {
    let tf = UITextField()

    let attributedText = NSMutableAttributedString(string: "Name", 
    attributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 14), NSAttributedString.Key.foregroundColor: UIColor.black])

    tf.attributedPlaceholder = attributedText

    tf.textColor = UIColor.black
    tf.font = UIFont.systemFont(ofSize: 14)
    tf.borderStyle = .none
    tf.layer.backgroundColor = UIColor.white.cgColor
    tf.layer.masksToBounds = false
    tf.layer.shadowColor = UIColor.lightGray.cgColor
    tf.layer.shadowOffset = CGSize(width: 0.0, height: 0.5)
    tf.layer.shadowOpacity = 1.0
    tf.layer.shadowRadius = 0.0

    return tf

}()

I expect to get the input in my Textfield to return, for example the name. But now do I only get nil .

It looks like you're little bit confued, how delegates work. So I created sample example:

protocol Delegate: class { // declare delegate protocol
    func someFunction()
}

class Cell: UICollectionViewCell {

    weak var delegate: Delegate? // declare delegate variable

    func callDelegate() {
        delegate?.someFuntion() // call method on delegate
    }
}

class ViewController: UICollectionViewController {
    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        ...
        cell.delegate = self // set delegate of cell as your view controller
        ...
    }
}

extension ViewController: Delegate { // implement protocol
    func someFunction() { // this method gets called when you call this method on delegate from some cell
    }
}

Okay, that should give you better view to that problem. So now let's transform it to your code.

Start with declaring protocol

protocol EditUserProfileCellDelegate: class {
    func nameSaved(_ name: String)
}

now create variable in cell subclass and call delegate when text field did end editing

class EditUserProfileCell: UICollectionViewCell, UINavigationControllerDelegate, UIImagePickerControllerDelegate {

    weak var delegate: EditUserProfileCellDelegate?
    ...
}

extension EditUserProfileCell: UITextFieldDelegate {
    func textFieldDidEndEditing(_ textField: UITextField) {
        if textField == nameTextField {
            delegate?.nameSaved(textField.text!)
        }
    }
}

now let's implement protocol to your view controller

extension EditUserProfileController: EditUserProfileCellDelegate {
    func nameSaved(_ name: String) {
        ... // do something with name
    }
}

and finally don't forget to set delegate of your cell in cellForItemAt

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    ...
    cell.delegate = self
    ...
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM