2

I have a tableview list that has a select action tied to it. When the user selects the row, it gives them a prompt and begins to download a file and displays progress using a progressive indicator. For some reason, the indicator is being displayed every 12 records from the selection. Why is this happening... am I selecting the cell incorrectly?

Here is my code:

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    let cell = self.tableView.cellForRow(at: indexPath) as! downloadCell
    let cellName = CurrentFiles[indexPath.row].labelName
    let internalName = CurrentFiles[indexPath.row].internalName
    let fileLocation = CurrentFiles[indexPath.row].fileName
    let safeURL = fileLocation.addingPercentEncoding(withAllowedCharacters:NSCharacterSet.urlQueryAllowed)
    let fileExtension = CurrentFiles[indexPath.row].fileExtension
    let fileDate = CurrentFiles[indexPath.row].lastUpdate
    if (cell.progressView.isHidden) && (cell.fileStatus == "Installed") && (cell.fileIcon.image ==  nil) {
        let fileLoc = getSharedFilePath(appGroup:applicationGroup,sharedFilename:"\(internalName).\(fileExtension)")
        let defaults = UserDefaults.standard
        defaults.set(fileLoc, forKey: "loadmap")
        defaults.set(cellName, forKey: "loadmapName")
        performSegue(withIdentifier: "gotoMap", sender: self)
    } else if (cell.progressView.isHidden) {
        alertControllerMsg(msgStyle: UIAlertControllerStyle.alert,msgTitle: "Download File", msgBody: "Are you sure you want to download \(cellName)?", cancelLbl: "Cancel", actionLbl: "Download", complete: {
            cell.fileStatus = "Installed"      //prevent double download
            //download file
            let destination: (URL, HTTPURLResponse) -> (URL, DownloadRequest.DownloadOptions) = {
                (temporaryURL, response) in
                if let directoryURL = FileManager().containerURL(forSecurityApplicationGroupIdentifier: applicationGroup), let suggestedFilename = response.suggestedFilename {
                    let filePath = directoryURL.appendingPathComponent("\(suggestedFilename)")
                    return (filePath, [.removePreviousFile, .createIntermediateDirectories])
                }
                return (temporaryURL, [.removePreviousFile, .createIntermediateDirectories])
            }
            if self.reachability.isReachableViaWiFi {
                cell.progressView.isHidden = false
                //BackendAPI is used to allow for downloads in background
                BackendAPIManager.sharedInstance.alamoFireManager.download(safeURL!, to: destination)
                    .downloadProgress { progress in
                        cell.fileIcon.image =  nil
                        cell.progressView.setProgress(Float(progress.fractionCompleted), animated: true)
                        cell.pctLabel.text = "\(String(format:"%g",round(progress.fractionCompleted*100)))%"
                    }.response { response in
                        cell.pctLabel.text = nil
                        cell.progressView.isHidden = true
                        cell.additionalLbl.text = nil
                        UserDefaults(suiteName: applicationGroup)!.set(fileDate, forKey: internalName)
                        cell.fileStatus = "Installed"
                        self.getAvailSpace()
                }
            } else {
                self.alertControllerMsg(msgStyle: UIAlertControllerStyle.alert,msgTitle: "Insufficient Network", msgBody: "Please connect to a Wifi network to download this file.", cancelLbl: "Cancel", actionLbl: "Retry", complete: {
                    self.downloadAndSort()
                })
            }
        })
    }
}

EDIT:

CellforRowAt code

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    if let cell = tableView.dequeueReusableCell(withIdentifier: "downloadCell", for: indexPath) as? downloadCell {
        let currentFile = CurrentFiles[indexPath.row]
        cell.configureCell(currentFile: currentFile)
        return cell
    } else {
        return downloadCell()
    }
}

EDIT 2:

