How to get the label values from multiple selected cells in a UITableView and pass them to a different ViewController swift - swift

Sorry, I'm a noob,
I am a bit stuck. I have been researching this for awhile and cannot find anything to help.
So, my problems is:
I have a Table View controller with a bunch of Cells (Depending on users contact address book). These Cells contain the users contacts information (Name and #) users can select up to 3 cells (Contacts).
That all works fine, I just need to know how to get the name and # labels data from each cell so I can display that information in another View Controller (CAContactsList) when I press the "Done" button (which I'm also stumped with).
My Current Table View Controller Class:
class AddContactsListTableView: UITableViewController {
var contacts = [FetchedContact]()
override func viewDidLoad() {
super.viewDidLoad()
fetchContacts()
}
private func fetchContacts() {
print("Attempting to fetch contacts")
let store = CNContactStore()
store.requestAccess(for: .contacts) { (granted, error) in
if let error = error {
print("failed to request access", error)
return
}
if granted {
print("access granted")
let keys = [CNContactGivenNameKey, CNContactFamilyNameKey, CNContactPhoneNumbersKey]
let request = CNContactFetchRequest(keysToFetch: keys as [CNKeyDescriptor])
do {
try store.enumerateContacts(with: request, usingBlock: { (contact, stopPointer) in
print(contact.givenName)
self.contacts.append(FetchedContact(firstName: contact.givenName, lastName: contact.familyName, telephone: contact.phoneNumbers.first?.value.stringValue ?? ""))
})
} catch let error {
print("Failed to enumerate contact", error)
}
} else {
print("access denied")
}
}
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
// return the number of sections
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// return the number of rows
return contacts.count
}
override func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
//Max Number of contacts allowed to be selected
let limit = 3
if let selectedRows = tableView.indexPathsForSelectedRows {
if selectedRows.count == limit {
let alertController = UIAlertController(title: "Oops", message: "Sorry, but you are limited to only \(limit) Contacts", preferredStyle: UIAlertController.Style.alert)
alertController.addAction(UIAlertAction(title: "Ok", style: .default, handler: {action in}))
self.present(alertController, animated: true, completion: nil)
return nil
}
}
return indexPath
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cellIdentifier = "AddContactsCell"
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as? AddContactsCell
// Configure the cell...
cell?.NamesLabel.text = contacts[indexPath.row].firstName + " " + contacts[indexPath.row].lastName
cell?.NumberLabel.text = contacts[indexPath.row].telephone
return cell!
}
}
My Current Cell Class:
class AddContactsCell: UITableViewCell {
//Mark Properties
#IBOutlet weak var NamesLabel: UILabel!
#IBOutlet weak var NumberLabel: UILabel!
#IBOutlet weak var ButtonSelector: UIButton!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// update UI with Checkmark when Selected
accessoryType = selected ? .checkmark : .none
}
}
And my Fetched Contacts Class
struct FetchedContact {
var firstName: String
var lastName: String
var telephone: String
}
Any help would be Greatly Appreciated!

Override the prepare(for segue: UIStoryboardSegue, sender: Any?) in the AddContactsListTableView class where you can pass the selected contacts to the next view controller.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Pass the selected object to the new view controller.
if let selectedRows = tableView.indexPathsForSelectedRows {
let selectedContacts = selectedRows.map{contacts[$0.row]}
let newVC = segue.destination as! NewViewController
newVC.contacts = selectedContacts
}
}
See this tutorial for more.

So basically you are already on the right track querying the table view's indexPathsForSelectedRows since it will contain the indices you need to filter your contacts for. The selected contacts should be:
guard let selectedIndices = tableView.indexPathsForSelectedRows else { return }
let selectedContacts = selectedIndices.map { contacts[$0.item] }
[Edit]: Use a more concise version

Related

Anyone know how to make username appear on shop?

