Fix crashing bug in FetchRequestQueue by making sure the completion is called not more than once from FetchRequestOperation. Fix #1133.
This commit is contained in:
parent
fcb0f0c439
commit
31a2afb067
|
@ -16,7 +16,7 @@ import Articles
|
||||||
|
|
||||||
typealias FetchRequestOperationResultBlock = (Set<Article>, FetchRequestOperation) -> Void
|
typealias FetchRequestOperationResultBlock = (Set<Article>, FetchRequestOperation) -> Void
|
||||||
|
|
||||||
class FetchRequestOperation {
|
final class FetchRequestOperation {
|
||||||
|
|
||||||
let id: Int
|
let id: Int
|
||||||
let resultBlock: FetchRequestOperationResultBlock
|
let resultBlock: FetchRequestOperationResultBlock
|
||||||
|
@ -35,8 +35,17 @@ class FetchRequestOperation {
|
||||||
precondition(Thread.isMainThread)
|
precondition(Thread.isMainThread)
|
||||||
precondition(!isFinished)
|
precondition(!isFinished)
|
||||||
|
|
||||||
if isCanceled {
|
var didCallCompletion = false
|
||||||
|
|
||||||
|
func callCompletionIfNeeded() {
|
||||||
|
if !didCallCompletion {
|
||||||
|
didCallCompletion = true
|
||||||
completion(self)
|
completion(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if isCanceled {
|
||||||
|
callCompletionIfNeeded()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,7 +53,7 @@ class FetchRequestOperation {
|
||||||
if articleFetchers.isEmpty {
|
if articleFetchers.isEmpty {
|
||||||
isFinished = true
|
isFinished = true
|
||||||
resultBlock(Set<Article>(), self)
|
resultBlock(Set<Article>(), self)
|
||||||
completion(self)
|
callCompletionIfNeeded()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,22 +61,21 @@ class FetchRequestOperation {
|
||||||
var fetchersReturned = 0
|
var fetchersReturned = 0
|
||||||
var fetchedArticles = Set<Article>()
|
var fetchedArticles = Set<Article>()
|
||||||
for articleFetcher in articleFetchers {
|
for articleFetcher in articleFetchers {
|
||||||
var didCallCompletion = false
|
|
||||||
articleFetcher.fetchArticlesAsync { (articles) in
|
articleFetcher.fetchArticlesAsync { (articles) in
|
||||||
precondition(Thread.isMainThread)
|
precondition(Thread.isMainThread)
|
||||||
if self.isCanceled {
|
guard !self.isCanceled else {
|
||||||
if !didCallCompletion {
|
callCompletionIfNeeded()
|
||||||
didCallCompletion = true
|
|
||||||
completion(self)
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert(!self.isFinished)
|
||||||
|
|
||||||
fetchedArticles.formUnion(articles)
|
fetchedArticles.formUnion(articles)
|
||||||
fetchersReturned += 1
|
fetchersReturned += 1
|
||||||
if fetchersReturned == numberOfFetchers {
|
if fetchersReturned == numberOfFetchers {
|
||||||
self.isFinished = true
|
self.isFinished = true
|
||||||
self.resultBlock(fetchedArticles, self)
|
self.resultBlock(fetchedArticles, self)
|
||||||
completion(self)
|
callCompletionIfNeeded()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ import Foundation
|
||||||
|
|
||||||
// Main thread only.
|
// Main thread only.
|
||||||
|
|
||||||
class FetchRequestQueue {
|
final class FetchRequestQueue {
|
||||||
|
|
||||||
private var pendingRequests = [FetchRequestOperation]()
|
private var pendingRequests = [FetchRequestOperation]()
|
||||||
private var currentRequest: FetchRequestOperation? = nil
|
private var currentRequest: FetchRequestOperation? = nil
|
||||||
|
@ -40,9 +40,8 @@ private extension FetchRequestQueue {
|
||||||
|
|
||||||
currentRequest = requestToRun
|
currentRequest = requestToRun
|
||||||
pendingRequests.removeFirst()
|
pendingRequests.removeFirst()
|
||||||
requestToRun.run { (fetchRequestOperation) in
|
currentRequest.run { (fetchRequestOperation) in
|
||||||
precondition(fetchRequestOperation === self.currentRequest)
|
precondition(fetchRequestOperation === self.currentRequest)
|
||||||
precondition(fetchRequestOperation === requestToRun)
|
|
||||||
self.currentRequest = nil
|
self.currentRequest = nil
|
||||||
self.runNextRequestIfNeeded()
|
self.runNextRequestIfNeeded()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue