Passing data between a table view cell and a view controller [duplicate] - ios

This question already has answers here:
Passing data between view controllers
(45 answers)
Closed 2 years ago.
Right now I have a table view and another view controller. I would like to use the didSelectRowAt function to show a detailed view of the tableview cell on the new view controller. How would I pass data from the the tableview cell to a new view controller? Here is what I currently have.
This is the code for my main view controller.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var searchBar: UISearchBar!
#IBOutlet weak var tableView: UITableView!
struct data {
var sectionTitle = String()
var rowTitles = [String]()
}
var dataArray = [data(sectionTitle: "section 1", rowTitles: ["row 1", "row 2", "row 3"]),
data(sectionTitle: "section 2", rowTitles: ["row 1", "row 2"]),
data(sectionTitle: "section 3", rowTitles: ["row 1"])
]
var searchArray = [(sectionTitle: String, rowTitles: [String])]()
var searching = false
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
}
}
extension ViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if searching {
return searchArray[section].rowTitles.count
} else {
return dataArray[section].rowTitles.count
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "searchCell")
if searching {
cell?.textLabel?.text = self.searchArray[indexPath.section].rowTitles[indexPath.row]
} else {
cell?.textLabel?.text = self.dataArray[indexPath.section].rowTitles[indexPath.row]
}
return cell!
}
func numberOfSections(in tableView: UITableView) -> Int {
return dataArray.count
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
if searching {
return searchArray.count
} else {
return dataArray[section].sectionTitle
}
}
}
This is the code for my second view controller so far.
import UIKit
class secondViewController: UIViewController {
#IBOulet weak var nameLabel: UILabel!
#IBOulet weak var descriptionLabel: UILabel!
#IBOulet weak var imageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func visitButtonTapped(_ sender: Any) {
}
}
Here is my current Storyboard.

Create a model in your ViewController
import UIKit
class secondViewController: UIViewController {
#IBOulet weak var nameLabel: UILabel!
#IBOulet weak var descriptionLabel: UILabel!
#IBOulet weak var imageView: UIImageView!
var titleOfItem : String
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func visitButtonTapped(_ sender: Any) {
}
}
In your tableView delegate
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// Init you secondVC
secondVC.titleOfItem = searchArray[indexPath.section].rowTitles[indexPath.row]
// pushToVC / Present
}

Related

tableview doesn't show anything?

I made sure that my cell identifier was correct I'm not too sure what the problem is. I've been rereading the code on this viewController and I'm not sure if I'm missing something or if there's a specific reason why my tableview isn't loading.
import UIKit
import JGProgressHUD
class BasketViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
tableView.tableFooterView = footerView
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
//MARK: TO DO CHECK IF USER IS LOGGED IN
loadBasketFromFirestore()
}
//MARK: VARS
var basket : basket?
var allItems : [Item] = []
var purchaseItemID : [String] = [] //holds id of items you want to purchase
var hud = JGProgressHUD(style: .dark)
//MARK: IBOUTLETS
#IBOutlet weak var totalPriceLabel: UILabel!
#IBOutlet weak var totalItemsInBasket: UILabel!
#IBOutlet weak var checkOutButton: UIButton!
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var footerView: UIView!
//MARK: IBACTIONS
#IBAction func checkOutButtonTapped(_ sender: Any) {}
//something is wrong with
//MARK: DOWNLOAD BASKET
private func loadBasketFromFirestore(){
//MARK: CHANGE 1234 TO A USER ID STRING
downloadBasketFromFirestore("1234") { (basket) in
self.basket = basket
self.getBasketItems()
}
}
private func getBasketItems(){
if (basket != nil) {
print("getting items")
downloadItems(_withIDS: basket!.itemID) { (allItems) in
self.allItems = allItems
self.tableView.reloadData()
}
} else { print("basket is nil")}
}
}
extension BasketViewController : UITableViewDataSource , UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return allItems.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "basketCell", for: indexPath) as! ITEMTableViewCell
cell.generateCellForITEMS(item: allItems[indexPath.row])
return cell
}
}

Why is table view displayed but cells is not?

