Last active
August 29, 2015 14:04
-
-
Save nixta/a5df128557fe61a27223 to your computer and use it in GitHub Desktop.
Translating a delegate model to a closures model. Put these files in the same Swift module.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// AGSQueryTask.swift | |
// swift-samples | |
// | |
// Created by Eric Ito on 7/28/14. | |
// Copyright (c) 2014 Esri. All rights reserved. | |
// | |
import ArcGIS | |
// workaround for accessing closure wrapped in an enum | |
// https://devforums.apple.com/message/986308#986308 | |
struct Container<T> { | |
var closure: T | |
} | |
// this enum will have our closure types | |
enum QueryCallbackType { | |
case ExecuteClosure(Container<(featureSet: AGSFeatureSet?, error: NSError?) -> ()>) | |
case ExecuteWithIDsClosure(Container<(objectIDs: [Int]?, error: NSError?) -> ()>) | |
case ExecuteWithRelatedFeaturesClosure(Container<(relatedFeatures: [Int:[AGSFeatureSet]]?, error: NSError?) -> ()>) | |
case ExecuteFeatureCountClosure(Container<(featureCount: Int?, error: NSError?) -> ()>) | |
} | |
extension AGSQueryTask { | |
// create a private struct to hold our delegate handler | |
private struct Static { | |
static var instance: AGSQueryTaskDelegateHandler! = nil | |
static var token: dispatch_once_t = 0 | |
} | |
var delegateHandler: AGSQueryTaskDelegateHandler! { | |
get { | |
dispatch_once(&Static.token) { | |
Static.instance = AGSQueryTaskDelegateHandler() | |
self.delegate = Static.instance | |
} | |
return Static.instance! | |
} | |
set { | |
Static.instance = newValue | |
self.delegate = Static.instance | |
} | |
} | |
public func executeQuery(query: AGSQuery, withCompletion completion: (featureSet: AGSFeatureSet?, error: NSError?) -> ()) -> NSOperation? { | |
let op = self.executeWithQuery(query) | |
return self.delegateHandler.registerCallback(.ExecuteClosure(Container(closure: completion)), forOperation: op) | |
} | |
public func executeForIDsWithQuery(query: AGSQuery, withCompletion completion:(objectIDs: [Int]?, error: NSError?) -> ()) -> NSOperation? { | |
let op = self.executeForIdsWithQuery(query) | |
return self.delegateHandler.registerCallback(.ExecuteWithIDsClosure(Container(closure: completion)), forOperation: op) | |
} | |
public func executeWithRelationshipQuery(query: AGSRelationshipQuery, withCompletion completion:(relatedFeatures: [Int: [AGSFeatureSet]]?, error: NSError?) -> ()) -> NSOperation? { | |
let op = self.executeWithRelationshipQuery(query) | |
return self.delegateHandler.registerCallback(.ExecuteWithRelatedFeaturesClosure(Container(closure: completion)), forOperation: op) | |
} | |
public func executeFeatureCountWithQuery(query: AGSQuery, withCompletion completion:(count: Int?, error: NSError?) -> ()) -> NSOperation? { | |
let op = self.executeFeatureCountWithQuery(query) | |
return self.delegateHandler.registerCallback(.ExecuteFeatureCountClosure(Container(closure: completion)), forOperation: op) | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// AGSQueryTaskDelegateHandler.swift | |
// swift-samples | |
// | |
// Created by Eric Ito on 7/28/14. | |
// Copyright (c) 2014 Esri. All rights reserved. | |
// | |
import ArcGIS | |
private enum QueryResultsType { | |
case Execute((AGSFeatureSet?, NSError?)) | |
case ExecuteWithIDs(([Int]?, NSError?)) | |
case ExecuteWithRelatedFeatures(([Int:[AGSFeatureSet]]?, NSError?)) | |
case ExecuteFeatureCount((Int?, NSError?)) | |
} | |
// MARK: Internal Delegate Handler | |
internal class AGSQueryTaskDelegateHandler: NSObject, AGSQueryTaskDelegate { | |
// this will map our operation to our callback | |
private var callbacks: [Int:QueryCallbackType] = [Int:QueryCallbackType]() | |
internal func registerCallback(callback: QueryCallbackType, forOperation op: NSOperation) -> NSOperation { | |
self.callbacks[op.hash] = callback | |
return op | |
} | |
// MARK: AGSQueryTaskDelegate | |
// TODO: Why do we have to mark these delegate methods public?? | |
public func queryTask(queryTask: AGSQueryTask!, operation op: NSOperation!, didExecuteWithFeatureSetResult featureSet: AGSFeatureSet!) { | |
unpackAndFireCallbackForOperation(op, resultType: .Execute((featureSet, nil))) | |
} | |
public func queryTask(queryTask: AGSQueryTask!, operation op: NSOperation!, didFailWithError error: NSError!) { | |
unpackAndFireCallbackForOperation(op, resultType: .Execute((nil, error))) | |
} | |
public func queryTask(queryTask: AGSQueryTask!, operation op: NSOperation!, didExecuteWithObjectIds objectIds: [AnyObject]!) { | |
unpackAndFireCallbackForOperation(op, resultType: .ExecuteWithIDs((objectIds as? [Int], nil))) | |
} | |
public func queryTask(queryTask: AGSQueryTask!, operation op: NSOperation!, didFailQueryForIdsWithError error: NSError!) { | |
unpackAndFireCallbackForOperation(op, resultType: .ExecuteWithIDs((nil, error))) | |
} | |
public func queryTask(queryTask: AGSQueryTask!, operation op: NSOperation!, didExecuteWithRelatedFeatures relatedFeatures: [NSObject : AnyObject]!) { | |
unpackAndFireCallbackForOperation(op, resultType: .ExecuteWithRelatedFeatures((relatedFeatures as? [Int:[AGSFeatureSet]], nil))) | |
} | |
public func queryTask(queryTask: AGSQueryTask!, operation op: NSOperation!, didFailRelationshipQueryWithError error: NSError!) { | |
unpackAndFireCallbackForOperation(op, resultType: .ExecuteWithRelatedFeatures((nil, error))) | |
} | |
public func queryTask(queryTask: AGSQueryTask!, operation op: NSOperation!, didExecuteWithFeatureCount count: Int) { | |
unpackAndFireCallbackForOperation(op, resultType: .ExecuteFeatureCount((count, nil))) | |
} | |
public func queryTask(queryTask: AGSQueryTask!, operation op: NSOperation!, didFailQueryFeatureCountWithError error: NSError!) { | |
unpackAndFireCallbackForOperation(op, resultType: .ExecuteFeatureCount((nil, error))) | |
} | |
// MARK: Private | |
private func unpackAndFireCallbackForOperation(operation: NSOperation, resultType: QueryResultsType) { | |
switch resultType { | |
case .Execute(let (featureSet, error)): | |
fireCallbackForOperation(operation, values: (featureSet, error)) | |
case .ExecuteWithIDs(let (objectIDs, error)): | |
fireCallbackForOperation(operation, values: (objectIDs, error)) | |
case .ExecuteWithRelatedFeatures(let (relatedFeatures, error)): | |
fireCallbackForOperation(operation, values: (relatedFeatures, error)) | |
case .ExecuteFeatureCount(let (count, error)): | |
fireCallbackForOperation(operation, values: (count, error)) | |
} | |
} | |
private func fireCallbackForOperation(operation: NSOperation, values: (Any?, Any?)) { | |
if let callbackType = self.callbacks[operation.hash] as? QueryCallbackType { | |
switch callbackType { | |
case .ExecuteClosure(let container): | |
let (featureSet, error) = values | |
container.closure(featureSet: featureSet as? AGSFeatureSet, error: error as? NSError) | |
case .ExecuteWithIDsClosure(let container): | |
let (objectIDs, error) = values | |
container.closure(objectIDs: objectIDs as? [Int], error: error as? NSError) | |
case .ExecuteWithRelatedFeaturesClosure(let container): | |
container.closure(relatedFeatures: values.0 as? [Int:[AGSFeatureSet]], error: values.1 as? NSError) | |
case .ExecuteFeatureCountClosure(let container): | |
container.closure(featureCount: values.0 as? Int, error: values.1 as? NSError) | |
} | |
self.callbacks[operation.hash] = nil | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment