1

How to cancel Alamofire request if the downloaded file is already exists in documents folder?

Here is the code for request:

Alamofire.download(.GET, fileUrls[button.tag], destination: { (temporaryURL, response) in
    if let directoryURL = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0] as? NSURL {
        let fileURL = directoryURL.URLByAppendingPathComponent(response.suggestedFilename!)
        self.localFilePaths[button.tag] = fileURL
        if NSFileManager.defaultManager().fileExistsAtPath(fileURL.path!) {
            NSFileManager.defaultManager().removeItemAtPath(fileURL.path!, error: nil)
        }
        return fileURL
    }
    println("temporaryURL - \(temporaryURL)")
    self.localFilePaths[button.tag] = temporaryURL
    return temporaryURL
}).progress { _, totalBytesRead, totalBytesExpectedToRead in
    println("\(totalBytesRead) - \(totalBytesExpectedToRead)")
    dispatch_async(dispatch_get_main_queue()) {
        self.progressBar.setProgress(Float(totalBytesRead) / Float(totalBytesExpectedToRead), animated: true)

        if totalBytesRead == totalBytesExpectedToRead {
            self.progressBar.hidden = true
            self.progressBar.setProgress(0, animated: false)
        }
    }
}.response { (_, _, data, error) in
    let previewQL = QLReaderViewController()
    previewQL.dataSource = self
    previewQL.currentPreviewItemIndex = button.tag
    self.navigationController?.pushViewController(previewQL, animated: true)
}

I've also tried to create a request variable var request: Alamofire.Request? and then cancel request?.cancel() it if that file exists but it doesn't work.

Can someone help me to solve this issue?

TryinHard
  • 4,078
  • 3
  • 28
  • 54
mkz
  • 2,302
  • 2
  • 30
  • 43

2 Answers2

1

Rather than cancelling the request, IMO you shouldn't make it in the first place. You should do the file check BEFORE you start the Alamofire request.

If you absolutely feel you need to start the request, you can always cancel immediately after starting the request.

var shouldCancel = false

let request = Alamofire.request(.GET, "some_url") { _, _ in
        shouldCancel = true
    }
    .progress { _, _, _ in
        // todo...
    }
    .response { _, _, _ in
        // todo...
    }

if shouldCancel {
    request.cancel()
}
cnoon
  • 16,575
  • 7
  • 58
  • 66
0

TL; DR: Canceling a request is a bit cumbersome in many cases. Even Alamofire, as far as I know, does not guarentee that request will be cancelled upon your request, immediately. However, you may use dispatch_suspend or NSOperation in order to overcome this.

Grand Central Dispatch (GCD)

This way utilizes functional programming.

Here we enlight our way with low-level programming. Apple introduced a good library, aka GCD, to do some thread-level programming.

You cannot cancel a block, unless... you suspend a queue (if it is not main or global queue).

There is a C function called dispatch_suspend, (from Apple's GCD Reference)

void dispatch_suspend(dispatch_object_t object);

Suspends the invocation of block objects on a dispatch object.

And you can also create queues (who are dispatch_object_ts) with dispatch_queue_create.

So you can do your task in user created queue, and you may suspend this queue in order to prevent CPU from doing something unnecessary.

NSOperation (also NSThread)

This way utilizes functional programming over object-oriented interface.

Apple also introduced NSOperation, where object-oriented programming may be object, whereas it is easier to cope with.

NSOperation is an abstract class, which associates code and data, according to the Apple's documentation.

In order to use this class, you should either use one of its defined subclasses, or create your own subclass: In your case particularly, I suppose NSBlockOperation is the one.

You may refer to this code block:

let block = NSBlockOperation { () -> Void in
    // do something here...
}

// Cancel operation
block.cancel()

Nevertheless, it also does not guarantee stopping from whatever it is doing. Apple also states that:

This method does not force your operation code to stop. Instead, it updates the object’s internal flags to reflect the change in state. If the operation has already finished executing, this method has no effect. Canceling an operation that is currently in an operation queue, but not yet executing, makes it possible to remove the operation from the queue sooner than usual.

If you want to take advantage of flags, you should read more: Responding to the Cancel Command

Buğra Ekuklu
  • 3,049
  • 2
  • 17
  • 28