Set labels in a custom cell to names from an array using a separate controller

给你一囗甜甜゛ 提交于 2020-08-10 19:17:55

问题


I have a view controller with a table. The view controller has a button that segues to another controller with 4 textfields. There is a name textfield and three others where numbers can be inputed. When a user presses add, an array is appended and the view controller is dismissed while updating the table in the previous view controller. The user is then presented a table with a new cell added. The cell has 4 labels.

I am trying to figure out how to set each label in a cell to the 4 textfields that are in the view controller that created the new cell. Here is a picture of the view controller with a cell created:

Here is the view controller when the plus button is pressed that creates the cell by updating the array:

I would like to be able to set the far left label to represent the name that is added to the array every time. The first time a person clicks the plus button, the textfields view controller will pop up and the the user can put the name in the textfield. When the add button is pressed the label on the left would show the name in the controller that appended the array. The next name that is added through the view controller will be in the cell below the previous name entered and so forth. I need to get the array to show the text properly. I originally wanted the cells to have textfields that the user could put the info in there but the cells data wasn't sending to firebase database properly.

Here is the code for the first view controller:

import UIKit
import Firebase

class ConsiderationsTestViewController: UIViewController, UITextFieldDelegate {

@IBOutlet weak var tableView: UITableView!

static var numberOfPeople: [String] = []

var AddPersonCell = "AddPersonCell"

@IBOutlet weak var CompanyImage: UIImageView!

@IBOutlet weak var companyNameTextFieldConsiderations: UITextField!

@IBOutlet weak var companyDescriptionTextFieldConsiderations: UITextField!

@IBOutlet weak var startDateTextFieldConsiderations: UITextField!

@IBOutlet weak var endDateTextFieldConsiderations: UITextField!

let datePickerS = UIDatePicker()
let datePickerE = UIDatePicker()

    var database: Database!
    var storage: Storage!
    var selectedImage: UIImage?
    
    var ref:DatabaseReference?
    var databaseHandle:DatabaseHandle = 0
    
    let dbref = Database.database().reference()
    let uid = Auth.auth().currentUser?.uid
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        tableView.delegate = self
        tableView.dataSource = self
        
        self.companyNameTextFieldConsiderations.delegate = self
        self.companyDescriptionTextFieldConsiderations.delegate = self
        