Making a shopping cart app and come to a problem. I have a login page where if logged in it will store in core data and login but I want to make the username appear on the table view on another view controller
LoginVC:
import UIKit
import CoreData
class LoginVC: UIViewController {
#IBOutlet weak var username: UITextField!
#IBOutlet weak var password: UITextField!
var context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view
fetchData()
}
#IBAction func login(_ sender: Any) {
for acc in userList {
if username.text == acc.username && password.text == acc.password {
currentUser = username.text!
try! context.save()
performSegue(withIdentifier: "DisplayShop1", sender: nil)
}
/*else if username.text == "" || password.text == "" || username.text != acc.username || password.text != acc.username {
let alert = UIAlertController(title: "Alert", message: "Please enter the right credentials", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Dismiss", style: .default, handler: nil))
present(alert, animated: true, completion: nil)
}*/
}
}
func fetchData(){
userList = try! context.fetch(User.fetchRequest())
}
}
ListingShopVC
import UIKit
import CoreData
class ListingShopVC: UIViewController, UITableViewDelegate, UITableViewDataSource{
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var usernameloggedin: UILabel!
#IBOutlet weak var creditsdisplay: UILabel!
var context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
var myUser:[User] = []
var mySecond:[Product] = []
var mySecondF:[Product] = []
var id:String = ""
var name:String = ""
var price:Double = 0.0
var image:String = ""
var details:String = ""
#IBOutlet weak var searchBar: UISearchBar!
override func viewDidLoad() {
super.viewDidLoad()
fetch()
tableView.delegate = self
tableView.dataSource = self
extracted()
usernameloggedin.text = "Welcome \(userList)"
creditsdisplay.text = "You have \(userList)"
}
// MARK: - Table view data source
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 mySecond.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "hello", for: indexPath) as! TableCellData
// Configure the cell...
cell.shopTitle.text = mySecond[indexPath.row].name
cell.shopPrice.text = "$" + String(mySecond[indexPath.row].price) + "0"
cell.shopDesc.text = mySecond[indexPath.row].description
if let imageURL = URL(string: mySecond[indexPath.row].image) {
DispatchQueue.global().async {
let data = try? Data(contentsOf: imageURL)
if let data = data {
let image = UIImage(data: data)
DispatchQueue.main.async {
cell.shopImageView.image = image
}
}
}
}
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
id = mySecond[indexPath.row].id
name = mySecond[indexPath.row].name
price = mySecond[indexPath.row].price
image = mySecond[indexPath.row].image
//print("At table \(image)")
details = mySecond[indexPath.row].description
performSegue(withIdentifier: "toDetails", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender:Any?){
if segue.identifier == "toDetails"{
let vc = segue.destination as! ProductDetail
vc.productID = id
vc.productName = name
vc.productPrice = price
vc.productPicture = image
vc.productDetails = details
print(vc.productDetails)
}
}
func extracted(){
guard let url = URL(string: "http://rajeshrmohan.com/sport.json")
else {return}
let task = URLSession.shared.dataTask(with: url){
(data,response,error) in
guard let dataResponse = data,
error == nil else {
print(error?.localizedDescription ?? "Response Error")
return
}
do {
let decoder = JSONDecoder()
let model:[Product] = try decoder.decode([Product].self, from: dataResponse)
//print(model)
for i in 0..<model.count{
self.mySecond.append(model[i])
}
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
catch let parsingError {
print("Error", parsingError)
}
}
task.resume()
}
#IBAction func logOut(_ sender: Any) {
}
func fetch(){
userList = try! context.fetch(User.fetchRequest())
tableView.reloadData()
}
}
The top part https://i.stack.imgur.com/9RahD.jpg
I just want to make it appear on on top also it seems my login page and codes doesn't work well If I put a if empty so if any probable suggestions will be appreciated
As far as I understand you can't pass data between pages. Add this to the page you got the userList from.
#IBAction func okAction(_ sender: Any) {
let controller = storyboard?.instantiateViewController(withIdentifier: "DisplayShop1") as! ListingShopVC
controller.userList = userList
controller.modalPresentationStyle = .fullScreen
present(controller, animated: true, completion: nil)
}
If you add this to the page you want to transfer the userList of later, you can call the userList.
var userList: String = ""
You almost have it. Instead of passing the username into the string, you're passing the entire list of Core Data objects which get formatted as a string, but not in the way you want. You should get the username for the user, then pass that into the string:
let username = userList.first?.username ?? ""
usernameloggedin.text = "Welcome \(username)"
creditsdisplay.text = "You have \(username)"
That said, here's a couple critiques to make this work even more reliably.
I would move this part of the code to your function to load from the database. That way if you ever reload the data from the database, it will get the correct user, and the name will be updated appropriately.
You should pick one user that is doing the shopping, and only one user. Currently you are getting a list of users and keeping the list of users. There's also no sorting to determine which user is used, so it could change mid-shop. To fix that, I suggest you create a new property to store the current user that is of type User, rather than [User], and only load one user from the database. The fetch request will return an array, so you need to get and keep only the first one. Additionally, to make this even more reliable, you might consider having your first view check if there is a user logged in, get that user from the database (which you are already doing), and pass that user into the shop view using dependency injection. There's plenty of tutorials out there for how to handle that, but basically you get a reference to the second view in the prepareForSegue call and set the user property on that second view to the desired user, thereby 'injecting your dependency'.

