Load TableView cell before/on ViewDidLoad? - swift

Currently I have a tableview that loads cells when I scroll down (scrollview). Is it possible to load and populate all cells on viewDidLoad. I would like to assign data to a cell before it can be viewed. I have tried using self.tableView.reloadData() but not successful.

If you don't want to use UITableView's cell reusing concept, then create all the UITableViewCells beforehand in viewDidLoad and store them in an array.
Example:
class ViewController: UIViewController, UITableViewDataSource
{
var arr = [UITableViewCell]()
override func viewDidLoad()
{
super.viewDidLoad()
//Create your custom cells here and add them to array
let cell1 = UITableViewCell()
let cell2 = UITableViewCell()
arr.append(cell1)
arr.append(cell2)
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return arr.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
return arr[indexPath.row]
}
}

Related

How to add table view cell with a button inside of another table view cell?

I am trying to make a to-do list app and I am having trouble trying to add subtasks to my main to-do tasks. I have a button inside each table view cell, when this button is pressed I want it to add another table view cell that I can type and save a "subtask" on.
//set up tableView row amount
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return taskData.count
}
//set up what is in the tableView row
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//This is for a main task
let cell = tableView.dequeueReusableCell(withIdentifier: "TaskCell", for: indexPath) as! CustomTableViewCell
cell.label.text = taskData[indexPath.row]
return cell
}
Use delegates to pass data from cells to your ViewController, and reload the tableView.
CustomTableViewCell:
protocol CustomTableViewCellDelegate: class {
func customTableViewCellButtonClicked(_ cell: CustomTableViewCell)
}
class CustomTableViewCell: UITableViewCell {
weak var delegate: CustomTableViewCellDelegate?
func buttonClicked() {
self.delegate?.customTableViewCellButtonClicked(self)
}
}
ViewController:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TaskCell", for: indexPath) as! CustomTableViewCell
cell.label.text = taskData[indexPath.row]
cell.delegate = self
return cell
}
func customTableViewCellButtonClicked(_ cell: CustomTableViewCell) {
// add the task you need from that cell to your tasks list.
taskData.append(....)
//reload your tableView
self.tableView.reloadData()
}

How to expand tableview cell on click on button which is located outside the cell in the tableview?

There is a tableview cell and there is a more button which is located on the tableview not in the cell so I want that when the project run it show only five user data in the tableview cell and other user data is show when the user click on the more button(which is located out side the cell) how do I achieved this?
Thanks for help
You can find the prototype cell image
//Mark:TableViewDelegate
extension MembersViewController:UITableViewDelegate,UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return imgarray.count
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tblView.dequeueReusableCell(withIdentifier: "membTableCell", for: indexPath) as! membTableCell
cell.profiletabImg.image = imgarray[indexPath.row]
cell.namelbl.text = names[indexPath.row]
cell.positionlbl.text = "Ceo of code with color"
return cell
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 40
}
#IBAction func morebutton(sender:UIButton){
}
}
The tableview expands automatically if you add data to the array and call the tableview.reloadData() function.
From the Apple's Doc -
"Call this method to reload all the data that is used to construct the table, including cells, section headers and footers, index arrays, and so on. For efficiency, the table view redisplays only those rows that are visible. It adjusts offsets if the table shrinks as a result of the reload. The table view’s delegate or data source calls this method when it wants the table view to completely reload its data. It should not be called in the methods that insert or delete rows, especially within an animation block implemented with calls to beginUpdates() and endUpdates()."
#IBAction func moreBtnPressed(_ sender: Any) {
tableviewArray.append("Append your array with remaining items")
tableview.reloadData()
}
Return 5 in numberOfRowsInSection method if more button is not tapped.
When more button is tapped reload the tableview and return imgarray.count in numberOfRowsInSection method.
class TableViewController: UITableViewController {
var dataArr = [String]()
var expanded = false
override func viewDidLoad() {
super.viewDidLoad()
dataArr = (1..<25).map({ String($0) })
self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "\(dataArr.count - 5) more", style: .plain, target: self, action: #selector(morebutton(_:)))
}
#objc func morebutton(_ sender: UIBarButtonItem) {
self.navigationItem.rightBarButtonItem = nil
expanded = true
tableView.reloadData()
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if !expanded && !dataArr.isEmpty {
return 5
} else {
return dataArr.count
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier") ?? UITableViewCell(style: .default, reuseIdentifier: "reuseIdentifier")
cell.textLabel?.text = dataArr[indexPath.row]
return cell
}
}

UITABLE view sections with different prototype cells in each section