        // Set the Firebase reference
        ref = Database.database().reference()
        
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(ConsiderationsTestViewController.handleSelectCompanyImageView))
         CompanyImage.addGestureRecognizer(tapGesture)
         CompanyImage.isUserInteractionEnabled = true

        self.navigationController!.navigationBar.isTranslucent = false
        
        navigationItem.backBarButtonItem = UIBarButtonItem(
        title: "", style: .plain, target: nil, action: nil)
        
        createDatePickerForStart()
        
        createDatePickerForEnd()
        
        NotificationCenter.default.addObserver(self, selector: #selector(loadList), name: NSNotification.Name(rawValue: "load"), object: nil)
    }

  @objc func loadList(){
    //load data here
    self.tableView.reloadData()
}

    @objc func handleSelectCompanyImageView() {

        let pickerController = UIImagePickerController()
        pickerController.delegate = self
        pickerController.allowsEditing = true
        present(pickerController, animated: true, completion: nil)
                    }
    
    @IBAction func AddPersonTapped(_ sender: Any) {
  
       }

    @IBAction func sendButtonTapped(_ sender: Any) {
    
    let companyNameC = companyNameTextFieldConsiderations.text!.trimmingCharacters(in: .whitespacesAndNewlines)
    let companyDescriptionC = companyDescriptionTextFieldConsiderations.text!.trimmingCharacters(in: .whitespacesAndNewlines)
    
    let today = Date()
    let formatter1 = DateFormatter()
    formatter1.dateFormat = "MMM d y"
    print(formatter1.string(from: today))
    let todaysDate = formatter1.string(from: today)
            
    let storageRef = Storage.storage().reference(forURL: "STORAGE URL HERE")
    let imageName = companyNameTextFieldConsiderations.text!
    let storageCompanyRef = storageRef.child("Company_Image_Considerations").child("\(todaysDate)").child(imageName)
    let companyDescriptionTextFieldText = companyDescriptionTextFieldConsiderations.text
    let dateToStart = startDateTextFieldConsiderations.text
    let dateToDecide = endDateTextFieldConsiderations.text
    let companyRef = Database.database().reference().child("Considerations").child("\(todaysDate)").child(imageName)

    let considerationInfluencerRef = Database.database().reference().child("Considerations").child("\(todaysDate)").child(imageName).child("Users")
    
     //let values = ["Feed_Quantity": "feedTFC", "Story_Quantity": "storyTFC", "Compensation": "compensationTFC"]
    
        guard let imageSelected = self.CompanyImage.image else {
            print ("Avatar is nil")
            return
                }
                   
                var dict: Dictionary<String, Any> = [
                    "Company Image": "",
                    "Company Description": companyDescriptionTextFieldText!,
                    "Start Date": dateToStart!,
                    "Decision Date": dateToDecide! ]
    
                   
        guard let imageData = imageSelected.jpegData(compressionQuality: 0.5) else {
            return
                }
    
                let metadata = StorageMetadata()
                metadata.contentType = "image/jpeg"
                storageCompanyRef.putData(imageData, metadata: metadata, completion:
                { (StorageMetadata, error) in
                if (error != nil) {
                return
                    }
                            
                storageCompanyRef.downloadURL { (url, error) in
                if let metadateImage = url?.absoluteString {
                dict["Company Image"] = metadateImage
                   
                companyRef.updateChildValues(dict, withCompletionBlock:  {
                (error, ref) in
                if error == nil {
                print("Done")
                return
                    }
                  }
                )
               }
             }
                            
                                   storageRef.updateMetadata(metadata) { metadata, error in
                                    if error != nil {
                                    //Uh-oh, an error occurred!
                                    } else {
                                    // Updated metadata for 'images/forest.jpg' is returned
                                }
                            }
                        })
    
      //        considerationInfluencerRef.updateChildValues(values as [AnyHashable : Any]) { (error, ref) in
      //        if error != nil {
      //        print(error ?? "")
      //        return
      //                           }
    
      self.navigationController?.popViewController(animated: true)
      //           }
       }


    func createDatePickerForStart() {
    // center text in field
    startDateTextFieldConsiderations.textAlignment = .center
    
    // toolbar
    let toolbar = UIToolbar()
    toolbar.sizeToFit()
    
    // barbutton
    let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: nil, action: #selector(donePressedStart))
    toolbar.setItems([doneButton], animated: true)
    
    // assign toolbar to textfield
    
    startDateTextFieldConsiderations.inputAccessoryView = toolbar
    
    // assign datePicker to text field
    startDateTextFieldConsiderations.inputView = datePickerS
    
    // date picker mode
    datePickerS.datePickerMode = .date
    
     }
 
    func createDatePickerForEnd() {
    // center text in field
    endDateTextFieldConsiderations.textAlignment = .center
    
    // toolbar
    let toolbar = UIToolbar()
    toolbar.sizeToFit()
    
    // barbutton
    let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: nil, action: #selector(donePressedEnd))
    toolbar.setItems([doneButton], animated: true)
    
    // assign toolbar to textfield
    endDateTextFieldConsiderations.inputAccessoryView = toolbar
    
    // assign datePicker to text field
    endDateTextFieldConsiderations.inputView = datePickerE
    
    // date picker mode
    datePickerE.datePickerMode = .dateAndTime
       }

    @objc func donePressedStart() {
    // formatter
    let formatter = DateFormatter()
    formatter.dateStyle = .medium
    formatter.timeStyle = .none
    
    startDateTextFieldConsiderations.text = formatter.string(from: datePickerS.date)
    self.view.endEditing(true)
     }

    @objc func donePressedEnd() {
    // formatter
    let formatter = DateFormatter()
    formatter.dateStyle = .medium
    formatter.timeStyle = .medium
    
    endDateTextFieldConsiderations.text = formatter.string(from: datePickerE.date)
    self.view.endEditing(true)
            }

    @IBAction func testTapped(_ sender: Any) {
    print(ConsiderationsTestViewController.numberOfPeople)
           }
        }
    
    extension ConsiderationsTestViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
               func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
                   //print("did Finish Picking Media")
                   if let image = info[UIImagePickerController.InfoKey(rawValue: "UIImagePickerControllerEditedImage")] as? UIImage{
                       selectedImage = image
                       CompanyImage.image = image
                   }
                   dismiss(animated: true, completion: nil)
               }
           }

      extension ConsiderationsTestViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return ConsiderationsTestViewController.numberOfPeople.count
         }

    func numberOfSections(in tableView: UITableView) -> Int {
    return 1
         }


    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCell(withIdentifier: AddPersonCell, for: indexPath) as! ConsiderationsCell
    
    return cell
       }

     }