How to input the value from UI button in Teble View cell to the variable declared in Table View Controller?

I want to save the value of filled button(●) into the array "q.answer[indexPath.row]" about each question "q.question[indexPath.row]).
currentQuizButtonIndex is currently renewed every time when ◯ changes to ● by tapping. However, I have no idea how to save in to variable q which is declared in TableViewController.
View Controller display
Code about QuizCell.swift (TableCell which is about 5 buttons and UIlabel.)
import UIKit
import Foundation
protocol QuizCellDelegate {
func quizCellDidChangeCurrentButtonIndex(_ cell: QuizCell, index: Int)
}
class QuizCell: UITableViewCell {
var currentQuizButtonIndex: Int = 0 {
didSet {
let value = self.currentQuizButtonIndex
self.updateCurrentQuizButton(value)
if let delegate = self.delegate {
delegate.quizCellDidChangeCurrentButtonIndex(self, index: value)
}
}
}
#IBOutlet weak var questionLabel: UILabel!
#IBOutlet var answerButtons: [UIButton]!
var delegate: QuizCellDelegate?
override func awakeFromNib() {
super.awakeFromNib()
//print("ここまできてるか確認")
// Initialization code
}
#IBAction func didTapQuizButton(_ sender: UIButton) {
if let index = self.answerButtons.firstIndex(of: sender){
self.currentQuizButtonIndex = index
delegate?.quizCellDidChangeCurrentButtonIndex(self, index: index)
print(index)
}
}
private func updateCurrentQuizButton(_ currentIndex: Int){
for (index, answerButton) in self.answerButtons.enumerated(){
if index == currentIndex {
answerButton.setTitle("●", for: .normal)
} else {
answerButton.setTitle("○", for: .normal)
}
}
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
Code about View Controller
import UIKit
class AnswerQuizViewController: UIViewController, UITableViewDelegate {
var q: QuestionSeries!
#IBOutlet weak var quizTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
quizTableView.dataSource = self
quizTableView.delegate = self
// cell xibファイルを使うときは書く必要があるやつ。
// quizTableView.register(UINib(nibName: K.Cells.QuizCellNibName, bundle: nil), forCellReuseIdentifier: K.Cells.QuizCellIdentifier)
quizTableView.register(UINib(nibName: "QuizCell", bundle: nil), forCellReuseIdentifier: "QuizCellIdentifier")
// Do any additional setup after loading the view.
}
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
// override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// // Get the new view controller using segue.destination.
// // Pass the selected object to the new view controller.
//// if segue.identifier == K.Segue.checkResult {
//// let resultViewController = segue.destination as! ResultViewController
//// answerQuizViewController.q =
//// print(answerQuizViewController.q)
// }
}
// MARK: - quizTableViewのアレンジ
extension AnswerQuizViewController: UITableViewDataSource, QuizCellDelegate {
func quizCellDidChangeCurrentButtonIndex(_ cell: QuizCell, index: Int) {
if let indexPath = self.quizTableView.indexPath(for: cell){
self.q.question[indexPath.row].answer = index
print(index)
}else{
print("ここきてます")
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return q.question.count
//print(q.question.count)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let question = q.question[indexPath.row]
let cell = quizTableView.dequeueReusableCell(withIdentifier: K.Cells.QuizCellIdentifier, for: indexPath) as! QuizCell
cell.questionLabel.text = question.text
// print(question.text)
return cell
}
}
It is also helpful if you have any idea of implementing this by alternative way.
Thanks.
How about you create a static array and store your data into that array.
when the button is tapped you can append it into that static array.
Create a new file. Just a basic "Swift file".
struct structName {
static var qArray: [String] = []
}
Then append data by:
structName.q.append()
Finally get your data trough:
structName.q[index]

realm selectedRowAtIndexPath using segue showing different results

it is my first time using segment control and realm. so currently I am using segue to perform segue to Add/EditVC for modification of data.
when segue performed and took data to Add/EditVC to variable selectedTransaction, I want as following data to to be filled accordingly
/* selectedTransaction print statement Results */
print("selectedTransaction = \(selectedTransaction!)")
selectedTransaction = Transaction {
categoryType = Category {
type = expense;
name = EXPENSE 3;
};
amount = 1000;
date = April 2;
}
amountTF.text = selectedTransaction.amount (done and correct)
categorySCoutlet.selectedSegmentIndex = selectedTransaction.categoryType.type (fail to show segmentindex at selectedTransaction.categoryType.type)
categoryTF.text = selectedTransaction.categoryType.name (name shown correctly, however will return nil if user did not RESELECT again)
I was expecting all data are shown as if it created.
However, I faced 2 issue in getting it done
SegmentControl selected index are always in 0 instead of selectedTransaction.categoryType.name (I want the segment control to be at the index which is as created)
categoryTF.text are showing correctly, but if I did not choose again and leave as it be. It will auto return back to nil in results when I pressed the saveButton. : I wish categoryTF.text will return as created and value will not change even if I did not touch it and clicked saveButton
In gif shown below, I chosen row2 as sample. and the result in Realm Browser showing as it is.
I only changed the amountTF.text information from 1200 to 2000, which in result realm browser will set the result of cateogoryType in segmentcontrol to "income" and category will return to nil
sample of the workflow
//Data Model
//MARK: - Transaction Category Section
enum CategoryType : String, CaseIterable {
case income = "income"
case expense = "expense"
init?(id : Int) {
if id < CategoryType.allCases.count {
self = CategoryType.allCases[id]
} else {
return nil
}
}
}
class Category : Object {
#objc dynamic var type : String = CategoryType.income.rawValue
#objc dynamic var name : String = ""
// let parentCategory = LinkingObjects(fromType: Transaction.self, property: "ofCategory")
convenience init(type:CategoryType, name: String) {
self.init()
self.type = type.rawValue
self.name = name
}
}
/* VC that should read and load all data to required place */
//edit
var selectedTransaction : Transaction!
#IBOutlet weak var amountTF: UITextField!
//PickerView for keyboard
lazy var pickerView : UIPickerView = UIPickerView()
//Segment Control
#IBOutlet weak var categorySCoutlet: UISegmentedControl!
#IBOutlet weak var categoryTF: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
amountTF.text! = selectedTransaction.amount
categoryTF.text! = selectedTransaction.categoryType!.name
setupPicker()
}
#IBAction func categoryTypeSC(_ sender: UISegmentedControl) {
guard let type = CategoryType(id: sender.selectedSegmentIndex) else {
fatalError("error")
}
currentCategories = categories.filter("type == %#", type.rawValue)
categoryTF.text = currentCategories.first?.name
pickerView.reloadAllComponents()
pickerView.selectRow(1, inComponent: 0, animated: true)
}
//MARK:- Add Transaction Btn
#IBAction func addTransButtonTapped(_ sender: UIButton) {
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesBegan(touches, with: event)
if touches.first?.view == view {
categoryTF.resignFirstResponder()
}
}
//MARK:- Picker Helper
func setupPicker() {
currentCategories = categories.filter("type == %#", CategoryType.income.rawValue)
categoryTF.inputView = pickerView
pickerView.delegate = self
pickerView.dataSource = self
categorySCoutlet.setTitle("Income", forSegmentAt: 0)
categorySCoutlet.setTitle("Expense", forSegmentAt: 1)
categorySCoutlet.addTarget(self, action: #selector(categoryTypeSC(_:)), for: .valueChanged)
}
You are calling tableView.deselectRow(at: indexPath, animated: false) in your tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) method.
This results in returning the incorrect indexPath in prepareForSegue.
You should either remove the deselectRow call from didSelectRowAtIndexPath method,
or you should create a property to hold the value of indexPath.
Something like this:
// somewhere in your class
var selectedIndexPath: IndexPath?
then
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let selectedRowForTrans : Transaction = getTransactions[indexPath.row]
selectedIndexPath = indexPath // set the value of selectedIndexPath
tableView.deselectRow(at: indexPath, animated: false)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if (segue.identifier == "editTrans") {
if let indexPath = selectedIndexPath { // check if there is a valid indexPath
let editTransVC = segue.destination as! AddTransactionTableViewController
let selectedRowForTrans : Transaction = getTransactions[indexPath.row]
editTransVC.selectedTransaction = selectedRowForTrans
}
}
}
Hope this helps