I have a table view with different sections and for each section it has different prototype cells. I have created the prototype cell in storyboard but I could not make more than one cell in cellForRowAtIndexPath. I have attached the whole code for reference.
This is my storyboard design
This is the final output screen which it should look like
import UIKit
class PlacePeopleViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var friendlistTableView: UITableView!
var sectionHead = ["Friends", "Others"]
override func viewDidLoad() {
super.viewDidLoad()
friendlistTableView.delegate = self
friendlistTableView.dataSource = self
// Do any additional setup after loading the view.
}
// MARK: - tableview datasource & delegate
func numberOfSections(in tableView: UITableView) -> Int {
return sectionHead.count
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return self.sectionHead[section]
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0 {
return 5
}else {
return 10
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell1") as! RecentVizzTableViewCell
cell.placeName.text = "poland"
cell.placeAddress.text = "Simon Albania"
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 79
}
func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return 15
}
}
Note : You can do this using only one cell. just hide/show the connect Button by checking some condition.
If you want to use different cells for different sections, inside your cellForRowAt indexPath method return your cells based on your section like below .
switch indexPath.section {
case 0:
let cell = tableView.dequeueReusableCell(withIdentifier: "cell1") as! RecentVizzTableViewCellOne
return cell
default:
let defaultcell = tableView.dequeueReusableCell(withIdentifier: "defaultcell") as! RecentVizzTableViewCellDefatult
return defaultcell
}
hope this will help to you. good luck.

Connect Prototype Cells to View Controller [Swift 4]

I am new to programming and currently working on a newsfeed like app. I had a normal Table view up and running fine, but want to try it now with a costume cell type. So I created one and thought connecting the labels the usual way would be perfectly fine, but I was wrong. So I am wondering how I can let my Text label connect to my view controller, so I can use my custom cell.
class ViewController: BaseViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet var newsfeedTableView: UITableView!
var ref: DatabaseReference!
var posts = [String]()
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return (posts.count)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: UITableViewCell.CellStyle.default, reuseIdentifier: "cell")
//here is where I need the custom label to get the posts
cell.textLabel?.text = posts[indexPath.row]
cell.textLabel?.font = UIFont.boldSystemFont(ofSize: 18.0)
return cell
}
}
Create subclass of UITableViewCell and connect IBOutlets to this class
class YourCell: UITableViewCell {
#IBOutlet weak var customLabel: UILabel!
...
}
don't forget to set class of your prototype cell in storyboard:
then in cellForRowAt data source method downcast your dequeued cell as YourCell
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! YourCell
then you have access to YourCell outlets
cell.customLabel.text = "SomeText"
...
I'm assuming that you are using Storyboard.
First of all, you should understand that there is little difference when you use own custom table cell. In that case, in the method "cellForRowAtIndexPath", after dequeue your cell, you just have to typecast table cell like 'as! YourCustomTableCellClass'. After this line, you can access each property of this class.
First, design your table cell on Storyboard whatever you want.
Now, make a subclass of UITableViewCell and assign this class to your prototype custom cell which you have designed on Storyboard. Also, don't forget to set "reuse identifier in Storyboard table cell.
Then connect your outlets with custom cell class from Storyboard.
Now you can use code like this:
class YourTableCellClass: UITableViewCell {
// I'm using these outlets as a sample, but you have to connect them from Storyboard.
var leftTextLabel: UILabel!
var rightTextLabel: UILabel!
}
class YourTableController: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
// MARK: - TableView Delegate & DataSource
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1 // return your number of rows here...
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 100 // return the height for the row here.....or you can set height from Storyboard if you have fix height of all rows.
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CellIdentifier", for: indexPath) as! YourTableCellClass
cell.leftTextLabel.text = "Text" // Set text here....
cell.rightTextLabel.text = "Text" // Set text here....
return cell
}
}

how to implement segue from uitableviewcell to another tableviewcell

I have two view controller with tableviewcell and in both of them I can add items.
What I want to implement is that when I add items in the first tableviewcell lets say I add (item one , item two) and press on (item one).
I want to sugue to the second tableviewcell and add data.
BUT I want the data in the second tableviewcell to save separately,
that means, now if I press on (item one) I should see the data that I added
but if I press on (item two) it should be empty and I can add data later.
I have saved the data for the two tableviewcell in coredata.
I don't use segues or coredata in this solution, but the solution will fix what you need to some extent at least.
class vc1: UIViewController, UITableViewDelegate, UITableViewDataSource {
let tableView = UITableView()
let options: [Int] = [1,2]
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return options.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
return UITableViewCell()
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let vc = vc2()
//Not sure where to put the setup to be honest
//option 1:
vc.setupTableView(forCell: indexPath.item)
present(vc, animated: true) {
//option 2:
vc.setupTableView(forCell: indexPath.item)
}
}
}
class vc2: UIViewController, UITableViewDelegate, UITableViewDataSource {
let tableView = UITableView()
var selectedCell: Int!
//Having an nested array in an array will solve this custom "page" you are looking for
let results: [[String]] = [["test1", "test2"], ["test3", "test4"]]
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
}
func setupTableView(forCell cell: Int) {
selectedCell = cell
tableView.reloadData()
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return results[selectedCell].count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
cell.textLabel = results[selectedCell][indexPath.item]
return UITableViewCell()
}
}