Reputation: 23
I have a UITableView with custom cell displaying a list of files that can be downloaded. The cell displays the filename and download status. Everything working fine except one scenario :
Scrolling the tableview to get the cell out of screen and back refreshes the cell correctly. Anyway to do this programmatically?"
Otherwise, in normal case where user doesn't change screen, reloadData() is working fine.
Any idea how to fix this?
Thanks
I have used alamofire download with progress in the function below which is inside my UIViewController.
func DownloadFile(fileurl: String, indexPath: NSIndexPath, itemPath: String, itemName: String, itemPos: String, ItemSelected:Bool) {
let cell = myTableView.cellForRowAtIndexPath(indexPath) as! myCustomCell
let destination = Alamofire.Request.suggestedDownloadDestination(directory: .DocumentDirectory, domain: .UserDomainMask)
Alamofire.download(.GET, fileurl, destination: destination)
.progress {bytesRead, totalBytesRead, totalBytesExpectedToRead in
// This closure is NOT called on the main queue for performance
// reasons. To update your ui, dispatch to the main queue.
dispatch_async(dispatch_get_main_queue()) {
print("Total bytes read on main queue: \(totalBytesRead) / \(totalBytesExpectedToRead)")
let progress = Int((Double(totalBytesRead)/Double(totalBytesExpectedToRead)) * 100)
cell.lblMoreRuqyaFileInfo.text = "Downloading file...(\(progress)%)"
}
}
.response { _, _, _, error in
if let error = error {
print("\(error)")
cell.lblMoreRuqyaFileInfo.text = "Failed to download file. Please try again."
} else {
cell.lblMoreRuqyaFileInfo.text = "File Downloaded sucessfully"
//reloadData() not working from here
self.myTableView.reloadData()
}
}
}
The above func is being called in the tableview's editActionsForRowAtIndexPath below.
func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]? {
if myTableView.cellForRowAtIndexPath(indexPath) == nil {
let action = UITableViewRowAction()
return [action]
}
let cell = myTableView.cellForRowAtIndexPath(indexPath) as! myCustomCell
let fileurl = cell.textLabel!.text
let ruqyainfo = cell.lblMoreRuqyaFileInfo.text
let sItemPath = cell.lblCompiledRuqya.text! + "->" + cell.textLabel!.text! + "->\(indexPath.section)->\(indexPath.row)"
let sItemName = cell.lblCompiledRuqya.text!
let sItemPos = "->\(indexPath.section)->\(indexPath.row)"
var bItemSelected:Bool = false
if myTableView.cellForRowAtIndexPath(indexPath)?.accessoryType == UITableViewCellAccessoryType.Checkmark {
bItemSelected = true
} else {
bItemSelected = false
}
//check if file already downloaded,return empty action, else show Download button
if ruqyainfo?.containsString("Download") == false {
let action = UITableViewRowAction()
return [action]
}
let line = AppDelegate.dictCompiledRuqya.mutableArrayValueForKey(AppDelegate.dictCompiledRuqya.allKeys[indexPath.section] as! String)
let name = line[indexPath.row].componentsSeparatedByString("#")
let DownloadAction = UITableViewRowAction(style: .Normal, title: "Download\n(\(name[3]))") { (action: UITableViewRowAction!, indexPath) -> Void in
self.myTableView.editing = false
AppDelegate.arrDownloadInProgressItem.append(name[0])
self.DownloadFile(fileurl!, indexPath: indexPath, itemPath: sItemPath, itemName: sItemName,itemPos: sItemPos, ItemSelected: bItemSelected)
}
DownloadAction.backgroundColor = UIColor.purpleColor()
return [DownloadAction]
}
Upvotes: 3
Views: 1882
Reputation: 1693
You used :
let cell = myTableView.cellForRowAtIndexPath(indexPath) as! myCustomCell
and set text for lblMoreRuqyaFileInfo
:
cell.lblMoreRuqyaFileInfo.text = "File Downloaded sucessfully"
so, you don't have to call self.myTableView.reloadData()
Try:
dispatch_async(dispatch_get_main_queue()) {
cell.lblMoreRuqyaFileInfo.text = "File Downloaded sucessfully"
}
p/s and where did you call functionDownloadFile
, show it, plz!
Upvotes: 0
Reputation: 6040
It could be a thread related issue (aka you're coming back from the download thread, not on the UI thread, hence the data is refreshed but not displayed).
Try using this on self
and pass it a selector that refreshes your tableview.
performSelectorOnMainThread:
Upvotes: 0
Reputation: 501
Hey @John Make sure your TableView datasource is reflected with file upload status permanently.
I think, when you complete file uploading you change status in tableview datasource
1. First scenario as you are switching to second view controller, and coming back to previous view, it might be reinitializing your datasource. Data source might wasn't permanently reflected.
2. In normal scenario, as you are on same view controller(not switching to other). Tableview datasource might be not reinitialized holding updated file upload status.
I suggest to save user file download status saved at some persistant storage or on web server. That doesn't leads to inconsistency in data.
Upvotes: 0
Reputation: 5554
you can use delegates so that the download controller can tell the first controller that the download is complete, and that it should redraw the tableView - or at least the indexPath that has just completed.
set up the download controller like this
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
{
let destinationController : DownloadController = segue.destinationViewController as! DownloadController
destinationController.delegate = self
destinationController.indexRowToRefresh = currentlySelectedIndexRow
}
and then in the download completion closure, add something like this
delegate.refreshTableRow(indexRowToRefresh)
and in your first controller, implement the delegate method to refresh this row (or the whole table)
func refreshTableRow(indexRowToRefresh : Int)
{
var indexPath = NSIndexPath(forRow: indexRowToRefresh, inSection: 0)
tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Top)
}
Upvotes: 0
Reputation: 2251
//Objective C
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
[self.yourTableView reloadData];
}
//Swift
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.yourTableView.reloadData()
}
Upvotes: 0