Not able to load data in segmented control tableview from Firestore database

I am trying to populate table view w.r.t the segmented control by getting data from Firestore database, but due to some reason I am not being able to do so, I am trying an example available online which has preset data, but here I am retrieving data from the Firestore database.
It is not giving any runtime error as well, simply not loading the data. Below is the screenshot of the view controller of the code. Kindly assist
class FirstSegementViewController: UIViewController {
#IBOutlet var segmentControl:UISegmentedControl!
#IBOutlet var tableView: UITableView!
var s1Post:[s1] = []
var s2Post:[s2] = []
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
retrieveAllPosts()
}
func retrieveAllPosts(){
let postsRef = Firestore.firestore().collection("posts").limit(to: 50)
postsRef.getDocuments { (snapshot, error) in
if let error = error {
print(error.localizedDescription)
} else {
if let snapshot = snapshot {
for document in snapshot.documents {
let data = document.data()
//self.postKey = document.documentID
let username = data["post_author_username"] as? String ?? ""
let postTitle = data["postTitle"] as? String ?? ""
let postcategory = data["postcategory"] as? String ?? ""
let postContent = data["postContent"] as? String ?? ""
let postAuthorProfilePicUrl = data["post_user_profile_pic_url"] as? String ?? ""
let postAuthorSpinnerC = data["post_author_spinnerC"] as? String
let newSourse = s1(_documentId: document.documentID, _username: username, _postTitle: postTitle, _postcategory: postcategory, _postContent: postContent, _postuserprofileImagUrl: postAuthorProfilePicUrl, _postAuthorSpinncerC: postAuthorSpinnerC)
self.s1Post.append(newSourse)
// print(self.postKey)
}
self.tableView.reloadData()
}
}
}
}
#IBAction func indexChanged(_ sender: UISegmentedControl) {
switch segmentControl.selectedSegmentIndex
{
case 0:
retrieveAllPosts()
// label1.text = "First Segment Selected"
case 1:
retrieveAllPosts()
// label1.text = "Second Segment Selected"
default:
break
}
//self.tableView.reloadData()
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
}
*/
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
}
*/
}
extension FirstSegementViewController: UITableViewDelegate, UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
var value = 0
switch segmentControl.selectedSegmentIndex{
case 0:
value = s1Post.count
break
case 1:
value = s2Post.count
break
default:
break
}
return value
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MyCell", for: indexPath) as! MyWsPostCell
switch segmentControl.selectedSegmentIndex{
case 0:
cell.s11 = s1Post[indexPath.row]
break
case 1:
cell.s21 = s2Post[indexPath.row]
break
default:
break
}
return cell
}
}
You seem to be setting value for self.s1Post only.

