Though I assigned value(self) to delegate/dataSource, reloadData doesn't work.
So, I set breakpoint, its dataSource hasn't the data.
How do I work reloadData? Here is my example code.
func getData(query: String) {
// ...(data processing part)
var parser: NSXMLParser! = NSXMLParser(data: data)
parser.delegate = self
parser.parse() // parsing works well.
self.testTableView.hidden = false // breakpoint 1
self.testTableView.dataSource = self
self.testTableView.delegate = self
self.testTableView.reloadData()
// breakpoint 2
insertTableWithConstraint() // set constraints
// init. dataSource
self.testTableView.dataSource = nil
}
I tried both "self.testTableView.~" and "testTableView.~", but It didn't work. Here is variable sets in my breakpoint
testTableView = (UITableView) 00000001360dee00 some = (UITableView) 0x00000001360dee00 ... _dataSource = (sunny.TestViewController *)0x135d34950 [0] (sunny.TestViewController) ...testDatas = (NSMutableArray) "4 values"
I append the my CellForRowAtIndex code.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell: UITableViewCell! = tableView.dequeueReusableCellWithIdentifier("Cell") as UITableViewCell
cell.textLabel.text = testDatas.objectAtIndex(indexPath.row).valueForKey("title") as NSString
cell.detailTextLabel?.text = testData.objectAtIndex(indexPath.row).valueForKey("roadAddress") as NSString
NSLog("cell.textLabel.text : \(cell.textLabel.text)") // It was not shown in exec.
NSLog("cell.detailTextLabel.text : \(cell.detailTextLabel?.text)") // It was not shown in exec.
return cell as UITableViewCell
}
I forgot to append the numberOfRowsInSection code. So I append it.
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return testDatas.count
}
1) You shouldn't call self.testTableView.dataSource = nil. If your app crashes without it, it probably means you're trying to access your data without first checking it is not empty.
2) I assume that your NSXMLParser is used to populate your UITableView rows. NSXMLParser works with a delegate mechanism, so you should call testTableView.reloadData() only when you're done parsing, not immediately like you're doing right now. A good place to call it would be in the parserDidEndDocument delegate function.
3) In your func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell function, check that indexPath corresponds to something accessible in your testDatas variable (which I assume is built during XML parsing). This might be why your app is crashing right now.
4) Also, be careful to appropriately set the cell count in the tableView(_ tableView: UITableView,
numberOfRowsInSection section: Int) -> Int delegate function (probably using testDatas.count).
First of all don't set, tableview's dataSource & delegate to nil, set them to self.
As you said your numberOfRowsInSection returns exact count of the datasource object. Then try this:
override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
let cell = tableView.dequeueReusableCellWithIdentifier("reuseIdentifier", forIndexPath: indexPath)
cell.textLabel.text = testDatas.objectAtIndex(indexPath.row).valueForKey("title") as NSString
return cell
}
Hope this helps.. :)
Related
i have the dictionary - dictTime: [Int:[Int]] and I'd like to show it in tableView in cell.
To show key in every cell - not a problem, but I'd like to show every element of value of dictionary in "own" UILabel, so I created [UILabel] and understand that count of UILabel in array must be equal count of elements in value of dictionary, but how to do it in func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell for showing for every row (row - it's key-[value])?
Assuming your dictionary is like [Int1: [Int2]], that means:
dictTime.allKeys will give you array of all Int1
dictTime[Int1] will give you respective [Int2]
Example:
var dictTime = [1: [1,2], 2: [2,3], 3: [3,4]]
For showing these in a tableView:
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dictTime.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("MyCell", forIndexPath: indexPath)
let keys = Array (dictTime.keys)
cell.textLabel?.text = String (keys[indexPath.row])
cell.detailTextLabel?.text = String (dictTime[indexPath.row])
return cell
}
In func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell call an other function and pass your dictionary value to that function for example [1,2,3] also pass your tbaleviewcell to that function. Now in that function run a loop on your dictionary array [1,2,3] and one by one UILabel into your tableviewcell programmatically.
I am not sure I understand the problem. If you want to have as many rows as dictionary entries, use the following:
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dictTime.count
}
If you want to have as many labels in your cell, as entries for each key in your dictionary, you need to implement a complicated solution.
I would suggest creating a "super cell" which has the maximum amount of labels, put them in a stach view, and hide them according to the number of entries.
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
}
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
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 am appending data from parse into an array, but when I try to load array in table view nothing shows up. The array is populated, but nothing is showing up. How do I fix this?
class View2: UIViewController, UITableViewDataSource, UITableViewDelegate{
var ret = [String]()
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return ret.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = table.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)
cell.textLabel?.text = ret[indexPath.row]
return cell
}
}
After set 'ret' value, you have to reload table.
In my case,
var ret = [String](){
didSet{
self.tableView.reloadData()
}
}
in my case I forgot to connect the UITableView datasource outlet to the ViewController.
Ensure your tableview is being reloaded after you receive the data. Use tableViewName.reloadData()
Add a call to reloadData() method of UITableView in the setter of your array.