Here is the code for the second view controller:

import UIKit
import Firebase

class DropDownCellViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate, UITextFieldDelegate {

var numberOfPeople = [String]()

var users = [User]()

var userName = [String]()

var filteredNames: [String]!

let dropDownCell = "dropDownCell"

var emptyField = [String]()

override func viewDidLoad() {
super.viewDidLoad()

updateDataArray()

tableView.register(UserCell.self, forCellReuseIdentifier: dropDownCell)

filteredNames = userName

    tableView.delegate = self
    tableView.dataSource = self
    nameTextField.delegate = self
       
    tableView.isHidden = true
       
       // Manage tableView visibility via TouchDown in textField
nameTextField.addTarget(self, action: #selector(textFieldActive), for: UIControl.Event.touchDown)
   }

@IBOutlet weak var nameTextField: NoCopyPasteUITextField!

@IBOutlet weak var tableView: UITableView!

@IBOutlet weak var gridTextField: UITextField!

@IBOutlet weak var storyTextField: UITextField!

@IBOutlet weak var compensationTextField: UITextField!

@IBAction func textFieldChanged(_ sender: AnyObject) {
    tableView.isHidden = true
}

@IBAction func cancelButtonTapped(_ sender: Any) {
    self.navigationController?.popViewController(animated: true)
}

@IBAction func addButtonTapped(_ sender: Any) {
    
    ConsiderationsTestViewController.numberOfPeople.append("\(nameTextField.text!)")
    
    self.navigationController?.popViewController(animated: true)
    
    print(ConsiderationsTestViewController.numberOfPeople)
    
    DispatchQueue.main.async {
       NotificationCenter.default.post(name: NSNotification.Name(rawValue: "load"), object: nil)
            }
    }

  let searchController = UISearchController(searchResultsController: nil)

  override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    }

  override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?)
    {
      guard let touch:UITouch = touches.first else
      {
          return;
      }
      if touch.view != tableView
      {
          nameTextField.endEditing(true)
          tableView.isHidden = true
      }
    }

   @objc func textFieldActive() {
       tableView.isHidden = !tableView.isHidden
   }

  // MARK: UITextFieldDelegate
   func textFieldDidEndEditing(_ textField: UITextField) {
       // TODO: Your app can do something when textField finishes editing
       print("The textField ended editing. Do something based on app requirements.")
   }
   
   func textFieldShouldReturn(_ textField: UITextField) -> Bool {
       textField.resignFirstResponder()
       return true
   }


  func numberOfSections(in tableView: UITableView) -> Int {
      // #warning Incomplete implementation, return the number of sections
    return 1
   }

  func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    // #warning Incomplete implementation, return the number of rows
    
    return filteredNames.count
    }

  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    
    let cell = tableView.dequeueReusableCell(withIdentifier: dropDownCell, for: indexPath) as!
    UserCell
    
    let user = users[indexPath.row]
    cell.textLabel?.text = user.name
    
    if let profileImageUrl = user.profileImageUrl {
    
    cell.profileImageView.loadImageUsingCacheWithUrlString(urlString: profileImageUrl)
        
    }
    return cell
}

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 72
}

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    // Row selected, so set textField to relevant value, hide tableView
           // endEditing can trigger some other action according to requirements
           nameTextField.text = userName[indexPath.row]
           tableView.isHidden = true
           nameTextField.endEditing(true)
       }

