Is it possible to give UITableViewCells each a unique ViewController? - ios

To expand, I have a UITableView of two cells, and I want to give each of the cells, when tapped, their own unique view controller (as their functions will be different). I have scoured this website, as well as Google and could not quite find an answer. Here's the set up of my UITableView:
class ViewController: UITableViewController {
let functions = ["Rule of 72","Future Value", "Simple Interest"]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = self.functions[indexPath.row]
return cell
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 3
}
}
Ultimately, the idea is to build an app that allows for the calculation of certain financial and economic equations. These equations will require different inputs and outputs (Rule of 72 will only need one UITextField, whereas Future Value will need four UITextField's).

I would suggest creating a enum confirming to CaseIterable. Also implement the func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath).
class ViewController: UITableViewController {
enum OptionTypes: CaseIterable {
case ruleOf72
case futureValue
case simpleInterest
var description: String {
switch self {
case .ruleOf72: return "Rule of 72"
case .futureValue: return "Future Value"
case .simpleInterest: return "Simple Interest"
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
let item = OptionTypes.allCases[indexPath.row]
cell.textLabel?.text = item.description
return cell
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return OptionTypes.allCases.count
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let item = OptionTypes.allCases[indexPath.row]
switch item {
case .ruleOf72:
navigateToRuleOf72ViewController()
case .futureValue:
navigateToFutureValueViewController()
case .simpleInterest:
navigateToSimpleInterestViewController()
}
}
private func navigateToRuleOf72ViewController() {}
private func navigateToFutureValueViewController() {}
private func navigateToSimpleInterestViewController() {}
}

Related

Can not find indexpath in scope in tableview

import UIKit
private let reuseableIdentifier = "cell"
class TableViewController: UITableViewController{
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(UITableViewCell.self,forCellReuseIdentifier: reuseableIdentifier)
}
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 0
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let cell = tableView.dequeueReusableCell(withIdentifier: reuseableIdentifier, for: indexPath )
return cell
}
}
So this is my code but at the dequereuseableCell for: indexPath it showing error like can not find indexPath in scope.
You need to return a number greater than 0 in the method of numberOfSections and numberOfRowsInSection
You need to return a cell in the method of cellForRowAt indexPath
import UIKit
private let reuseableIdentifier = "cell"
class TableViewController: UITableViewController{
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(UITableViewCell.self,forCellReuseIdentifier: reuseableIdentifier)
}
override func numberOfSections(in tableView: UITableView) -> Int {
// return number of sections
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// return number of rows in sections
return 10
}
// add method
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: reuseableIdentifier, for: indexPath )
return cell
}
}
You are still missing one method:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// dequeue your cell here
}
the method you use should read:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
//return the number of elements to show here
}
documentation
tutorial

How to place table cells different way when orientation is horizontal in swift

sorry to bother programmers again,
I'm writing a simple app, and one of the view controllers has a table.
I'm new to all of this so I found some videos and programmed the table. This is the code above classes (honestly I still don't understand what it does):
extension ViewController3: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("you tapped me!")
}
}
extension ViewController3: UITableViewDataSource
{
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return names.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = names[indexPath.row]
return cell
}
}
And this is the class:
class ViewController3: UIViewController {
#IBOutlet var tView: UITableView!
let names = [
"Alex",
"Andrew",
"Mary",
"Henry"]
override func viewDidLoad() {
super.viewDidLoad()
tView.delegate = self
tView.dataSource = self
}
}
It works fine but the task is when the orientation of the phone/simulator is horizontal, to SHOW the table not in one row, but 2x2 (like 4 cells - 2 rows, 2 lines). I don't know where to search it, I found some tips about placing elements in this way but it's not for a table. And I don't know whether its possible or not. Thank you all in advance

How do I drag table view rows in Swift but only in a single section

