UITableView cell duplicates - ios

I'm working on my first Swift app, and stuck on a bug forever. When adding a new entry to the coredata, everything goes fine the first time. However, with additional items, the previously added item is duplicated in the table.
The data is not duplicated, only the cell. When the app is reloaded, the cells are displayed correctly.
Here's the code that populates the cells:
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
if let fetchedSections: AnyObject = fetchedResultController.sections as AnyObject? {
return fetchedSections.count
} else {
return 0
}
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if let fetchedSections: AnyObject = fetchedResultController.sections as AnyObject? {
return fetchedSections[section].numberOfObjects
} else {
return 0
}
}
func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
let lookup = sortedArray[indexPath.row] as! NSManagedObjectID
let spot = spotsDict[lookup] as! Spots
let cell = tableView.dequeueReusableCellWithIdentifier("SpotCell", forIndexPath:indexPath) as! SpotCell
println(sortedArray)
println(spot)
cell.spotLabel.text = spot.title
cell.spotPhoto.image = self.imagesDict[lookup]
cell.distanceLabel.text = self.distanceStringDict[lookup] as NSString! as String
cell.spotPhoto.layer.cornerRadius = 4
cell.spotPhoto.clipsToBounds = true
return cell
}

Please replace your code
let lookup = sortedArray[indexPath.row] as! NSManagedObjectID
with below code in cellForRowAtIndexPath method.
let lookup = sortedArray[indexPath.section] as! NSManagedObjectID

The root of the problem was in my sorting method.. simplified the code a lot, and sorted with sortDescriptors instead.

Related

UITableViewCells won't load index is out of range

I am trying to load some data from CloudKit to populate a tableview with custom cells and I am having difficulty getting the data to appear.
When I define the number of rows as the count of the CKRecord array the tableview shows up, but with nothing loaded into them. They are just spaced out correctly for the images to be in there. Also, when I set breakpoints at let record = matches[indexPath.row] it won't trigger.
However, if I change the return matches.count to an actual number, the project crashes at let record = matches[indexPath.row]
with the error that the index is out of range. I want to keep the number of rows as the count for the record array, but that is the only change that will actually execute the override function that calls the tableview cell.
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return matches.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Card", for: indexPath) as! MatchTableViewCell
let record = matches[indexPath.row]
if let img = record.value(forKey: "Picture") as? CKAsset {
cell.profileimg.image = UIImage(contentsOfFile: img.fileURL.path)
}
return cell
}
Any advice is appreciated
Update- here is where I load the model
func loadModel() {
let totalMatch = (defaults.object(forKey: "passedmatch") as! [String] )
let predicateMatch = NSPredicate(format: "not (UserID IN %#)", totalMatch )
ProfilesbyLocation = defaults.object(forKey: "Location") as! String
let query = CKQuery(recordType: ProfilesbyLocation , predicate: predicateMatch )
publicData.perform(query, inZoneWith: nil,completionHandler: ({results, error in
print("loading")
if (error != nil) {
let nsError = error! as NSError
print(nsError.localizedDescription)
print ("error")
} else {
if results!.count > 0 {
DispatchQueue.main.async() {
self.tableView.reloadData()
self.refresh.endRefreshing()
print("refreshed")
}
}
}
}
)
)}
It sounds like you are not calling
tableview.reloadData()
after your asynchronous data comes in. Leave numberOfRowsInSection as it is and make sure when your network request comes back you are reloading. That should do it.
If you received your data from background thread(or queue), please make sure when you update your UI elements under the main thread(or queue). Try this:
DispatchQueue.main.async {
tableView.reloadData()
}
This solved my problem.
First, disconnect the Delegate/DataSource of the TableView from the Interface Builder refer this image. When you have finally prepared your data that is matches array then add this.
`DispatchQueue.main.async {
tableView.dataSource = self
tableView.delegate = self
tableView.reloadData
}`
Hope this helps.
It looks like your matches is incorrect. Before you call func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int)
, you should check your matches.
If you are still not sure about that. You can init your matches with string literals and have a try.

Setting one parse object of type array to a tableView

I know that I can query for, lets say, users that have emailVerified equal to true and present them into a tableView, but I was having trouble getting a single Parse object of type array into a tableView. I couldn't find anything online about this specific problem, but after putting a few answers together, I got it to work my answer is below for those also having trouble with this.
Here is what I found based on my question. I have an object in Parse called "my_classes" that is of type array. I want to get the items from the array into a tableView.
1) Create a variable: var myClassesResults : NSMutableArray = []
2) Create the function or place the code where necessary:
func getUserData() {
if PFUser.currentUser()!.objectForKey("my_classes") != nil {
let classes = PFUser.currentUser()!.objectForKey("my_classes")!
myClassesResults = classes as! NSMutableArray
self.noClasses = false
self.tableView.reloadData()
} else {
self.noClasses = true
self.tableView.reloadData()
}
}
3) tableView functions:
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.myClassesResults.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)
cell.textLabel!.text = myClassesResults[indexPath.row] as? String
return cell
}

Custom cells repeating

