fetchPlacesNearCoordinate
は(非同期的に実行されている)事前のリクエストをキャンセルしているので、あなたは最初の1が完了するまで、あなたが第2の要求を開始していないことを確認する必要があります。
それを行うための最も簡単な方法は、完了ハンドラである:
func fetchPlace(coordinate: CLLocationCoordinate2D, completionHandler:() ->()) {
let searchedTypes = ["cafe"]
let searchRadius: Double = 150
dataProvider.fetchPlacesNearCoordinate(coordinate, radius:searchRadius, types: searchedTypes) { places in
for place: GooglePlace in places {
print(place)
completionHandler()
}
}
}
そして、あなたが行うことができます。
fetchPlace(CLLocationCoordinate2DMake(40.725203800000003, -74.011287899999999)) {
self.fetchPlace(CLLocationCoordinate2DMake(40.760920499999997, -73.988664700000001)) {
print("done with both requests")
}
}
より複雑な、まだ多くの一般的な解決策は、になりますこのフェッチを非同期のNSOperation
サブクラスにラップし、これらの要求をフェッチ要求専用のシリアルキューに追加することができます。それがどうなっているのかを知る必要がある場合は、私に知らせてください。例えば
:
let fetchQueue: NSOperationQueue = {
let queue = NSOperationQueue()
queue.name = "com.domain.app.fetch"
queue.maxConcurrentOperationCount = 1
return queue
}()
let provider = GoogleDataProvider()
override func viewDidLoad() {
super.viewDidLoad()
let completionOperation = NSBlockOperation() {
print("done with both requests")
}
let coordinate1 = CLLocationCoordinate2DMake(40.725203800000003, -74.011287899999999)
let operation1 = FetchOperation(provider: provider, coordinate: coordinate1)
completionOperation.addDependency(operation1)
fetchQueue.addOperation(operation1)
let coordinate2 = CLLocationCoordinate2DMake(40.760920499999997, -73.988664700000001)
let operation2 = FetchOperation(provider: provider, coordinate: coordinate2)
completionOperation.addDependency(operation2)
fetchQueue.addOperation(operation2)
NSOperationQueue.mainQueue().addOperation(completionOperation)
}
:
class FetchOperation: AsynchronousOperation {
let provider: GoogleDataProvider
let coordinate: CLLocationCoordinate2D
init(provider: GoogleDataProvider, coordinate: CLLocationCoordinate2D) {
self.provider = provider
self.coordinate = coordinate
}
override func main() {
fetchPlace(coordinate)
}
func fetchPlace(coordinate: CLLocationCoordinate2D) {
let searchedTypes = ["cafe"]
let searchRadius: Double = 150
provider.fetchPlacesNearCoordinate(coordinate, radius:searchRadius, types: searchedTypes) { places in
for place: GooglePlace in places {
print(place)
self.completeOperation()
}
}
}
}
そして:
//
// AsynchronousOperation.swift
//
// Created by Robert Ryan on 9/20/14.
// Copyright (c) 2014 Robert Ryan. All rights reserved.
//
import Foundation
/// Asynchronous Operation base class
///
/// This class performs all of the necessary KVN of `isFinished` and
/// `isExecuting` for a concurrent `NSOperation` subclass. So, to developer
/// a concurrent NSOperation subclass, you instead subclass this class which:
///
/// - must override `main()` with the tasks that initiate the asynchronous task;
///
/// - must call `completeOperation()` function when the asynchronous task is done;
///
/// - optionally, periodically check `self.cancelled` status, performing any clean-up
/// necessary and then ensuring that `completeOperation()` is called; or
/// override `cancel` method, calling `super.cancel()` and then cleaning-up
/// and ensuring `completeOperation()` is called.
public class AsynchronousOperation : NSOperation {
override public var asynchronous: Bool { return true }
private let stateLock = NSLock()
private var _executing: Bool = false
override private(set) public var executing: Bool {
get {
return stateLock.withCriticalScope { _executing }
}
set {
willChangeValueForKey("isExecuting")
stateLock.withCriticalScope { _executing = newValue }
didChangeValueForKey("isExecuting")
}
}
private var _finished: Bool = false
override private(set) public var finished: Bool {
get {
return stateLock.withCriticalScope { _finished }
}
set {
willChangeValueForKey("isFinished")
stateLock.withCriticalScope { _finished = newValue }
didChangeValueForKey("isFinished")
}
}
/// Complete the operation
///
/// This will result in the appropriate KVN of isFinished and isExecuting
public func completeOperation() {
if executing {
executing = false
}
if !finished {
finished = true
}
}
override public func start() {
if cancelled {
finished = true
return
}
executing = true
main()
}
override public func main() {
fatalError("subclasses must override `main`")
}
}
/// Asynchronous Operation base class
///
/// This class lets you perform asynchronous block operation. Make sure that the
/// the provided `block` calls `completeOperation`, or else this operation will
/// never finish.
public class AsynchronousBlockOperation : AsynchronousOperation {
private var block:((AsynchronousOperation) ->())?
init(block:(AsynchronousOperation) ->()) {
self.block = block
super.init()
}
override public func main() {
block?(self)
}
override public func completeOperation() {
block = nil
super.completeOperation()
}
}
/*
Copyright (C) 2015 Apple Inc. All Rights Reserved.
See LICENSE.txt for this sample’s licensing information
Abstract:
An extension to `NSLock` to simplify executing critical code.
From Advanced NSOperations sample code in WWDC 2015 https://developer.apple.com/videos/play/wwdc2015/226/
From https://developer.apple.com/sample-code/wwdc/2015/downloads/Advanced-NSOperations.zip
*/
import Foundation
extension NSLock {
/// Perform closure within lock.
///
/// An extension to `NSLock` to simplify executing critical code.
///
/// - parameter block: The closure to be performed.
func withCriticalScope<T>(@noescape block: Void -> T) -> T {
lock()
let value = block()
unlock()
return value
}
}
あなたは正しい、fetchPlaces'が非同期である 'ことを理解していますか?したがって、2回目の電話が来る前に何かを印刷する時間がありません。 – matt
'self.fetchPlaceOnTheWayHome'は' fetchPlace'という関数を呼び出さないので、ここではまったく別のことが起こっているかもしれません。 – matt
@matt woops私はそれを修正しました。あなたはそれを私が想像しているように動作するように変更する方法を学ぶ方向で私を指摘できますか? – tryingtolearn