//Mark: Search Bar Config
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    
    filteredNames = []
    
    if searchText == "" {
        filteredNames = userName
        
    }
    else {
        for names in userName {
            
            if names.lowercased().contains(searchText.lowercased()) {
                
                filteredNames.append(names)
            }
        }
    }
    self.tableView.reloadData()
}

func updateDataArray() {
    
    Database.database().reference().child("users").observe(.childAdded, with: { (snapshot) in
        
        if let dictionary = snapshot.value as? [String: AnyObject] {
            
            let user = User()
            //self.setValuesForKeys(dictionary)
            user.name = dictionary["name"] as? String
            user.email = dictionary["email"] as? String
            user.facebookUrl = dictionary["facebookUrl"] as? String
            user.instagramUrl = dictionary["instagramUrl"] as? String
            user.linkedInUrl = dictionary["linkedInUrl"] as? String
            user.profileImageUrl = dictionary["profileImageUrl"] as? String
            user.twitterUrl = dictionary["twitterUrl"] as? String
            user.id = dictionary["id"] as? String
            user.userType = dictionary["userType"] as? String
            
            self.users.append(user)
            self.userName.append(user.name!)
            self.filteredNames.append(user.name!)
            
            DispatchQueue.main.async {
            self.tableView.reloadData()
            }
        }
        
    }, withCancel: nil)
    
    
  }
 }

I am trying to append the label with a function that is called in the addButton function called renameLabel. Here is the func rename label code:

func renameLabel() {
let cell = ConsiderationsTestViewController.init().tableView.dequeueReusableCell(withIdentifier: AddPersonCell) as! ConsiderationsCell
    
cell.nameLabelC.text = ("\(ConsiderationsTestViewController.numberOfPeople)")
}

I am now getting the error:

Thread 1: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value

Any help would be awesome!


回答1:


First of all create a protocol above second VC.

protocol UpdatingArrayDelegate: class {
    func updateArray(newArray: [String])
}

And inside the second VC create:

var updatingArrayDelegate: UpdatingArrayDelegate!

Then before pushing to the second VC, set the delegate to self:

@objc func pushToSecondVCButtonTapped() {
    let destVC = secondVC()
    updatingArrayDelegate = self
    self.navigationController?.pushViewController(destVC, animated: true)
    // if you don't have self.navigationController use:
    // present(destVC(), animated: true, completion: nil)
}

Now when finishing the edit on secondVC when pressing your addButton do the following:

@objc func doneButtonTapped() {
    updatingArrayDelegate?.updateArray(newArray: myNewArrayCreatedOnThisSecondVC)
    self.navigationController?.popViewController(animated: true)
}

Then add the delegate function on first

extension FirstVC: UpdatingArrayDelegate {
    func updateArray(newArray: [String]) {
        print("updateArray")
        let myCell = myTableView.cellForRow(at: IndexPath(row: x, section: y)) as! MyCell
        myCell.textLabel1.text = newArray[0]
        myCell.textLabel2.text = newArray[1]
        myCell.textLabel3.text = newArray[2]
        myCell.textLabel4.text = newArray[3]
    }
}

You can think about delegate like this: The boss (secondVC) gives a the worker (firstVC) a protocol of what to do. The Worker reads the protocol and is doing the work with his function given in the protocol. Before the worker runs to the boss, he must be sure that he can do the next task (written on the protocol he is going to have.)



来源:https://stackoverflow.com/questions/63195254/set-labels-in-a-custom-cell-to-names-from-an-array-using-a-separate-controller

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!