On my storyboard is a Tab Bar Controller with two view controllers. The first view controller has a UITableView, and the second view controller is used to collect data which will be displayed in table view format on the first view controller.
For this, I have created four swift files:
TARISKTREATMENT.swift - contains the class TARISKTREATMENT that's linked to the first view controller (the one with the UITableView)
TAADDRISKTREATMENT.swift - contains the class TAADDRISKTREATMENT that's linked to the second view controller.
TREATMENTS.swift - Struct that's used to collect data entered on second view controller.
CUSTOMTREATMENTCELL.swift - UITableViewCell class for the custom cell.
The second view controller collects the data from the user perfectly, and when I run print commands, I can see that the data is actually in the struct.
For some reason, the code from TARISKTREATMENT.swift does not populate the custom cell.
What am I doing wrong here?
CODE: TARISKTREATMENT.swift (View controller 1 with UITableView - the one that's not working...)
import UIKit
class TARISKTREATMENT: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var TreatmentsTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
TreatmentsTableView.dataSource = self
TreatmentsTableView.delegate = self
TreatmentsTableView.reloadData()
}//END - viewDidLoad
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return TreatmentsManager.newTreatments.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let IndividualCell = TreatmentsTableView.dequeueReusableCellWithIdentifier("TreatmentCell", forIndexPath: indexPath) as! CUSTOMTREATMENTCELL
IndividualCell.outletLabel_TreatmentPackageName.text = TreatmentsManager.newTreatments[indexPath.row].varTreatmentPackageName
IndividualCell.outletLabel_TreatmentDescription.text = TreatmentsManager.newTreatments[indexPath.row].varTreatmentPackageDetail
IndividualCell.outletLabel_TreatmentResponsiblePerson.text = TreatmentsManager.newTreatments[indexPath.row].varTreatmentResponsiblePerson
IndividualCell.outletLabel_TreatmentDTGCompleted.text = String(TreatmentsManager.newTreatments[indexPath.row].varTreatmentDTGCompleted)
let varSelectPriorityPic = TreatmentsManager.newTreatments[indexPath.row].varTreatmentPriority
switch varSelectPriorityPic {
case "HIGH":
IndividualCell.outletImage_TreatmentPriority.image = imageTreatmentPriorityHigh
case "MEDIUM":
IndividualCell.outletImage_TreatmentPriority.image = imageTreatmentPriorityMedium
case "LOW":
IndividualCell.outletImage_TreatmentPriority.image = imageTreatmentPriorityLow
default:
break
}
return IndividualCell
}
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath){
if (editingStyle == UITableViewCellEditingStyle.Delete){
TreatmentsManager.newTreatments.removeAtIndex(indexPath.row)
TreatmentsTableView.reloadData()
}
}
}
CODE: TREATMENTS.swift
import UIKit
var TreatmentsManager: classTreatmentsManager = classTreatmentsManager()
struct structTreatment {
var varTreatmentPackageName : String
var varTreatmentPackageDetail : String
var varTreatmentResponsiblePerson : String
var varTreatmentPriority : String
var varTreatmentDTGCompleted : NSDate
}
class classTreatmentsManager: NSObject {
var newTreatments = [structTreatment]()
func funcAddTreatment(varTreatmentPackageName: String, varTreatmentPackageDetail: String, varTreatmentResponsiblePerson: String, varTreatmentPriority: String, varTreatmentDTGCompleted: NSDate){
newTreatments.append(structTreatment(varTreatmentPackageName: varTreatmentPackageName, varTreatmentPackageDetail: varTreatmentPackageDetail, varTreatmentResponsiblePerson: varTreatmentResponsiblePerson, varTreatmentPriority: varTreatmentPriority, varTreatmentDTGCompleted: varTreatmentDTGCompleted))
}
}
CODE: CUSTOMTREATMENTCELL.swift
import UIKit
class CUSTOMTREATMENTCELL: UITableViewCell {
#IBOutlet weak var outletImage_TreatmentPriority: UIImageView!
#IBOutlet weak var outletLabel_TreatmentPackageName: UILabel!
#IBOutlet weak var outletLabel_TreatmentDescription: UILabel!
#IBOutlet weak var outletLabel_TreatmentResponsiblePerson: UILabel!
#IBOutlet weak var outletLabel_TreatmentDTGCompleted: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
I've uploaded a small video to show what's (not) happening here.
Your assistance is appreciated - thanks!
Everything is fine in your code. What you miss is reloading the data :
override func viewWillAppear() {
super.viewWillAppear()
TreatmentsTableView.reloadData()
}
Related
I have been searching for some time now and have developed a massive headache trying to solve this problem. Basically, I would like to have a parent tableView mainTableView to contain a tableViewCell that includes a label and another tableView innerTableView. This problem is not as simple as I had hoped.
If there is a better way to implement what I want with different components, please let me know.
Otherwise, I have tried to simplify the code to its bare bones with simple data. Please assume I have correctly connected all my outlets properly. I have 3 swift files for this simplified version. ViewController.swift is the main VC that holds the mainTableView. MainTableViewCell.swift is the main cell that will hold a label and a tableView innerTableView in it. InnerTableViewCell is the final cell that will be associated with the innerTableView. In this cell, there is only a label. I have been successful in creating this first layer and the mainNameLabel.text shows up properly on the main storyboard. However, I have configured MainTableViewCell to the best of my knowledge and have come short to success. The innerTableView does not appear on the main storyboard.
Below, I will provide the code of each swift file:
ViewController.swift
//
// ViewController.swift
// NestedTableViews
//
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var mainTableView: UITableView!
//fake data
var arr = ["Hello", "Hi", "Whats up", "How's it going"]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
mainTableView.delegate = self
mainTableView.dataSource = self
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MainTableViewCell") as! MainTableViewCell
let word = arr[indexPath.row]
cell.mainNameLabel.text = word
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arr.count
}
}
MainTableViewCell.swift
//
// MainTableViewCell.swift
// NestedTableViews
//
import UIKit
class MainTableViewCell: UITableViewCell, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var mainNameLabel: UILabel!
#IBOutlet weak var innerTableView: UITableView!
var innerArr = ["How are you?", "How are you doing?", "What's the matter?"]
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
innerTableView.dataSource = self
innerTableView.delegate = self
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "InnerTableViewCell") as! InnerTableViewCell
let innerWord = innerArr[indexPath.row]
cell.innerNameLabel.text = innerWord
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return innerArr.count
}
}
InnerTableViewCell
//
// InnerTableViewCell.swift
// NestedTableViews
//
import UIKit
class InnerTableViewCell: UITableViewCell {
#IBOutlet weak var innerNameLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
Here is what the storyboard looks like in this current state:
What is it that I am doing wrong? I could ask 100 questions but regardless, I am still very stuck here. How do I get the nested tableView innerTableView to appear and with the proper data?
Thank you in advance
I have checked out the other posts but I'm not sure next steps here. Here's what I have currently. Do I need to add a tableView variable somewhere else? Connect something differently?
class LookbookPostViewController: UIViewController {
#IBOutlet weak var titleLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
titleLabel.text = postArray[myIndex].title
// Do any additional setup after loading the view.
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
#IBOutlet weak var tableView: UITableView!
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
return postArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "postViewCell", for: indexPath) as! LookbookPostViewCell
cell.postLabel.text = postArray[indexPath.row].title
print(postArray)
return cell
}
/
}
I then have this set up for my connections, but can't seem to get the Table View to recognize any data I'm trying to output.
I also have `class LookbookPostViewCell: UITableViewCell {
#IBOutlet weak var postLabel: UILabel!
}
`
I was able to solve this by changing:
class LookbookPostViewController: UIViewController
to
class LookbookPostViewController: UIViewController, UITableViewDelegate, UITableViewDataSource
and then right clicking and making the delegate and datasource, the View Controller, like in this photo here.
I make app with news feed which has to open on other ViewController. But can't pass data via segue.
Viewcontroller with newsfeed
class SecondViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var titlenews = ""
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "newsfeedCell", for: indexPath) as! NewsFeedCell
cell.newsfeed_title.text = self.news?[indexPath.item].headline
cell.newsfeed_topic.text = self.news?[indexPath.item].topic
cell.newsfeed_time.text = timetime(from: (self.news?[indexPath.item].time)!)
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("tableview")
let vc = storyboard?.instantiateViewController(withIdentifier: "newsBody") as? NewsBody
vc?.labeltext = (self.news?[indexPath.item].headline)!
print((self.news?[indexPath.item].headline)!)
self.navigationController?.pushViewController(vc!, animated: true)
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.news!.count
} //number of rows
#IBOutlet weak var tableview: UITableView!
var news: [Newsfeed]? = []
override func viewDidLoad() {
super.viewDidLoad()
getJSON()
}
func getJSON(){
///Here all do right
}
}
Viewcontroller which has to receive data from news feed
class NewsBody: UIViewController {
#IBOutlet weak var testLabel: UILabel!
var labeltext = ""
override func viewDidLoad() {
super.viewDidLoad()
print(labeltext)
testLabel.text = labeltext
}
}
print(labeltext) shows that NewsBody receive empty value or nothing.
But print((self.news?[indexPath.item].headline)!) inside of SecondViewController shows that I try to push proper value.
What I do incorrect between this actions? What wrong with segue and pass of data?
It seems that instantiateViewController(withIdentifier: "newsBody") triggers view load under the hood. It should not (in theory) but it might do just that in your case.
This means that viewDidLoad() will be called before the vc?.labeltext = (self.news?[indexPath.item].headline)! is executed.
I'd recommend you to do the following.
class NewsBody: UIViewController {
#IBOutlet weak var testLabel: UILabel!
var labeltext: String? {
didSet { updateUI() }
}
override func viewDidLoad() {
super.viewDidLoad()
updateUI()
}
private func updateUI() {
testLabel.text = labeltext
}
}
This way if you set the labeltext property after the view is loaded, it will still trigger the UI update. And if you set the labeltext property before the view is loaded, as soon as viewDidLoad() is called.
BTW, you are not using segues here. But even if you do, you can easily use the same method as I proposed, because it allows you to stop thinking about whether property updates will update the UI.
Also please note that I made the property optional. It will allow you to avoid force casts and just do
vc?.labeltext = self.news?[indexPath.item].headline
UILabel.text is also an optional String property, so they will play well together.
I followed this post and put inside my custom UITableViewCell SummaryCell the UITableView detailTableView
But now I'm getting the error:
Type 'SummaryCell` does not conform to protocol `UITableViewDataSource`
If anyone could tell what I'm doing wrong & how to fix this I would greatly appreciate it!
Code for SummmaryCell:
class SummaryCell: UITableViewCell, UITableViewDelegate, UITableViewDataSource{
#IBOutlet weak var dayOfWeek: UILabel!
#IBOutlet weak var totalSpent: UILabel!
#IBOutlet weak var totalSpentView: UIView!
#IBOutlet weak var heightOfMainView: NSLayoutConstraint!
#IBOutlet weak var detailTableView: UITableView!
var data: [Expense] = [Expense]()
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
detailTableView.delegate = self
detailTableView.dataSource = self
//create data array
let calendar = NSCalendar.currentCalendar()
let dateComponents = NSDateComponents()
dateComponents.day = 14
dateComponents.month = 5
dateComponents.year = 2015
dateComponents.hour = 19
dateComponents.minute = 30
let date = calendar.dateFromComponents(dateComponents)
data = [Expense(amountSpent: 60), Expense(amountSpent: 20, date: date!), Expense(amountSpent: 40, date: date!, function: Function.Social, category: Category.Fun, subcategory: Subcategory.Events)]
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data.count
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("detailCell") as! DetailTableViewCell
return cell
}
}
What my summaryCell looks like :
It is generally considered bad practice to make your UITableViewCell class conform to the UITableViewDataSource and UITableViewDelegate protocols.
I would strongly recommend to set these both to a view controller containing a table view and could imagine that this probably causes your error.
To follow up to return false's answer, a cell should only be responsible for its own views. It shouldn't have a property for its tableView. It's generally a bad design for the cell to need to know or control anything about a view in its superview hierarchy.
Also if you consider the unlikely possibility that the reusable cell that happened to be the delegate were to be deinitialized, the tableView would no longer have a delegate.
Sorry if this kind of question isn't welcome here but I'd appreciate the help. I have a fully functioning table now set up but I did it using the TableViewController in storyboard. I now realize I cannot change the size of the view using that item and it doesn't fit well on the screen as is. I understand I need to use a regular view controller and add the table view manually. I can do that but I spent hours getting the table to work properly and I'm afraid to break it. Can someone walk me through transitioning between the two?
Here is the storyboard
Here is the view controller code
import UIKit
class CharacterTableViewController: UITableViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet var characterTableView: UITableView!
var characterArray: [Character] = [Character]()
override func viewDidLoad() {
super.viewDidLoad()
self.characterSetup()
}
func characterSetup() {
var admiralSwiggins = Character(name: "Admiral Swiggins", abilities: "Stun, Blind, Shield, Damage Over Time, Area of Effect", characterImage: "admiral.png")
var ayla = Character(name: "Ayla", abilities: "Area of Effect, Damage Over Time, Fly, Lifesteal, Shield, Slow", characterImage: "ayla.png")
var clunk = Character(name: "Clunk", abilities: "Lifesteal, Area of effect, Ensnare, Slow, Launch String", characterImage: "clunk.png")
characterArray.append(admiralSwiggins)
characterArray.append(ayla)
characterArray.append(clunk)
}
override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
var cell:CharacterTableViewCell = self.tableView.dequeueReusableCellWithIdentifier("Cell") as CharacterTableViewCell
if indexPath.row % 2 == 0 {
cell.backgroundColor = UIColor.redColor()
}
let character = characterArray[indexPath.row]
cell.nameLabel.text = character.name
cell.abilityLabel.text = character.abilities
cell.characterImage.image = UIImage(named: character.characterImage)
return cell
}
override func tableView(tableView: UITableView!, didSelectRowAtIndexPath indexPath: NSIndexPath!) {
}
}
And here is the cell
import UIKit
class CharacterTableViewCell: UITableViewCell {
#IBOutlet var nameLabel: UILabel!
#IBOutlet var abilityLabel: UILabel!
#IBOutlet var characterImage: UIImageView!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}