I have an app that has a tableview embedded in a ViewController and whenever I navigate to another ViewController and navigate back to the table view, the cells repeat when I scroll. Does anyone have any advice on how to prevent this? The current code for the tableview is :
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return marathonRaces.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let singleCell: marathonTableViewCell = tableView.dequeueReusableCellWithIdentifier("marathonCell") as! marathonTableViewCell
singleCell.marathonName.text = marathonRaces[indexPath.row]
singleCell.entry.text = "\(entryNumber[indexPath.row])"
singleCell.entries.text = "\(entires[indexPath.row])"
singleCell.length.text = "\(length[indexPath.row])"
return singleCell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let indexPath = self.marathonsTableView.indexPathForSelectedRow!
let currentCell = marathonsTableView.cellForRowAtIndexPath(indexPath) as! marathonTableViewCell
let marathonEvents = currentCell.marathonName.text
self.performSegueWithIdentifier("marathonDetail", sender: self)
}
I am using swift, xcode7, and parse as my backend
the only relevant code within viewDidAppear would be :
var query = PFQuery(className: “Marathons")
query.orderByAscending("end")
query.findObjectsInBackgroundWithBlock { (marathons, error:NSError?) -> Void in
if(error == nil ){
//success
for marathon in marathons! {
self.marathonRaces
.append(marathon[“marathonName"] as! String)
self.entry.append(marathon[“entryNumber"] as! Int)
self.entries.append(marathon[“entries"] as! Int)
self.length.append(marathon[“length"] as! Int)
}
self.marathonsTableView.reloadData()
}else {
print(error)
}
}
The problem is in your viewDidAppear method. Every time the controller appears you fetch data from background, append them to your arrays and reload the tableview. Move the code for fetching data to viewDidLoad for example and "repeating" should be gone.
Have you checked to see if the datasource marathonRaces is gaining more entries?
You may be adding more entries on each back navigation, if so either do not add them or remove all entries prior to adding them.

tableView not loading data from parse

I have a function called loadData
func loadData(){
feedData.removeAllObjects()
var findFeedData:PFQuery = PFQuery(className: "userQuotes")
findFeedData.findObjectsInBackgroundWithBlock{
(objects:[AnyObject]?, error:NSError?)->Void in
if error == nil{
if let objs = objects{
for object in objs{
let quote:PFObject = object as! PFObject
self.feedData.addObject(quote)
}
let array:NSArray = self.feedData.reverseObjectEnumerator().allObjects
self.feedData = NSMutableArray(array: array)
self.tableView.reloadData()
}
}
}
}
and then in the cellForRowAtIndexPath I actually get the data and display it. I self.loadData() in the viewDidLoad function.
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell:QuoteTableViewCell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! QuoteTableViewCell
let quote:PFObject = self.feedData.objectAtIndex(indexPath.row) as! PFObject
cell.contentTextView.text = quote.objectForKey("content") as! String
// Configure the cell...
return cell
}
I am getting no compiler errors and everything seems to be working. The content gets pushed to parse but it doesn't load with these functions. All that runs is an empty table view cells When it should be displaying content from Parse. I feel I am missing something simple logically here... I am a beginner so pardon any silly mistakes. I am following a tutorial but that is a bit outdated.
If you are using a mutable array, you will need to initialize it before adding in objects.
You are changing UI on an asynchronous thread.
The call to parse is async. When this call completes you are reloading your table view.
You should instead dequeu your UI change to the main thread
dispatch_async(dispatch_get_main_queue()) {
self.tableView.reloadData()
}
Verify these methods:
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1 //or more if you want
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.feedData.count
}

UI TableView not returning data

I have a table view, where the cell is clicked on, and it segues into another tableview. The first tableview works and loads the appropriate data. the second does not display the data. Here is my code:
let query = PFQuery(className: "_User")
query.whereKey("Chemistry", equalTo: true)
query.findObjectsInBackgroundWithBlock { (caption: [AnyObject]?, erreur: NSError?) -> Void in
if erreur == nil {
// on a réussi
for caption in caption! {
self.chemistryListe.append(caption["username"] as! String)
}
println("we are here")
println(self.chemistryListe)
}
else {
// quelque chose s'est passé
}
}
And here are my cellforRowatIndexPath and numberOfRowsinSection methods:
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.chemistryListe.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("SearchResult") as! CompanyTableViewCell
println(self.chemistryListe)
cell.nameLabel.text = chemistryListe[indexPath.row]
return cell
}
if I change this line:
cell.nameLabel.text = chemistryListe[indexPath.row]
to this:
cell.nameLabel.text = "testcell"
then everything works, and it correctly displays the text "testcell". So obviously it is not reading that there is anything in the chemistryListe array. But I set a breakpoint in the middle of my query, and saw that the query was correctly fetching the data that should be in the array, and was putting it into the array. But just the tableview cell isn't reading it. Any idea what could be wrong? thanks
Make sure first if you have data into the array. Then you if the array contains string change this line to :
cell.nameLabel.text = chemistryListe[indexPath.row] as! String
Change
cell.nameLabel.text = chemistryListe[indexPath.row]
to
cell.nameLabel.text = "\(chemistryListe[indexPath.row])"
Found the answer myself:
I just needed to add
self.tableView.reloadData()
to the end of the query method.
thanks to all for the effort.

Resources