使用单独的控制器将自定义单元格中的标签设置为数组中的名称
Posted
技术标签:
【中文标题】使用单独的控制器将自定义单元格中的标签设置为数组中的名称【英文标题】:Set labels in a custom cell to names from an array using a separate controller 【发布时间】:2020-07-31 15:58:57 【问题描述】:我有一个带表格的视图控制器。视图控制器有一个按钮,可以连接到另一个具有 4 个文本字段的控制器。有一个名称文本字段和其他三个可以输入数字的字段。当用户按下 add 时,会附加一个数组,并在更新前一个视图控制器中的表时关闭视图控制器。然后向用户呈现一个添加了新单元格的表格。该单元格有 4 个标签。
我试图弄清楚如何将单元格中的每个标签设置为创建新单元格的视图控制器中的 4 个文本字段。这是创建单元格的视图控制器的图片:
这是按下加号按钮时的视图控制器,它通过更新数组来创建单元格:
我希望能够设置最左边的标签来表示每次添加到数组中的名称。当一个人第一次单击加号按钮时,文本字段视图控制器将弹出,用户可以将名称放在文本字段中。当按下添加按钮时,左侧的标签将显示附加数组的控制器中的名称。通过视图控制器添加的下一个名称将位于先前输入的名称下方的单元格中,依此类推。我需要让数组正确显示文本。我最初希望单元格具有用户可以将信息放入其中的文本字段,但单元格数据没有正确发送到 firebase 数据库。
这是第一个视图控制器的代码:
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
这是第二个视图控制器的代码:
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)
我正在尝试使用在名为 renameLabel 的 addButton 函数中调用的函数附加标签。这里是func重命名标签代码:
func renameLabel()
let cell = ConsiderationsTestViewController.init().tableView.dequeueReusableCell(withIdentifier: AddPersonCell) as! ConsiderationsCell
cell.nameLabelC.text = ("\(ConsiderationsTestViewController.numberOfPeople)")
我现在收到错误:
Thread 1: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value
任何帮助都会很棒!
【问题讨论】:
【参考方案1】:首先在第二个VC之上创建一个协议。
protocol UpdatingArrayDelegate: class
func updateArray(newArray: [String])
在第二个 VC 里面创建:
var updatingArrayDelegate: UpdatingArrayDelegate!
然后在推送到第二个 VC 之前,将委托设置为 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)
现在在按 addButton 完成 secondVC 上的编辑时,请执行以下操作:
@objc func doneButtonTapped()
updatingArrayDelegate?.updateArray(newArray: myNewArrayCreatedOnThisSecondVC)
self.navigationController?.popViewController(animated: true)
然后先添加委托函数
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]
您可以这样考虑委托: 老板(secondVC)给工人(firstVC)一个做什么的协议。 Worker 读取协议并使用协议中给出的功能进行工作。在工人跑向老板之前,他必须确保他可以完成下一个任务(写在他将要拥有的协议上。)
【讨论】:
以上是关于使用单独的控制器将自定义单元格中的标签设置为数组中的名称的主要内容,如果未能解决你的问题,请参考以下文章
填充 UITableViewController 时,自定义单元格中的标签为空