I am trying to make an app which save some entries in Core Data and also with an option to sync it online. What I want is that when the document is syncing, it has a different image on the cell's imageView and on the background, I send requests to get the unique IDs of all the synced documents. So, whenever the document is synced, its' imageView's image changes. So, far, I have done this.
override func viewDidLoad() {
super.viewDidLoad()
self.syncedIds = NSMutableArray()
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.tokenAndIds = NSMutableArray()
let prefs:NSUserDefaults = NSUserDefaults.standardUserDefaults()
let authToken = prefs.valueForKey("authToken") as! String
values["auth_code"] = "\(authToken)"
self.checkSync()
NSTimer.scheduledTimerWithTimeInterval(6.0, target: self, selector: #selector(ReceiptsListViewController.checkSync), userInfo: nil, repeats: true)
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(CellIdentifier as String, forIndexPath: indexPath) as! ReceiptsViewCell
// Configure the cell...
let entry: DiaryEntry = self.fetchedResultsController.objectAtIndexPath(indexPath) as! DiaryEntry
cell.configureCellForEntry(entry)
cell.imageButton.tag = indexPath.row
if (self.tableView.editing) {
cell.imageButton.hidden = true
} else {
cell.imageButton.hidden = false
}
if (cell.syncImageView.image == UIImage(named: "syncing")) {
let idString: String = "\(cell.idParam!)"
tokenAndIds.addObject(idString)
}
if (syncedIds != nil) {
for i in 0 ..< syncedIds.count {
if (syncedIds[i] as! String == "\(cell.idParam!)") {
print("Synced Ids are: \(syncedIds[i])")
let cell1 = tableView.dequeueReusableCellWithIdentifier(CellIdentifier as String, forIndexPath: indexPath) as! ReceiptsViewCell
let entry: DiaryEntry = self.fetchedResultsController.objectAtIndexPath(indexPath) as! DiaryEntry
entry.sync = 2
let coreDataStack: CoreDataStack = CoreDataStack.defaultStack
coreDataStack.saveContext()
cell1.configureCellForEntry(entry)
self.tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)
cell.syncImageView.image = UIImage(named: "sync")
}
}
}
return cell
}
func checkSync() {
if (tokenAndIds != nil && tokenAndIds != []) {
let idArray: NSMutableArray = tokenAndIds
let myUrl = NSURL(string: "http://10.0.0.4:81/iphone/sync.php")
let request = NSMutableURLRequest(URL: myUrl!)
request.HTTPMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
values["idArray"] = idArray
request.HTTPBody = try! NSJSONSerialization.dataWithJSONObject(values, options: [])
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
(let data, let response, let error) in
if let _ = response as? NSHTTPURLResponse {
do {
let json = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableContainers) as? NSDictionary
if error != nil {
print("error=\(error!)")
return
}
if let parseJSON = json {
for (key, value) in parseJSON {
if (value as! String == "0") {
print(key)
self.syncedIds.addObject(key)
}
}
}
} catch {
print("Error is Here: \(error)")
}
}
}
task.resume()
}
}
But the problem is that when I get the response about all the synced IDs and then I go into another View and then come back to make the changes to the syncImageView, cells keep on disappearing and I also get this warning: "no indexpath for cell being reused." I know it is something to do with cellForRowAtIndexPath method, but what is it? Also, if I stop the app and re-run it, then, everything is fixed like imageView is changed and no cells disappear.
The problem is the async call within cellForRowAtIndexPath
. You need to get your code (outside of the tableView dataSource and delegate) and once you have your data fetched (and likely stored in some type of collection, like an Array), call reloadData() on your tableView and refresh the data.
cellForRowAtIndexPath
should be looking for existing data, not fetching the data. indexPath.row
is used to call your collection index and get the appropriate data.
By the time your async call is finished, the cellForRowAtIndexPath
has already completed and the reference to the cell you are trying to update no longer exists (hence the error).
TIP:
Remember, after you get your data in a background thread, be sure to call reloadData() on the main thread
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.