{"action":"closed","issue":{"url":"https://api.github.com/repos/Alamofire/AlamofireImage/issues/121","repository_url":"https://api.github.com/repos/Alamofire/AlamofireImage","labels_url":"https://api.github.com/repos/Alamofire/AlamofireImage/issues/121/labels{/name}","comments_url":"https://api.github.com/repos/Alamofire/AlamofireImage/issues/121/comments","events_url":"https://api.github.com/repos/Alamofire/AlamofireImage/issues/121/events","html_url":"https://github.com/Alamofire/AlamofireImage/issues/121","id":160708167,"number":121,"title":"ImageDownloader request fails if same request was previously cancelled","user":{"login":"robmaceachern","id":430436,"avatar_url":"https://avatars.githubusercontent.com/u/430436?v=3","gravatar_id":"","url":"https://api.github.com/users/robmaceachern","html_url":"https://github.com/robmaceachern","followers_url":"https://api.github.com/users/robmaceachern/followers","following_url":"https://api.github.com/users/robmaceachern/following{/other_user}","gists_url":"https://api.github.com/users/robmaceachern/gists{/gist_id}","starred_url":"https://api.github.com/users/robmaceachern/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/robmaceachern/subscriptions","organizations_url":"https://api.github.com/users/robmaceachern/orgs","repos_url":"https://api.github.com/users/robmaceachern/repos","events_url":"https://api.github.com/users/robmaceachern/events{/privacy}","received_events_url":"https://api.github.com/users/robmaceachern/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/Alamofire/AlamofireImage/labels/bug","name":"bug","color":"ff3333"},{"url":"https://api.github.com/repos/Alamofire/AlamofireImage/labels/image%20downloader","name":"image downloader","color":"69B805"}],"state":"closed","locked":false,"assignee":{"login":"cnoon","id":169110,"avatar_url":"https://avatars.githubusercontent.com/u/169110?v=3","gravatar_id":"","url":"https://api.github.com/users/cnoon","html_url":"https://github.com/cnoon","followers_url":"https://api.github.com/users/cnoon/followers","following_url":"https://api.github.com/users/cnoon/following{/other_user}","gists_url":"https://api.github.com/users/cnoon/gists{/gist_id}","starred_url":"https://api.github.com/users/cnoon/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cnoon/subscriptions","organizations_url":"https://api.github.com/users/cnoon/orgs","repos_url":"https://api.github.com/users/cnoon/repos","events_url":"https://api.github.com/users/cnoon/events{/privacy}","received_events_url":"https://api.github.com/users/cnoon/received_events","type":"User","site_admin":false},"assignees":[{"login":"cnoon","id":169110,"avatar_url":"https://avatars.githubusercontent.com/u/169110?v=3","gravatar_id":"","url":"https://api.github.com/users/cnoon","html_url":"https://github.com/cnoon","followers_url":"https://api.github.com/users/cnoon/followers","following_url":"https://api.github.com/users/cnoon/following{/other_user}","gists_url":"https://api.github.com/users/cnoon/gists{/gist_id}","starred_url":"https://api.github.com/users/cnoon/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cnoon/subscriptions","organizations_url":"https://api.github.com/users/cnoon/orgs","repos_url":"https://api.github.com/users/cnoon/repos","events_url":"https://api.github.com/users/cnoon/events{/privacy}","received_events_url":"https://api.github.com/users/cnoon/received_events","type":"User","site_admin":false}],"milestone":{"url":"https://api.github.com/repos/Alamofire/AlamofireImage/milestones/17","html_url":"https://github.com/Alamofire/AlamofireImage/milestones/2.4.2","labels_url":"https://api.github.com/repos/Alamofire/AlamofireImage/milestones/17/labels","id":1891314,"number":17,"title":"2.4.2","description":"","creator":{"login":"cnoon","id":169110,"avatar_url":"https://avatars.githubusercontent.com/u/169110?v=3","gravatar_id":"","url":"https://api.github.com/users/cnoon","html_url":"https://github.com/cnoon","followers_url":"https://api.github.com/users/cnoon/followers","following_url":"https://api.github.com/users/cnoon/following{/other_user}","gists_url":"https://api.github.com/users/cnoon/gists{/gist_id}","starred_url":"https://api.github.com/users/cnoon/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cnoon/subscriptions","organizations_url":"https://api.github.com/users/cnoon/orgs","repos_url":"https://api.github.com/users/cnoon/repos","events_url":"https://api.github.com/users/cnoon/events{/privacy}","received_events_url":"https://api.github.com/users/cnoon/received_events","type":"User","site_admin":false},"open_issues":0,"closed_issues":2,"state":"open","created_at":"2016-07-19T06:01:33Z","updated_at":"2016-09-07T00:18:03Z","due_on":"2016-08-22T00:00:00Z","closed_at":null},"comments":4,"created_at":"2016-06-16T16:47:32Z","updated_at":"2016-09-07T00:18:03Z","closed_at":"2016-09-07T00:18:03Z","body":"I think this is basically the same issue as https://github.com/AFNetworking/AFNetworking/issues/3324 and https://github.com/AFNetworking/AFNetworking/pull/3325, so I'll reuse @florianschulz's words:\r\n\r\n> When you start downloading multiple images simultaneously, then immediately cancel these downloads and then start them again, some downloads fail with cancelled status. This seems to be tied to the value of the \"maximumActiveDownloads\" property of [ImageDownloader], since the number of attempted downloads has to be greater than this value in order to make some of the downloads fail. Increasing this value also solves the issue.\r\n\r\nI've ported his test case with a minor tweak: the `ImageDownloader.maximumActiveDownloads` is configured to always be less than the count of URLs we're testing.\r\n\r\n```swift\r\n/// Tests if a set of download requests can be started, then cancelled, and then successfully downloaded\r\nfunc testThatItCanDownloadAndCancelAndDownloadAgain() {\r\n    let expectation = expectationWithDescription(\"all downloads should complete\")\r\n    var successCounter = 0\r\n    \r\n    let imageURLs = [\r\n        NSURL(string: \"https://static.pexels.com/photos/1562/italian-landscape-mountains-nature.jpg\")!,\r\n        NSURL(string: \"https://static.pexels.com/photos/397/italian-landscape-mountains-nature.jpg\")!,\r\n        NSURL(string: \"https://static.pexels.com/photos/2698/dawn-landscape-mountains-nature.jpg\")!,\r\n        NSURL(string: \"https://static.pexels.com/photos/2946/dawn-nature-sunset-trees.jpg\")!,\r\n        NSURL(string: \"https://static.pexels.com/photos/5021/nature-sunset-person-woman.jpg\")!\r\n    ]\r\n    \r\n    let downloader = ImageDownloader(maximumActiveDownloads: imageURLs.count - 1)\r\n    \r\n    for url in imageURLs {\r\n        let receipt = downloader.downloadImage(URLRequest: NSURLRequest(URL: url), completion: nil)\r\n        downloader.cancelRequestForRequestReceipt(receipt!)\r\n    }\r\n    \r\n    for url in imageURLs {\r\n        downloader.downloadImage(URLRequest: NSURLRequest(URL: url), completion: { (response) in\r\n            switch response.result {\r\n            case .Success(_):\r\n                NSLog(\"success\")\r\n                successCounter = successCounter + 1\r\n                if successCounter == imageURLs.count {\r\n                    expectation.fulfill()\r\n                }\r\n            case .Failure(let error):\r\n                NSLog(\"failure: \\(error)\")\r\n                expectation.fulfill()\r\n            }\r\n        })\r\n    }\r\n    \r\n    waitForExpectationsWithTimeout(timeout * Double(imageURLs.count), handler: nil)\r\n    XCTAssertEqual(successCounter, imageURLs.count, \"At least one restarted request did not succeed\")\r\n}\r\n```\r\n\r\nThis fails using Xcode 7.3.1 testing against iOS 9.3 with AlamofireImage 2.4.0. I'm running into this problem when using the UIImageView extension on a collection view: certain collection view reloads or changes trigger this case which leaves some cells without an image.\r\n\r\nI think the problem is that it is currently possible to append an `operation` to a `responseHandler` that has been cancelled. eg in `responseHandler.operations.append(id: receiptID, filter: filter, completion: completion)`.\r\n\r\nI just found a better test case in AFNetworking that ensures the original requests cancel properly too: https://github.com/AFNetworking/AFNetworking/blob/master/Tests/Tests/AFImageDownloaderTests.m#L369"}}
{"actor":{"display_login":"cnoon"}}