Edited:
I'm trying to insert two arrays into one tableview with two cell labels. But not really sure how I can convert it all and make it work. Here is my code so far.
In the top of the main ViewController (Where the tableView is)
class ScoreBoardViewController: UIViewController, UITableViewDelegate, UITableViewDataSource
var countedArray: [String] = []
var nameArray: [String] = []
#IBOutlet weak var tableView: UITableView!
var list: [pointsTxt] = []
Additional info: I've added the self.tableView.delegate = self
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return list.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let listPath = list[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: "pointsCell") as! ScoreCell
cell.setCell(list: listPath)
return cell
}
func createArray() -> [pointsTxt]
{
var tempTxt: [pointsTxt] = []
let txt = pointsTxt(person: nameArray, points: countedArray)
tempTxt.append(txt)
self.list = tempTxt
self.tableView.reloadData()
return list
}
Class for the cell
class ScoreCell: UITableViewCell
{
#IBOutlet weak var person: UILabel!
#IBOutlet weak var points: UILabel!
func setCell(list: pointsTxt)
{
person.text = list.person
points.text = list.points
}
}
ERROR: Cannot assign value of type '[String]' to type 'String?'
Class for the array
class pointsTxt
{
var person: [String] = []
var points: [String] = []
init(person: [String] = [], points: [String] = [])
{
self.person = person
self.points = points
}
}
I hope you understand what I need. Thanks in advance!
You have to follow the following steps when creating a custom tableViewCell:
Subclass UITableViewCell
Add your Outlets to that subclass
register your subclass to the TableView
code Example for your rowAtIndexPath function:
.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row < nameArray.count {
// load from customerDetails array
let names = nameArray[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: "listCell", for: indexPath) as! UITableViewSubclassCell
cell.person.text = names
return cell
} else {
// load from customerDetails2 array
let points = countedArray[indexPath.row - nameArray.count]
let cell = tableView.dequeueReusableCell(withIdentifier: "listCell", for: indexPath) as! UITableViewSubclassCell
cell.person.text = points
return cell
}
}
Related
import UIKit
class ViewController: UIViewController,UITableViewDelegate, UITableViewDataSource, pass {
var array = [String]()
#IBOutlet weak var tblView: UITableView!
#IBOutlet weak var btnPush: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return array.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell", for: indexPath) as!TableViewCell
cell.lblName.text = array[indexPath.row]
cell.lblFullName.text = array[indexPath.row]
cell.lblRollno.text = array[indexPath.row]
cell.lblClass.text = array[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 200
}
#IBAction func btnPush(_ sender: UIButton) {
let vc = storyboard?.instantiateViewController(withIdentifier: "SecondVC") as!SecondVC
vc.mac = self
self.navigationController?.pushViewController(vc, animated: true)
}
func Datapass(Name: String, FullName Address: String, Rollno: String, Class: String) {
self.array.append(Name)
self.array.append(Address)
self.array.append(Rollno)
self.array.append(Class)
tblView.reloadData()
}
}
import UIKit
protocol pass {
func Datapass(Name:String, FullName:String, Rollno:String, Class:String)
}
class SecondVC: UIViewController {
#IBOutlet weak var textFldName: UITextField!
#IBOutlet weak var txtFldFullName: UITextField!
#IBOutlet weak var txtFldRollno: UITextField!
#IBOutlet weak var txtFldClass: UITextField!
var mac:pass?
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func btnAdd(sender: UIButton) {
mac?.Datapass(Name: textFldName.text!, FullName: txtFldFullName.text!, Rollno: txtFldRollno.text!, Class: txtFldClass.text!)
self.navigationController?.popViewController(animated: true)
}
}
your adding data to your array the wrong way. your adding 4 parameter
and your array will be like this:
array: 0:name|1:Address|2:Rollno|3:Class
and when your reading this from table every time you map this:
cell.lblName.text = array[0]
cell.lblFullName.text = array[0]
cell.lblRollno.text = array[0]
cell.lblClass.text = array[0]
every time table only reads one element of array for 4 times! you are not changing indexpath.row , it will change it's number after loading 1 cell.
the right way to do this is code below:
struct DbModel{
var name:String
var address:String
var rollno:String
var `class`:String
}
var array :[DbModel] = []
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell", for: indexPath) as! TableViewCell
let model = array[indexPath.row]
cell.lblName.text = model.name
cell.lblFullName.text = model.address
cell.lblRollno.text = model.rollno
cell.lblClass.text = model.class
return cell
}
func Datapass(Name: String, FullName Address: String, Rollno: String, Class: String) {
let model = DbModel(name: Name, address: Address, rollno: Rollno, class: Class)
self.array.append(model)
tblView.reloadData()
}
I have created a new Datasource for my dynamic UITable "NewUser List" Embed nn static view cell. my problem with var dataSource = NewUserDataSource(newStakeholders: self.newStakeholders)
give me this error
Value of type '(CreateCompanyTableViewController) -> () ->
CreateCompanyTableViewController' has no member 'newStakeholders'
class CreateCompanyTableViewController: UITableViewController {
#IBOutlet weak var lblNumberOfUser: UILabel!
var newStakeholders: [ReadOrganizationStakeholder] = []
#IBOutlet weak var companyUsersTableView: UITableView!
var dataSource = NewUserDataSource(newStakeholders: self.newStakeholders)
override func viewDidLoad() {
super.viewDidLoad()
lblNumberOfUser.text = "\(newStakeholders.count) Users"
companyUsersTableView.dataSource = dataSource
companyUsersTableView.delegate = dataSource as! UITableViewDelegate
}
}
class NewUserDataSource: NSObject, UITableViewDataSource {
// We keep this public and mutable, to enable our data
// source to be updated as new data comes in.
var newStakeholders: [ReadOrganizationStakeholder]
init(newStakeholders: [ReadOrganizationStakeholder]) {
self.newStakeholders = newStakeholders
}
func tableView(_ tableView: UITableView,
numberOfRowsInSection section: Int) -> Int {
return newStakeholders.count
}
func tableView(_ tableView: UITableView,
cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let stakeholders = newStakeholders[indexPath.row]
let cell = tableView.dequeueReusableCell(
withIdentifier: "newUserTableViewCell",
for: indexPath
) as! NewUserTableViewCell
cell.lblUsername.text = stakeholders.fullName
cell.lblEmail.text = stakeholders.emailAddress
return cell
}
}
In that line you are using self outside of a method.
Move that line to viewDidLoad() or to a new init method.
I am trying to have each choice in my UITableView to have its own unique set of data. For example, in my table view I have a list of states, then when I click on a state, I want each state to have a list of cities that correspond specifically to it. I have attached my code below, the code is strictly for the UITableView only.
I'm new to Xcode/Swift.
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var tableView: UITableView!
let textCellIdentifier = "TextCell"
var states = ["Illinois", "Indiana", "Kentucky", "Michigan", "Ohio", "Pennsylvania", "Wisconsin"]
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 states.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: textCellIdentifier, for: indexPath)
let row = indexPath.row
cell.textLabel?.text = states[row]
return cell
}
private func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: IndexPath) {
tableView.deselectRow(at: indexPath as IndexPath, animated: true)
let row = indexPath.row
print(states[row])
}
You can construct array model like this
struct MainItem {
var name:String
var cities:[String]
init(name:String,cities:[String]) {
self.name = name
self.cities = cities
}
}
//
let item1 = MainItem(name:"Illinois",cities:["city1","city2"])
let item2 = MainItem(name:"Indiana",cities:["city3","city4"])
var states = [item1,item2]
//
in cellForRowAt
cell.textLabel?.text = states[row].name
//
in didSelectRowAtIndexPath
let cities = states[row].cities
I recently did this by creating separate classes for each of the delegates I wanted to have. Move all of the table functions into a new class and create an instance of the class in your new controller. In the view did load function set the delegate for the first table. Whenever you switch tables with a button or whatever, do nextTable.delegate = xxxx.
View controller code:
let eventLogTableController = EventLogTableController()
let missedEventLogController = MissedEventTableController()
#IBOutlet weak var emptyTableLabel: UILabel!
#IBOutlet weak var missedEventLog: UITableView!
override func viewDidLoad() {
self.eventLog.delegate = eventLogTableController
The issue is as follows: I have a tableview with a custom cell. That cell contains a label and a UISwitch. I have set the label.text value to an array, but the UISwitch is getting reused.
Example: If I toggle the switch in the first row, the 5th row gets enabled, and if I scroll it continues to reuse the cells and cause issue.
Video : https://vimeo.com/247906440
View Controller:
class ViewController: UIViewController {
let array = ["One","Two","Three","Four","Five","Six","Seven","Eight","Nine","Ten"]
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
}
}
extension ViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CustomTableViewCell
cell.label.text = array[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return array.count
}
}
Custom Cell:
class CustomTableViewCell: UITableViewCell {
#IBOutlet weak var label: UILabel!
#IBOutlet weak var toggleSwitch: UISwitch!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
}
I realize there isn't code trying to store this data because I haven't been successful. Any ideas would be helpful. The project currently uses the MVC model and I believe that is the answer but just need some help.
I would recommend to you create cellViewModel class and keep array of it instead of just string. You cellViewModel may look like,
class CellViewModel {
let title: String
var isOn: Bool
init(withText text: String, isOn: Bool = false /* you can keep is at by default false*/) {
self.title = text
self.isOn = isOn
}
Now, build array of CellViewModel
let array =["One","Two","Three","Four","Five","Six","Seven","Eight","Nine","Ten"]
var cellViewModels = [CellViewModel]()
for text in array {
let cellViewModel = CellViewModel(withText: text)
cellViewModels.append(cellViewModel)
}
Change your tableVieDelegate function to :
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CustomTableViewCell
let cellViewModel = cellViewModels[indexPath.row]
cell.label.text = cellViewModel.title
cell.toggleSwitch.isOn = cellViewModel.isOn
cell.delegate = self
return cell
}
In you Custom Cell class, add this protocol :
protocol CellActionDelegate: class {
func didChangeSwitchStateOnCell(_ cell: CustomTableViewCell)
}
Add delegate as property in your custom cell,
weak var delegate: CellActionDelegate?
Also, on switch change, add this line,
delegate?.didChangeSwitchStateOnCell(self)
Now, your viewController should register and listen to this delegate :
I have added line cellForRowAtIndexPath to register for delegates. To listen this delegate, add this function in your VC.
func didChangeSwitchStateOnCell(_ cell: CustomTableViewCell) {
let indexPath = tableView.indexPath(for: cell)
cellViewModels[indexPath.row].isOn = cell.toggleSwitch.isOn
}
start creating a model for example :
struct item {
var id: String
var name: String
var isActivated: Bool
init(id: String, name: String, isActivated: Bool) {
self.id = id
self.name = name
self.isActivated = isActivated
}
}
let item1 = item(id: "1", name: "One", isActivated: false)
let item2 = ...........
let item3 = ...........
let items [item1, item2, item3]
With that you can trigger the boolean if it's activated or not.
You will also have to take a look to https://developer.apple.com/documentation/uikit/uitableviewcell/1623223-prepareforreuse I think.
I have a UITableViewController with three labels. The first two are from the .textLabel and .detailTextLabel, I have added a third label into the storyboard and hooked it up to a UITableViewCell file. When I run, the app crashes unless the label is set as an optional with a "?", but nothing is still presented in the table. If it does not have the optional sign, it crashes and I get a response saying "unexpectedly found nil while unwrapping an optional value". The other two .textLabel and .detailTextLabel work fine. I would appreciate any help!
Here is my TableViewController File,
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.groupscores.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier(cellidentifier) as? ScoresPageCell
if (cell != nil) {
cell = ScoresPageCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: cellidentifier)
}
let groupscorelist: PFObject = self.groupscores.objectAtIndex(indexPath.row) as! PFObject
var scores: AnyObject = groupscorelist.objectForKey("Score")!
var user: AnyObject = groupscorelist.objectForKey("User")!
var info: AnyObject = groupscorelist.objectForKey("Info")!
cell!.textLabel?.text = "\(scores)"
cell?.detailTextLabel?.text = "\(user)"
cell!.UserNameCellLabel?.text = "\(info)"
return cell!
}
And my UITableViewCell File,
class ScoresPageCell: UITableViewCell {
#IBOutlet var UserNameCellLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
}
}
Follow this my friend:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier(cellidentifier, forIndexPath: indexPath) as! ScoresPageCell
let groupscorelist = self.groupscores[indexPath.row]
var scores = groupscorelist["Score"] as! String // cast it to String if they are string.
var user = groupscorelist["User"] as! String
var info = groupscorelist["Info"] as! String
cell!.text1?.text = scores
cell?.text2?.text = user
cell!.UserNameCellLabel?.text = info
return cell
}
class ScoresPageCell: UITableViewCell {
#IBOutlet weak var text1: UILabel!
#IBOutlet weak var text2: UILabel!
#IBOutlet weak var UserNameCellLabel: UILabel!
}