我有一个应用程序,用户可以按顺序下载多个文件。我已按照Mr. Rob's solution进行顺序下载。但是,当我尝试取消下载时,我遇到了问题。
我尝试取消下载时有两种情况。
以下是代码
DownloadManager.swift
class DownloadManager: NSObject, NSURLSessionTaskDelegate, NSURLSessionDownloadDelegate
{
/// Dictionary of operations, keyed by the `taskIdentifier` of the `NSURLSessionTask`
internal var delegate : DownloadVC!
private var operations = [Int: DownloadOperation]()
/// Serial NSOperationQueue for downloads
let queue: NSOperationQueue = {
let _queue = NSOperationQueue()
_queue.name = "download"
_queue.maxConcurrentOperationCount = 1
return _queue
}()
/// Delegate-based NSURLSession for DownloadManager
lazy var session: NSURLSession = {
let sessionConfiguration = NSURLSessionConfiguration.defaultSessionConfiguration()
return NSURLSession(configuration: sessionConfiguration, delegate: self, delegateQueue: nil)
}()
/// Add download
///
/// - parameter URL: The URL of the file to be downloaded
///
/// - returns: The DownloadOperation of the operation that was queued
func addDownload(URL: NSURL) -> DownloadOperation
{
print("url in download manager: \(URL)")
let operation = DownloadOperation(session: session, URL: URL)
operations[operation.task.taskIdentifier] = operation
queue.addOperation(operation)
return operation
}
/// Cancel all queued operations
func cancelAll()
{
queue.cancelAllOperations()
}
// func cancelOne()
// {
// operations[identifier]?.cancel()
// print("identifier : \(identifier)")
// //queue.operations[identifier].cancel()
// // cancelAll()
// }
// MARK: NSURLSessionDownloadDelegate methods
func URLSession(session: NSURLSession,
downloadTask: NSURLSessionDownloadTask,
didFinishDownloadingToURL location: NSURL)
{
print("downloadTask.taskIdentifier \(downloadTask.taskIdentifier)")
operations[downloadTask.taskIdentifier]?.delegate = delegate
operations[downloadTask.taskIdentifier]?.URLSession(session, downloadTask: downloadTask, didFinishDownloadingToURL: location)
}
func URLSession(session: NSURLSession,
downloadTask: NSURLSessionDownloadTask,
didWriteData bytesWritten: Int64,
totalBytesWritten: Int64,
totalBytesExpectedToWrite: Int64)
{
operations[downloadTask.taskIdentifier]?.delegate = delegate
operations[downloadTask.taskIdentifier]?.URLSession(session, downloadTask: downloadTask, didWriteData: bytesWritten, totalBytesWritten: totalBytesWritten, totalBytesExpectedToWrite: totalBytesExpectedToWrite)
}
// MARK: NSURLSessionTaskDelegate methods
func URLSession(session: NSURLSession,
task: NSURLSessionTask,
didCompleteWithError error: NSError?)
{
let key = task.taskIdentifier
operations[key]?.URLSession(session, task: task, didCompleteWithError: error)
operations.removeValueForKey(key)
}
}
DownloadOperation.swift
class DownloadOperation : AsynchronousOperation
{
let task: NSURLSessionTask
var percentageWritten:Float = 0.0
var delegate : DataDelegate!
init(session: NSURLSession, URL: NSURL)
{
task = session.downloadTaskWithURL(URL)
super.init()
}
override func cancel() {
task.cancel()
super.cancel()
}
override func main() {
task.resume()
}
// MARK: NSURLSessionDownloadDelegate methods
func URLSession(session: NSURLSession,
downloadTask: NSURLSessionDownloadTask,
didWriteData bytesWritten: Int64,
totalBytesWritten write: Int64,
totalBytesExpectedToWrite expect: Int64)
{
//download bar progress
percentageWritten = Float(write) / Float(expect)
//progressBar.progress = percentageWritten
let pW = Int(percentageWritten*100)
delegate.didWriteData(pW)
}
// using cocoa Security for encryption and decryption
func URLSession(session: NSURLSession,
downloadTask: NSURLSessionDownloadTask,
didFinishDownloadingToURL location: NSURL)
{
let documentsDirectoryURL = NSFileManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first as NSURL?
print("Finished downloading!")
print(documentsDirectoryURL)
let downloadLocation = "\(location)".stringByReplacingOccurrencesOfString("file://", withString: "")
let fileData = NSFileManager().contentsAtPath(downloadLocation)
delegate.didFinishDownloadingToUrl(fileData!)
}
// MARK: NSURLSessionTaskDelegate methods
func URLSession(session: NSURLSession,
task: NSURLSessionTask,
didCompleteWithError error: NSError?)
{
completeOperation()
if error != nil {
print(error)
}
}
}
AsynchronousOperation.swift
class AsynchronousOperation : NSOperation
{
override var asynchronous: Bool { return true }
private var _executing: Bool = false
override var executing: Bool
{
get
{
return _executing
}
set {
if (_executing != newValue)
{
self.willChangeValueForKey("isExecuting")
_executing = newValue
self.didChangeValueForKey("isExecuting")
}
}
}
private var _finished: Bool = false
override var finished: Bool
{
get
{
return _finished
}
set
{
if (_finished != newValue)
{
self.willChangeValueForKey("isFinished")
_finished = newValue
self.didChangeValueForKey("isFinished")
}
}
}
func completeOperation()
{
if executing {
executing = false
finished = true
}
}
override func start()
{
if (cancelled) {
finished = true
executing = false
return
}
executing = true
main()
}
}
DownloadViewController.swift
这是我想要取消下载的地方。
if cell.downloadLabel.currentTitle == "CANCEL"
{
print("cancel button was pressed")
downloadManager.cancelAll()
// I want to put the codes here
let defaults: NSUserDefaults = NSUserDefaults.standardUserDefaults()
let key = cell.stringId
print("key : \(key)")
defaults.setBool(false, forKey: key)
defaults.synchronize()
cell.accessoryType = UITableViewCellAccessoryType.None
cell.downloadLabel.backgroundColor = UIColor.redColor()
cell.downloadLabel.setTitle("DOWNLOAD", forState: .Normal)
}
对于情况1,我尝试使用do
queue.operations[identifier].cancel()
但它崩溃说
*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayI objectAtIndex:]: index 1 beyond bounds [0 .. 0]'
对于情况2,我试图将所有下载的URL放入一个数组中,添加到队列中,一旦单击取消按钮,它将取消所有()队列,从队列中删除取消的URL并重新插入剩余的URL回到阵列。但是,它不会工作
有人能帮助我满足这两种情况吗?
答案 0 :(得分:2)
您需要保留对A
实例的引用。然后你可以打电话给NSOperation
。