在我的iOS应用中,UITableView
显示音轨列表。每个文件旁边都有一个accessory button,可以在收听文件之前单击该文件以下载文件。
我的下载功能包括if / else,打印文件已被下载(如果用户已经下载)。我希望它在下载按钮的位置显示.checkmark
附件,如果文件已下载,则视图打开 - 现在,只有在点击附件后才会这样做。
要设置第一个配件,我使用:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = TableData[indexPath.row]
cell.accessoryType = .detailDisclosureButton
return cell
}
然后在accessoryButtonTappedForRowWith
中,检查文件是否已下载并更新为复选标记,如果有:
override func tableView(_ tableView: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath) {
// doSomethingWithItem(indexPath.row)
if let audioUrl = URL(string: "https://rss.example.com.mp3") {
// then lets create your document folder url
let documentsDirectoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
// lets create your destination file url
let destinationUrl = documentsDirectoryURL.appendingPathComponent(audioUrl.lastPathComponent)
print(destinationUrl)
// to check if it exists before downloading it
if FileManager.default.fileExists(atPath: destinationUrl.path) {
print("The file already exists at path")
let cell = tableView.cellForRow(at: indexPath)
cell?.accessoryType = .checkmark
// if the file doesn't exist
} else {
// you can use NSURLSession.sharedSession to download the data asynchronously
URLSession.shared.downloadTask(with: audioUrl, completionHandler: { (location, response, error) -> Void in
guard let location = location, error == nil else { return }
do {
// after downloading your file you need to move it to your destination url
try FileManager.default.moveItem(at: location, to: destinationUrl)
print("File moved to documents folder")
} catch let error as NSError {
print(error.localizedDescription)
}
}).resume()
}
}
我的理论是,由于.checkmark
行,需要在附件上轻敲功能发生,它不能被点击的元素一改之前,像我想要的。
有没有更好的方法来减少用户的点击?
答案 0 :(得分:1)
您需要在cellForRowAt
中放置if else条件,并且需要检查文件是否已经下载。在此基础上,您需要设置.checkmark
或.detailDisclosureButton
。
一种方法是在TableData
中设置布尔值以检查文件是否已下载。如果您遵循这种方法,则无需在accessoryButtonTappedForRowWith
中获取所选单元格,您只需要在TableData
的特定索引上更改布尔标志的值,并需要重新加载单行。
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = TableData[indexPath.row]
if (TableData[indexPath.row]).isDownloaded {
cell.accessoryType = .checkmark
}else {
cell.accessoryType = .detailDisclosureButton
}
return cell
}
重新加载单行:
override func tableView(_ tableView: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath) {
// doSomethingWithItem(indexPath.row)
if let audioUrl = URL(string: "https://rss.example.com.mp3") {
// then lets create your document folder url
let documentsDirectoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
// lets create your destination file url
let destinationUrl = documentsDirectoryURL.appendingPathComponent(audioUrl.lastPathComponent)
print(destinationUrl)
// to check if it exists before downloading it
if FileManager.default.fileExists(atPath: destinationUrl.path) {
print("The file already exists at path")
(TableData[indexPath]).isDownloaded = true
tableView.reloadRows(at: [indexPath], with: UITableViewRowAnimation.none)
// if the file doesn't exist
} else {
// you can use NSURLSession.sharedSession to download the data asynchronously
URLSession.shared.downloadTask(with: audioUrl, completionHandler: { (location, response, error) -> Void in
guard let location = location, error == nil else { return }
do {
// after downloading your file you need to move it to your destination url
try FileManager.default.moveItem(at: location, to: destinationUrl)
print("File moved to documents folder")
} catch let error as NSError {
print(error.localizedDescription)
}
}).resume()
}
}
答案 1 :(得分:1)
一种方法是将代码从accessoryButtonTappedForRowWith
重构为另一种方法,让我们说checkIfDownloaded(at:)
并从accessoryButtonTappedForRowWith
和cellForRowAt
调用该方法:
// MARK: Utility methods
func audioURL(for indexPath: IndexPath) -> URL? {
if let audioUrl = URL(string: "https://rss.example.com.mp3") {
return audioUrl
} else {
return nil
}
}
func fileLocation(for indexPath: IndexPath) -> URL? {
if let audioUrl = audioURL(for: indexPath) {
// then lets create your document folder url
let documentsDirectoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
// lets create your destination file url
let destinationUrl = documentsDirectoryURL.appendingPathComponent(audioUrl.lastPathComponent)
return destinationUrl
} else {
return nil
}
}
func checkIfDownloaded(at indexPath: IndexPath) -> Bool {
// doSomethingWithItem(indexPath.row)
if let audioUrl = URL(string: "https://rss.example.com.mp3") {
// then lets create your document folder url
let documentsDirectoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
// lets create your destination file url
let destinationUrl = documentsDirectoryURL.appendingPathComponent(audioUrl.lastPathComponent)
print(destinationUrl)
// to check if it exists before downloading it
if FileManager.default.fileExists(atPath: destinationUrl.path) {
print("The file already exists at path")
return false
} else {
return true
}
}
}
func downloadAudioIfNotDownloaded(for indexPath: IndexPath, completion: (( /* downloaded */ Bool) -> Void)?) -> URL? {
if !checkIfDownloaded(at: indexPath),
let audioURL = audioURL(for: indexPath),
let destinationUrl = fileLocation(for: indexPath) {
// you can use NSURLSession.sharedSession to download the data asynchronously
URLSession.shared.downloadTask(with: audioURL, completionHandler: { (location, response, error) -> Void in
guard let location = location, error == nil else {
completion?(false)
return }
do {
// after downloading your file you need to move it to your destination url
try FileManager.default.moveItem(at: location, to: destinationUrl)
print("File moved to documents folder")
// success
completion?(true)
} catch let error as NSError {
print(error.localizedDescription)
completion?(false)
}
}).resume()
} else {
// was already downloaded
completion?(true)
}
}
// MARK: TableView delegate/datasource methods
override func tableView(_ tableView: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath) {
downloadAudioIfNotDownloaded(for: indexPath, completion: { success in
// fix up a new accessory view/
})
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = ...
if checkIfDownloaded(at: indexPath) {
cell.accessoryType = .checkmark
} else {
cell.accessoryType = .detailDisclosureButton
// although if you are starting to download automaticlly here
// make sure the user won't start it by herself while one download already is happening
downloadAudioIfNotDownloaded(for: indexPath, completion: { success in
// fix up a new accessory view/
})
}
return cell
}