TextFields don't get updated with values in unwind function Swift

I have textfields that should get a value displayed once returning from a TableViewController where user selects a cell. I get that value in unwindfunction, but textfieldsdon't get updated. When printing the value it prints correctly on unwinding, so unwindshould be set correctly, but it just don't get displayed in it's textfield. I also tried prepare(for unwind:in TableViewControllerbut with same results. Can you see what I'm doing wrong?
As always many thanks.
unwind function:
#IBAction func unwindToDetailsVc(segue: UIStoryboardSegue) {
//Insert function to be run upon dismiss of VC2
print("unwindSegue triggered")
if let vc = segue.source as? CityTableViewController {
print("segue source is city vc : \(String(describing: vc.city!))")
self.cityTextField.text = vc.city
}
if let vc = segue.source as? RegionTableViewController {
print("segue source is region vc : \(String(describing: vc.region!))")
self.regionTextField.text = vc.region
}
if let vc = segue.source as? CountryTableViewController {
print("segue source is country vc : \(String(describing: vc.country!))")
self.countryTextField.text = vc.country
}
}
didSelect in TableView:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath) as! CityTableViewCell
self.city = cell.cityLabel.text ?? ""
performSegue(withIdentifier: "unwindSegue", sender: self)
// self.dismiss(animated: true, completion: nil)
}
prepare for unwind:
override func prepare(for unwind: UIStoryboardSegue, sender: Any?) {
if unwind.identifier == "unwindSegue" {
if let detailsVc = unwind.destination as? ShopDetailsTableViewController {
detailsVc.cityTextField.text! = city
}
}
}
textfield delegate function:
func textFieldDidBeginEditing(_ textField: UITextField) {
print("Editing textfield")
if textField.accessibilityIdentifier == "city" {
print("Editing city textfield")
performSegue(withIdentifier: "citySegue", sender: self)
} else if textField.accessibilityIdentifier == "region" {
print("Editing regio textfield")
performSegue(withIdentifier: "regionSegue", sender: self)
} else if textField.accessibilityIdentifier == "country" {
print("Editing country textfield")
performSegue(withIdentifier: "countrySegue", sender: self)
}
}
You can simply use a closure to solve this kind of problem statement,
class ViewController: UIViewController {
#IBOutlet weak var textField: UITextField!
#IBAction func openTableVC(_ sender: UIButton) {
if let controller = UIStoryboard.init(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "TableViewController") as? TableViewController {
controller.handler = {[weak self](city) in
DispatchQueue.main.async {
self?.textField.text = city
}
}
self.navigationController?.pushViewController(controller, animated: true)
}
}
}
class TableViewController: UITableViewController {
var handler: ((String)->())?
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let city = "Delhi"
self.handler?(city)
self.navigationController?.popViewController(animated: true)
}
}
The above code is generic and will work in every case from where you want to open TableViewController.
I finally found out what I was doing wrong, I was calling the functions loading from CoreDatauser details and displaying them in viewWillAppear. Once I moved them in saveButtonafter the saving to CoreDatafunction call, it all works as expected. Textfield get updated with select values from tableviews.
Many thank to #PGDev for sharing a more convenient way of coding this, without all the if elsestatements and unwinds. Great example of higher level coding.