I have a table view with two sections and want to allow rows to be re-ordered for just one of the sections. I've found a lot of information about this, but can't restrict it to the single section. Here is my entire code - it's very simple, with one table view. I've put this together from various sources - thanks to those who have contributed to this topic.
To reproduce this in Storyboard, add a table view to the view controller, add some constraints, set number of Prototype Cells to 1, and set its Identifier to 'cell'.
The table view has two sections - 'Fruit' and 'Flowers'. Press and hold on any cell allows that cell to be moved, so this part works ok.
I want to restrict it so that I can only move in the first section.
Also, if I'm dragging a cell and move it from one section to another, it gives an error and the program crashes. I'd like it just to reject the move and send the cell back to its original position.
Thanks for any help. Ian
import UIKit
import MobileCoreServices
var fruitList = ["Orange", "Banana", "Apple", "Blueberry", "Mango"]
var flowerList = ["Rose", "Dahlia", "Hydrangea"]
// this all works
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, UITableViewDragDelegate, UITableViewDropDelegate {
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.dragInteractionEnabled = true
tableView.dragDelegate = self
tableView.dropDelegate = self
tableView.dragInteractionEnabled = true
}
func numberOfSections(in tableView: UITableView) -> Int {
return 2
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return UITableView.automaticDimension
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
if section == 0 {
return "Fruit"
} else {
return "Flowers"
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0 {
return fruitList.count
} else {
return flowerList.count
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
if indexPath.section == 0 {
cell.textLabel?.text = fruitList[indexPath.row]
} else {
cell.textLabel?.text = flowerList[indexPath.row]
}
return cell
}
func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
}
func tableView(_ tableView: UITableView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] {
var string: String
if indexPath.section == 0 {
string = fruitList[indexPath.row]
} else {
string = flowerList[indexPath.row]
}
guard let data = string.data(using: .utf8) else { return [] }
let itemProvider = NSItemProvider(item: data as NSData, typeIdentifier: kUTTypePlainText as String)
return [UIDragItem(itemProvider: itemProvider)]
}
func tableView(_ tableView: UITableView, performDropWith coordinator: UITableViewDropCoordinator) {
}
}
Just in case anyone finds their way here, thanks to the link #Paulw11 has provided, this is the extra bit of code needed. Replace
func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
}
with
func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
let string = fruitList[sourceIndexPath.row]
fruitList.remove(at: sourceIndexPath.row)
fruitList.insert(string, at: destinationIndexPath.row)
}
Obviously this is just a simple example program, but I've now adapted this code to a complex situation and it works perfectly.

numberOfSectionsInTableView not working

import UIKit
class exploreViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var searchBar: UISearchBar!
#IBOutlet weak var exploreTableView: UITableView!
var CELLHEIGHT = 200
var SECTIONHEADER = "SECTIONHEADER"
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
exploreTableView.delegate = self
exploreTableView.dataSource = self
exploreTableView.register(UINib(nibName: "answerCell", bundle: nil), forCellReuseIdentifier: "cell1")
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 2
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return SECTIONHEADER
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 2
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = self.exploreTableView.dequeueReusableCell(withIdentifier: "cell1", for: indexPath) as! answerCell
cell.name.text = "222222"
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return CGFloat(CELLHEIGHT)
}
}
My numberOfSectionsInTableView is never called and I can't get 2 sections.
From your code, I believe you are using Swift3. Then, the following are delegate and datasource methods for UITableView in Swift3
func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 0
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath)
// Configure the cell...
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
}
As you can see, your numberOfSections function's syntax is wrong.That is the reason.
This is actually due to access level resolution. When we don't specify the "public" ourselves, the compiler resolves it as to be some privately implemented function and even warns that it nearly matches a public function. If one ignores this then it neglects this function and rather calls the default implementation. Hope this helps someone.
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}

variable cell is never mutated

When I take var type variable then Xcode show warning
variable is never mutated
If I take let type variable then don't show any result!
import UIKit
class ViewController: UIViewController,UITableViewDataSource{
let people = [
("Pankaj","Dhaka"),
("Asish","Madaripur"),
("Anup","Narail")
]
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return "People"
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return people.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
let (personName , personLocation) = people[indexPath.row]
cell.textLabel?.text = personName
cell.textLabel?.text = personLocation
return cell
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
}
You cannot use a table view cell initialized with the default initializer UITableViewCell()
Reuse the cell, add an identifier (e.g. PeopleCell) in Interface Builder.
let cell = tableView.dequeueReusableCell(withIdentifier: "PeopleCell", for: indexPath)
And make sure that datasource and delegate of the table view are connected in Interface Builder, too.

Resources