My Situation: I want to save Data from an Array at Index X in an Row on Index X in Section 1.
My code is:
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return setObjectToPass.count
}
override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return "Section \(section)"
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cellEmpty = tableView.dequeueReusableCellWithIdentifier("LabelCell")
var countCell = 0
while countCell < setObjectToPass.count {
let indexPaths = NSIndexPath(forRow: countCell, inSection: 0)
let cell = tableView.dequeueReusableCellWithIdentifier( "LabelCell", forIndexPath: indexPaths)
cell.textLabel!.text = String(setObjectToPass[countCell])
print(cell)
countCell+=1
return cell
}
My Problem is that only the first index of the Array SetObjectToPass is passed and set into the Cell.text
while counter < fetchResult?.count {
let set = fetchResult![counter]
counter+=1;
setObject.append((set.reps?.integerValue)!)
}
You are implementing the tableView(_:cellForRowAtIndexPath:indexPath:) method wrongly.
Remember, every delegate method in UITableViewDelegate is like asking you a question. For example, numberOfSectionsInTableView(_:) is like asking you "How many sections do you want in your table view?". You answer the question by returning a value.
tableView(_:cellForRowAtIndexPath:indexPath:) is similar. It asks a question as well. It asks "What should I display in the table row at this index path?"
In your code, it seems like you want to give multiple answers - looping through the array and attempting to return multiple times. But it doesn't work that way, you can only give one answer.
In the first iteration of the while loop, the execution hits return and stopped. That's why you only see the first table cell.
Thus, you should change your code so that it only gives one answer to the question:
let cell = tableView.dequeueReusableCellWithIdentifier("LabalCell")
cell.textLabel?.text = String(setObjectsToPass[indexPath.row])
return cell
Don't use the loop in cellForRowAtIndexPath delegate method. cellForRowAtIndexPath method call each row based upon numberOfRowsInSection count rows, simply use indexpath.row, Use this code,
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cellEmpty = tableView.dequeueReusableCellWithIdentifier("LabelCell")
let cell = tableView.dequeueReusableCellWithIdentifier( "LabelCell", forIndexPath: indexPaths)
cell.textLabel!.text = setObjectToPass[indexPath.row] as? String
return cell
}
hope its helpful
Related
I have a UITableView, which as an example contains dynamic cells I create based on the content of an array.
I can populate these using the count of the array and indexPath to render a cell per item. I am happy with this and it works well.
I would like to try now and create static cells programmatically.
Immediately however I am stumped, how do I create this? I'm currently overriding numberOfRowsInSection and cellForRowAt indexPath as follows:
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellID", for: indexPath) as! ProfileCell
cell.rowContent.text = items[indexPath.row]
return cell
}
I suspect my first mistake is dequeueReusableCell and would really appreciate any help.
If I understood your question, you want to add a static cell in a tableView that contains dynamic cells.
If that is the case, you could hardcode this, increasing the return value here:
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count+1
}
In this case, you want to add just one static cell.
In cellForRowAtIndexPath, you should define where you want to add this static cell. In the example below, it would be the first cell:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0 {
//should change StaticCell to the static cell class you want to use.
let cell = tableView.dequeueReusableCell(withIdentifier: "staticCell", for: indexPath) as! StaticCell
//hardcore attributes here, like cell.rowContent.text = "A text"
return cell
}
let row = indexPath.row-1
let cell = tableView.dequeueReusableCell(withIdentifier: "cellID", for: indexPath) as! ProfileCell
cell.rowContent.text = items[row]
return cell
}
It's basically about shifting the items[row] according to the number of static cells you want to use.
I'm not sure if that will work, but would be my first guess (according to my experience about that). Try this and tell me if it worked :)
How to prevent crashes when an array is empty and you make a request from a UITableView or UIPickerView?
My current method is to always initialize my arrays before using them with dummy data but I'm not really happy with this method since sometimes the dummy data is not needed and even-worse, sometimes it doesn't even make sense to show the data, in fact most of the time what I want is to show an empty table if there is no data.
For instance if I will be retrieving an array from NSUserDefaults to be used in a UITableView I usually initialize it in the AppDelegate as follow...
AppDelegate.swift:
NSUserDefaults.standardUserDefaults().registerDefaults([
keyMyAarray:["Dummy Data"]// initializing array
])
SomeViewController:
var myArray = read content from NSUserDefaults...
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
fun tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return myArray.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = UITableViewCell()
cell.textLabel.text = myArray[indexPath.row]
return cell
}
Again, how can I safely use an un-initialized array in a UITableView and show an empty table?
There is no need to put "dummy data" in your array. You can just initilize an empty array. like below
var myArray = [String]()
And in numberOfRowsInSection return myArray.count. If count is zero, cellForRowAtIndexPath will not be called and you are safe to go.
3 empty rows by default.
var myArray:Array<String>? = ...
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
fun tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return myArray?.count ?? 3
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = UITableViewCell()
if let arrayStrings = myArray, arrayStrings.count > indexPath.row {
cell.textLabel.text = arrayStrings[indexPath.row]
}
return cell
}
I try to display a simple cell with one label and an add item button. I can't get it to display correctly. I spent a lot of time but I can't find the solution.
This is the result:
There is no add item button and no correct row. I have just two items in coredata.
This is my code:
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return items.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)
let data = items[indexPath.row] as Item
cell.textLabel?.text = data.body
return cell
}
What are the problems? Can anyone help me to display add item button, correct row count, and customize height of the cell correctly? Thanks in advanced.
First lets return the correct number of rows unto the table view.
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return cellContent.count
}
Next lets get it to output unto the prototype cells.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell")
cell.textLabel?.text = cellContent[indexPath.row]
return cell
}
Also lets call the unto the view controller the following so that it can run properly.
ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource
One last thing, your prototype's cell has the same identifier as the one in your code. In my code I would make sure that the identifier in the prototype cell is "Cell" since I called it in UITableViewCell(...reuseIdentifier: "Cell").
View picture to see where to add the identifier in your storyboard
I'm making an social networking app with a NodeJS backend. The app gets its data from the MongoDB associated with the Node app with a GET request. I have figured out how to parse the JSON returned from the GET request as a native Dictionary, but can not find a clean way of turning each of the objects in the dictionary into a TableViewCell in my TableView. The Dictionary is basically this:
["username":"personWhoPosted", "taggedUsername":"personWhoIsTagged", "imageURL":"http://urlofimageposted.com"]
I need each of those to fill different values/labels inside the TableViewCells
If you want to utilize indexPath, I would keep a copy of array of dictionary keys.
func fetchData() {
// ....
// Your own method to get the dictionary from json
let self.userDict = ["username":"personWhoPosted", "taggedUsername":"personWhoIsTagged", "imageURL":"http://urlofimageposted.com"]
// Keep a copy of dictionary key
let self.userDictKeyCopy = Array(self.userDict.keys)
// You may want to sort it
self.userDictKeyCopy.sort({$0 < $1})
}
// Table view delegates
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.userDictKeyCopy.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(kCustomCell) as! CustomTableCell
// Assuming one section only
let title = self.userDictKeyCopy[indexPath.row] // e.g. "taggedUsername"
cell.titleLabel = title
cell.contentLabel = self.userDict[title] // e.g. "personWhoIsTagged"
return cell
}
let yourDict = ["username":"personWhoPosted", "taggedUsername":"personWhoIsTagged", "imageURL":"http://urlofimageposted.com"]
Number of rows in section
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return yourDict.count
}
Cell for row at
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
let key = Array(yourDict)[indexPath.row].key
let value = yourDict[key]
return cell
}
I've been scouring the web trying to figure this out but can't find a clear answer. Here's what's going on:
I've created a UITableViewController called MainTableViewController and I have two custom cells that live in that: "FirstCell" and "SecondCell". They both use that naming convention as their reuse identifiers. I've also created cell class files for each: "FirstTableViewCell" and "SecondTableViewCell" that I've assigned each cell accordingly. I've also created IBOutlets for all the objects in the cells within each UITableViewCell class file.
So in MainTableViewController I have no problem getting "FirstCell" loaded. I'm doing that like so:
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("FirstCell") as! FirstTableViewCell
cell.friendfirstnameLabel.text = "Michael"
cell.friendImageView.image = UIImage(named: "mikepic")
return cell
}
How do I now call "SecondCell"? I know I will need to change my return to 2. But then how do I change the dequeueReusableCellWithIdentifier and cellForRowAtIndexPath code to make both my cells work? "Second Cell" has a radically different layout with different objects defined.
try this
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return yourArrayCount
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if indexPath.row % 2 == 0 {
let cell = tableView.dequeueReusableCellWithIdentifier("FirstCell") as! FirstTableViewCell
cell.friendfirstnameLabel.text = "Michael"
cell.friendImageView.image = UIImage(named: "mikepic")
return cell
} else {
let cell = tableView.dequeueReusableCellWithIdentifier("SecondCell") as! SecondTableViewCell
cell.friendfirstnameLabel.text = "Michael"
cell.friendImageView.image = UIImage(named: "mikepic")
return cell
}
}
You just need to deque your second cell with the reuse identifier assigned. This is completely on your requirements when you want to use first and when second.
You should simply change the parameter value you send to dequeueReusableCellWithIdentifier based on [indexPath row]. If it's 0, use "firstCell" and if it's 1, use "secondCell" and create a cell for the matching object type.
here i see you have static text to show in the cell view. Usually we have NSArray of data to populate the data in tableview and we define the count in umberOfRowsInSection method
so it will be very easy if you know what data you want to display in which cell like that you can easily use If statement for selecting your desire table cellview
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arrayCount
}
after checking count you can do this by if statement
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
NSUInteger row = [indexPath row];
if [yourArray objectAtIndex:row] =="Michael" {
let cell = tableView.dequeueReusableCellWithIdentifier("FirstCell") as! FirstTableViewCell
cell.friendfirstnameLabel.text = "Michael"
cell.friendImageView.image = UIImage(named: "mikepic")
return cell
} else {
let cell = tableView.dequeueReusableCellWithIdentifier("SecondCell") as! SecondTableViewCell
cell.friendfirstnameLabel.text = “Unknown"
cell.friendImageView.image = UIImage(named: "mikepic")
return cell
}
}