I'm builded view like this:
and constrains:
Here is a code:
Main controller
class SelectTagsViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var selectedTagsTableView: UITableView! //added table view
let allTags: [String] = ["Qwerty", "IT", "Manic", "VR", "WishHook", "Books", "Programing", "Aplication", "Something", "Fly", "Swift", "Earth", "Orbit", "Mars", "Summer", "Monkey", "AR", "Space"]
var selectedTags: [String] = ["Qwerty", "IT", "Manic", "VR"]
override func viewDidLoad() {
super.viewDidLoad()
selectedTagsTableView.tableFooterView = UIView(frame: CGRect.zero)
selectedTagsTableView.backgroundColor = .lightGray
selectedTagsTableView.register(SelectedTagCell.self, forCellReuseIdentifier: "SelectedTagCell")
}
}
Extension for tableview
extension SelectTagsViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let lable = selectedTags[indexPath.row]
let cell = selectedTagsTableView.dequeueReusableCell(withIdentifier: "SelectedTagCell") as! SelectedTagCell
cell.tagNameLabel.text = lable
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return selectedTags.count
}
}
And class for cells
class SelectedTagCell: UITableViewCell {
#IBOutlet weak var tagNameLabel: UILabel!
#IBOutlet weak var removeTagButton: UIButton!
#IBAction func removeTagButtonTapped(_ sender: Any) {
}
}
But cells aren't displayed:
All code are in one file, and all classes and identifiers are connected to components.
What did I miss?
On the recommendation of #Adrian, I added delegate and datasource below and all now work.
selectedTagsTableView.delegate = self
selectedTagsTableView.dataSource = self
And fixed problem with nil value, removed code below:
selectedTagsTableView.register(SelectedTagCell.self, forCellReuseIdentifier: "SelectedTagCell")

Deleting a UITableView cell in a specific section

There is a task. Each cell contains a button by clicking which you want to delete this cell. The problem is that sections are used to delineate the entire list by category. The data I take from Realm DB. removal must occur under two conditions because the name is repeated, so you need to consider the name from the label and the name of the section. I will be very grateful for the sample code with comments.
import UIKit
import RealmSwift
class PurchesViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var purchesTableView: UITableView!
let manage = ManagerData()
override func viewDidLoad() {
super.viewDidLoad()
purchesTableView.delegate = self
purchesTableView.dataSource = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
purchesTableView.reloadData()
}
func numberOfSections(in tableView: UITableView) -> Int {
return manage.loadPurchases().0.count
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return manage.loadPurchases().0[section]
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return manage.loadPurchases().1[section].count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "purchesCell", for: indexPath) as! CustomPurchesTableViewCell
cell.productLabel.text = manage.loadPurchases().1[indexPath.section][indexPath.row]
cell.weightProductLabel.text = manage.loadPurchases().2[indexPath.section][indexPath.row]
cell.weightNameLabel.text = manage.loadPurchases().3[indexPath.section][indexPath.row]
// cell.boughtButton.addTarget(self, action: #selector(removeProduct), for: .touchUpInside)
return cell
}
}
class CustomPurchesTableViewCell: UITableViewCell {
#IBOutlet weak var boughtButton: UIButton!
#IBOutlet weak var productLabel: UILabel!
#IBOutlet weak var weightProductLabel: UILabel!
#IBOutlet weak var weightNameLabel: UILabel!
#IBAction func removePurches(_ sender: Any) {
print("remove")
}
}
method for get data
func loadPurchases() -> ([String], Array<Array<String>>, Array<Array<String>>, Array<Array<String>>) {
var sections: [String] = []
var product = Array<Array<String>>()
var weight = Array<Array<String>>()
var nameWeight = Array<Array<String>>()
let realm = try! Realm()
let data = realm.objects(Purches.self)
for item in data {
if sections.contains(item.nameDish) == false {
sections.append(item.nameDish)
}
}
for a in sections {
var productArr = Array<String>()
var weightArr = Array<String>()
var nameWeightArr = Array<String>()
for prod in data {
if a == prod.nameDish {
productArr.append(prod.product)
weightArr.append(prod.weight)
nameWeightArr.append(prod.nameWeigh)
}
}
product.append(productArr)
weight.append(weightArr)
nameWeight.append(nameWeightArr)
}
return (sections, product, weight, nameWeight)
}
Index path you will get in cell class
Index path have two property section and row for table view
Now you can create on more method in Controller class and assign to a variable to every cell or you can use editAction provided by table view for delete
in order to get number section and row you need create IBOutlet in custom cell and on ViewController class is created addTarget for your button.
Example code at the bottom.
import UIKit
import RealmSwift
class PurchesViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var purchesTableView: UITableView!
let manage = ManagerData()
//... more code ...
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "purchesCell", for: indexPath) as! CustomPurchesTableViewCell
cell.productLabel.text = manage.loadPurchases().1[indexPath.section][indexPath.row]
cell.weightProductLabel.text = manage.loadPurchases().2[indexPath.section][indexPath.row]
cell.weightNameLabel.text = manage.loadPurchases().3[indexPath.section][indexPath.row]
cell.boughtButton.addTarget(self, action: #selector(removePurches(_:)), for: .touchUpInside)
return cell
}
#objc func removePurches(_ sender: UIButton) {
let position: CGPoint = sender.convert(CGPoint.zero, to: purchesTableView)
let indexPath: IndexPath! = self.purchesTableView.indexPathForRow(at: position)
print("indexPath.row is = \(indexPath.row) && indexPath.section is = \(indexPath.section)")
purchesTableView.deleteRows(at: [indexPath], with: .fade)
}
}
and custom class CustomPurchesTableViewCell for cell
class CustomPurchesTableViewCell: UITableViewCell {
#IBOutlet weak var boughtButton: UIButton! // you button for press
#IBOutlet weak var productLabel: UILabel!
#IBOutlet weak var weightProductLabel: UILabel!
#IBOutlet weak var weightNameLabel: UILabel!
}