class downloadCell: UITableViewCell {

@IBOutlet weak var fileLbl: UILabel!
@IBOutlet weak var fileIcon: UIImageView!
@IBOutlet weak var pctLabel: UILabel!
@IBOutlet weak var additionalLbl: UILabel!
@IBOutlet weak var fileSize: UILabel!
@IBOutlet weak var progressView: UIProgressView!

var fileStatus = "NotInstalled"
func configureCell(currentFile: currentFiles) {

    fileLbl.text = currentFile.labelName
    fileSize.text = currentFile.fileSize
    let internalName = currentFile.internalName
    fileIcon.image = UIImage(named: "download")
    additionalLbl.text = "Updated: \(convertDateFormatter(date: currentFile.lastUpdate))"

    let fileExists = (readFromSharedFile(sharedFilename: internalName, fileExtension: currentFile.fileExtension))
    if fileExists == "Success" {
        //file has been downloaded on device
        let lastUpdateDate = UserDefaults(suiteName: applicationGroup)!.string(forKey: internalName)

        if lastUpdateDate != currentFile.lastUpdate {
                fileIcon.image =  UIImage(named: "download")
                fileStatus = "NeedsUpdate"
            } else {
                fileIcon.image = nil
                fileStatus = "Installed"
                additionalLbl.text = nil
            }
    } else {
        // not on device
        fileStatus = "NotInstalled"

    }
}
}
Nate23VT
  • 423
  • 8
  • 27
  • Not related but why do you forced unwrap the cell (even with two `!`) but use always optional chaining (`cell?...`)? – vadian Mar 20 '17 at 17:54
  • Thanks, I had been meaning to clean it up. I think it got that way as a result of just relying on the autocorrect. It did not make a difference with my issue though. – Nate23VT Mar 21 '17 at 17:52
  • Edited to clean-up code as per vadian – Nate23VT Mar 30 '17 at 17:44
  • update your question with the `cellForRowAtindex` method to check how you create your cell. I think that your cells are being reused and the information is not maintained. – Lucho Mar 30 '17 at 20:12
  • here, [check this answer](http://stackoverflow.com/a/21134025/4905076), is very similar to your problem. He uses an array of progress to keep track the downloaded progress and set the correct value to the progress view on the cell. – Lucho Mar 30 '17 at 20:24
  • And what does `cell.configureCell(currentFile: currentFile)`? – Reinhard Männer Apr 05 '17 at 20:19

4 Answers4

1

On my view controller, I created a new dictionary to hold my file names and current progress defaulting to 0 and an array to hold the currently downloading files

var downloadProg = [String: Double]()
var currentDownloadNames = [String]()

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    if let cell = tableView.dequeueReusableCell(withIdentifier: "downloadCell", for: indexPath) as? downloadCell {
        let currentFile = CurrentFiles[indexPath.row]
        cell.configureCell(currentFile: currentFile)
        if !(currentDownloadNames.contains(currentFile.labelName)) {
            cell.progressView.isHidden = true
            cell.pctLabel.isHidden = true
            cell.fileIcon.isHidden = false
        } else {
            cell.fileIcon.isHidden = true
            cell.progressView.isHidden = false
            cell.pctLabel.isHidden = false
        }
        return cell
    } else {
        return downloadCell()
    }
}

I now set the dictionary percentage in my .downloadProgress

                            downloadProg[cellName] = progress.fractionCompleted

and I modified the downloadCell to show the percentage:

let pct = downloadProg[currentFile.labelName]
    if (progressView.isHidden == false){
        progressView.setProgress(Float(pct!), animated: true)
        pctLabel.text = "\(String(format:"%g",round(pct!*100)))%"
    } 
Nate23VT
  • 423
  • 8
  • 27
  • Nate, sorry I've been busy and didn't follow up to your requests for clarification. Although your current code is better, it still seems strange to me in the respect I pointed out earlier: `return downloadCell()` branch without any configuration looks very suspicious to me. You probably will have some issues when user rotates device if download is in progress. – SergGr Apr 06 '17 at 20:26
0

We really need your code for cellForRowAtindex as well and a better description of the issue. How many cells fit the screen (is it around 12)? Is just progress view shown for every 12-th cell or does actual progress run in every 12th cell? If the progress view is just shown but is not updated, then the most obvious reason that comes to mind is that you forgot to hide progressView in cellForRowAtindex when the cell is being re-used after dequeue​Reusable​Cell(with​Identifier:​).

SergGr
  • 23,570
  • 2
  • 30
  • 51
  • SergGr I have edited the post with the cellforrowatIndex code. My list view probably has around 30 values, 11 are shown in the beginning (landscape view). When I click the 3rd one, it also runs the progress update for the line 13 rows beneath that one. It appears like it is donwloading that file as well but I have confirmed that it is only downloading the one I have selected. – Nate23VT Mar 31 '17 at 14:59
  • @Nate23VT, obviously providing such `cellForRowAtindex` without methods it calls make no sense. Does `configureCell` hide `progressView` if the file is not being downloaded? What if you don't use `dequeue​Reusable​Cell` at all and every time create a new cell? Why `downloadCell` call doesn't receive `currentFile` as a parameter? – SergGr Mar 31 '17 at 17:06
  • I have added the downloadCell class code as well in edit - I am looking at reworking based on your questions but I am new to Swift – Nate23VT Apr 03 '17 at 16:28
  • Looks like I can't award the bounty to myself and this answer got me most on track. – Nate23VT Apr 06 '17 at 19:55
0

Tick the cell.progressview hidden flag to true in inspector builder either this. or you have to print and check your hidden status for progressview.

iSwift
  • 314
  • 3
  • 17
0

It sounds like you need to reset the progress view in your prepareForReuse:

In the cell override:

override func prepareForReuse() {

}

This gets called when the cell is reused, which sounds like what is happening for yourself.

Sean Lintern
  • 3,103
  • 22
  • 28