我有一个Tableview,其中包含同一类的多个单元格。在更改单元格内的开关时,应下载特定文件。
实际行为: 正确的开关正在改变其状态,即使在滚动时它也会被存储,所以这不是问题所在。 countryDesignator在开始下载时是正确的,完成后它也是正确的文件,但是当文件存储时,它使用错误的countryDesignator并且progressBar也是错误的。在这种特殊情况下,点击加拿大将导致文件[..] ca_asp.aip下载并且加拿大单元格中的开关发生变化,但奥地利单元格的progressBar正在移动,存储的文件名为at_asp_aip。
代码:
var countrySettings : [countryOptions] = [countryOptions(name: "Austria", isEnabled: false, progress: 0.0, filename: "at"),
countryOptions(name: "Australia", isEnabled: false, progress: 0.0, filename: "au"),
countryOptions(name: "Brazil", isEnabled: false, progress: 0.0, filename: "br"),
countryOptions(name: "Canada", isEnabled: false, progress: 0.0, filename: "ca"), ...]
var downloadCount : Int = 0
class CountrySettings: UIViewController, UITableViewDataSource, UITableViewDelegate {
@IBOutlet weak var countryTableView: UITableView!
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCell(withIdentifier: "Country") as! countryCell
cell.countryName.text = countrySettings[indexPath.row].name
cell.countrySwitch.isOn = countrySettings[indexPath.row].isEnabled
cell.countryDesignator = countrySettings[indexPath.row].filename
return cell
}
class countryCell: UITableViewCell, URLSessionDownloadDelegate,UIDocumentInteractionControllerDelegate {
@IBOutlet weak var countrySwitch: UISwitch!
@IBOutlet weak var countryName: UILabel!
var countryDesignator : String = "ad"
@IBAction func didChangeSwitchValue(_ sender: UISwitch) {
guard let indexPath = self.indexPath else { return }
downloadCount = 0
print(countryDesignator) // prints correct Designator
startDownloading()
}
func startDownloading () {
guard let indexPath = self.indexPath else { return }
countrySettings[indexPath.row].isEnabled = countrySwitch.isOn
DispatchQueue.main.async {
print(self.countryDesignator) // prints correct Designator
downloadCount += 1
if downloadCount == 1 {
let url = URL(string: "https://www.blablabla.com/" + self.countryDesignator + "_asp.aip")!
self.downloadTask = self.defaultSession.downloadTask(with: url)
self.downloadTask.resume()
}
}
}
// MARK:- URLSessionDownloadDelegate
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
print(countryDesignator) // prints WRONG!
print("File download succesfully")
let path = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)
let documentDirectoryPath:String = path[0]
let fileManager = FileManager()
var destinationURLForFile = URL(fileURLWithPath: documentDirectoryPath.appendingFormat("/" + countryDesignator + "_asp.aip"))
if downloadCount == 2 {
destinationURLForFile = URL(fileURLWithPath: documentDirectoryPath.appendingFormat("/" + countryDesignator + "_wpt.aip"))
}
if fileManager.fileExists(atPath: destinationURLForFile.path){
showFileWithPath(path: destinationURLForFile.path, completePath: destinationURLForFile)
print(destinationURLForFile.path)
}
else{
do {
try fileManager.moveItem(at: location, to: destinationURLForFile)
// load data into database
showFileWithPath(path: destinationURLForFile.path, completePath: destinationURLForFile)
}catch{
print("An error occurred while moving file to destination url")
}
}
}
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
DispatchQueue.main.async {
print(self.countryDesignator) // prints WRONG
guard let indexPath = self.indexPath else { return }
self.progress.setProgress(Float(totalBytesWritten)/Float(totalBytesExpectedToWrite), animated: true)
countrySettings[indexPath.row].progress = self.progress.progress
}
}
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
downloadTask = nil
progress.setProgress(0.0, animated: true)
if (error != nil) {
print("didCompleteWithError \(error?.localizedDescription ?? "no value")")
}
else {
print("The task finished successfully")
print(downloadCount)
if downloadCount == 1 {
startDownloading()
}
}
}
override func awakeFromNib() {
super.awakeFromNib()
let backgroundSessionConfiguration = URLSessionConfiguration.background(withIdentifier: "backgroundSession" + countryDesignator)
defaultSession = Foundation.URLSession(configuration: backgroundSessionConfiguration, delegate: self, delegateQueue: OperationQueue.main)
progress.setProgress(0.0, animated: false) // This is working correctly
}
}
答案 0 :(得分:1)
这是一个常见问题。由于UITableViewCell
为reuseable
,因此您保存单元格,但滚动时单元格会显示不同的datasource
。
您不应该保存单元格,而是记录下载的内容取决于数据源。
func startDownloading () {
guard let indexPath = self.indexPath else { return }
countrySettings[indexPath.row].isEnabled = countrySwitch.isOn
countrySettings[indexPath.row].isDownloading = true
DispatchQueue.main.async {
print(self.countryDesignator) // prints correct Designator
downloadCount += 1
if downloadCount == 1 {
let url = URL(string: "https://www.blablabla.com/" + self.countryDesignator + "_asp.aip")!
countrySettings[indexPath.row].downloadTask = self.defaultSession.downloadTask(with: url)
countrySettings[indexPath.row].downloadTask.resume()
}
}
}
始终将countryDesignator
更改为显示此下载数据源的单元格。