How to make an image correspond to each object in a NSMutableArray - xcode 7.3

Hi there I am trying to make a simple tableview directory with an image, a label and some info.
I am using a NSMutableArray with objects to establish teacher names and now I would like to add an image in the cell that corresponds to the label.
I am looking for any suggestions. I have not found any up-to-date tutorials.
Here is my current code:
import UIKit
class DirectoryViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var backButton2: UIButton!
#IBOutlet weak var directoryTableView: UITableView!
// #IBOutlet weak var nameLabel: NSLayoutConstraint!
//let searchController = UISearchController(searchResultsController: nil)
var directoryObjects: NSMutableArray! = NSMutableArray()
// var names = ["Teacher 1", "Teacher 2", "Teacher 3"]
override func viewDidLoad() {
super.viewDidLoad()
self.directoryObjects.addObject("Teacher 1")
self.directoryObjects.addObject("Teacher 2")
self.directoryObjects.addObject("Teacher 3")
self.directoryTableView.reloadData()
directoryTableView.delegate = self
directoryTableView.dataSource = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
//Mark - tableview
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return directoryObjects.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let directoryCell = tableView.dequeueReusableCellWithIdentifier("directoryCell", forIndexPath: indexPath) as! DirectoryTableViewCell
directoryCell.nameLabel.text = self.directoryObjects.objectAtIndex(indexPath.row) as? String
// directoryCell.directoryLabel.text = names[indexPath.row]
return directoryCell
}
#IBAction func backButton2Tapped(sender: AnyObject) {
self.dismissViewControllerAnimated(true, completion: nil)
}
}
You need to use a struct
struct Object {
var teacherString: String!
var image: UIImage!
}
Then your array is
var theArray = [
Object(teacherString: "Teacher 1", image: UIImage(name: "yourImage")),
Object(teacherString: "Teacher 2", image: UIImage(name: "yourImage")),
Object(teacherString: "Teacher 3", image: UIImage(name: "yourImage"))]
Sorry if some of my code is bad. I wrote this in notepad on windows.

Separating UITableViewDelegate and UITableViewDataSource Causes No Data to Show

My ViewController is getting way too big because of all the methods needed for UITableViewDelegate and UITableViewDataSource, so I refactored my code to a different file, but now the data doesn't show up anymore...
Here's my current implementation:
In MyViewController.swift
class SomeView: UIViewController {
#IBOutlet weak var myTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
myDataSourceClass(tableView: myTableView)
}
}
In MyNewDataSourceClass.swift
class myDataSourceClass: UITableViewDelegate, UITableViewDataSource {
let stuff = [1, 2, 3]
init(tableView: UITableView) {
super.init()
tableView.delegate = self
tableView.dataSource = self
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell")
cell?.textLabel?.text = "please show up"
return cell!
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.stuff.count
}
}
Any help would be very appreciated. Thank you!
// you need to reload table after setting delegate and datasource
class SomeView: UIViewController {
#IBOutlet weak var myTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
myDataSourceClass(tableView: myTableView)
myTableView.reloadData()
}
}

Resources