Skip to content

Commit cc0fd46

Browse files
committed
Add utility code for OSX to register to URL event
Add struct to create easily exception Add utility var into FailureCallbackErrorType Append query to NSURLComponents
1 parent 5376ef6 commit cc0fd46

File tree

5 files changed

+91
-36
lines changed

5 files changed

+91
-36
lines changed

CallbackURLKit/CallbackURLKit.swift

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,33 @@ public protocol FailureCallbackErrorType: ErrorType {
6464
var code: Int {get}
6565
var message: String {get}
6666
}
67+
extension FailureCallbackErrorType {
68+
public var XCUErrorParameters: Parameters {
69+
return [kXCUErrorCode: "\(self.code)", kXCUErrorMessage: self.message]
70+
}
71+
public var XCUErrorQuery: String {
72+
return XCUErrorParameters.query
73+
}
74+
}
6775

68-
let CallbackURLKitErrorDomain = "CallbackURLKit"
69-
public let ErrorNotSupportedAction = 1 // "(action) not supported by (appName)"
70-
public let ErrorMissingParameter = 2 // when handling an action, could return an error to show that parameters are missing
71-
public let ErrorMissingErrorCode = 3
76+
public struct Error {
77+
public static let Domain = "CallbackURLKit.error"
78+
79+
/// The custom error codes generated by Alamofire.
80+
public enum Code: Int {
81+
case NotSupportedAction = 1 // "(action) not supported by (appName)"
82+
case MissingParameter = 2 // when handling an action, could return an error to show that parameters are missing
83+
case MissingErrorCode = 3
84+
}
85+
86+
public static func errorWithCode(code: Code, failureReason: String) -> NSError {
87+
return errorWithCode(code.rawValue, failureReason: failureReason)
88+
}
89+
public static func errorWithCode(code: Int, failureReason: String) -> NSError {
90+
let userInfo = [NSLocalizedFailureReasonErrorKey: failureReason]
91+
return NSError(domain: Domain, code: code, userInfo: userInfo)
92+
}
93+
}
7294

7395
extension NSError: FailureCallbackErrorType {
7496
public var message: String { return localizedDescription }

CallbackURLKit/Client.swift

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -76,15 +76,9 @@ public class Client {
7676
if let c = code, ci = Int(c) {
7777
codeInt = ci
7878
} else {
79-
codeInt = ErrorMissingErrorCode
79+
codeInt = Error.Code.MissingErrorCode.rawValue
8080
}
81-
82-
var userInfo = [String: String]()
83-
if let msg = message {
84-
userInfo[NSLocalizedDescriptionKey] = msg
85-
}
86-
87-
return NSError(domain: CallbackURLKitErrorDomain, code: codeInt, userInfo: userInfo)
81+
return Error.errorWithCode(codeInt, failureReason: message ?? "")
8882
}
8983

9084
}

CallbackURLKit/Extensions.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,3 +73,18 @@ extension Dictionary {
7373

7474
}
7575
func +<K, V> (left: [K : V], right: [K : V]) -> [K : V] { return left.join(right) }
76+
77+
78+
extension NSURLComponents {
79+
func addToQuery(add: String) {
80+
if let query = self.query {
81+
self.query = query + "&" + add
82+
} else {
83+
self.query = add
84+
}
85+
}
86+
87+
}
88+
89+
func &= (left: NSURLComponents, right: String) { left.addToQuery(right) }
90+

CallbackURLKit/Manager.swift

Lines changed: 43 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,8 @@ public class Manager {
6969

7070
let action = String(path.characters.dropFirst()) // remove /
7171

72-
var parameters = url.query?.parseURLParams ?? [:]
73-
let actionParameters = Manager.filterProtocolParameters(parameters)
72+
let parameters = url.query?.parseURLParams ?? [:]
73+
let actionParameters = Manager.actionParameters(parameters)
7474

7575
// is a reponse?
7676
if action == kResponse {
@@ -98,7 +98,7 @@ public class Manager {
9898
// returnParams
9999
let comp = NSURLComponents(URL: url, resolvingAgainstBaseURL: false)!
100100
if let query = returnParams?.query {
101-
comp.query = (comp.query ?? "") + query
101+
comp &= query
102102
}
103103
if let newURL = comp.URL {
104104
Manager.openURL(newURL)
@@ -107,13 +107,8 @@ public class Manager {
107107
}
108108
let failureCallback = { (error: FailureCallbackErrorType) in
109109
if let urlString = parameters[kXCUError], url = NSURL(string: urlString) {
110-
111-
var errorParams: Parameters = [:]
112-
errorParams[kXCUErrorCode] = "\(error.code)"
113-
errorParams[kXCUErrorMessage] = error.message
114-
115110
let comp = NSURLComponents(URL: url, resolvingAgainstBaseURL: false)!
116-
comp.query = (comp.query ?? "") + errorParams.query
111+
comp &= error.XCUErrorQuery
117112
if let newURL = comp.URL {
118113
Manager.openURL(newURL)
119114
}
@@ -131,12 +126,10 @@ public class Manager {
131126
else {
132127
// unknown action, notifiy it
133128
if let errorURLString = parameters[kXCUError], url = NSURL(string: errorURLString) {
134-
var errorParams: Parameters = [:]
135-
errorParams[kXCUErrorCode] = "\(ErrorNotSupportedAction)"
136-
errorParams[kXCUErrorMessage] = "\(action) not supported by \(Manager.appName)"
137-
129+
let error = Error.errorWithCode(.NotSupportedAction, failureReason: "\(action) not supported by \(Manager.appName)")
130+
138131
let comp = NSURLComponents(URL: url, resolvingAgainstBaseURL: false)!
139-
comp.query = (comp.query ?? "") + errorParams.query
132+
comp &= error.XCUErrorQuery
140133
if let newURL = comp.URL {
141134
Manager.openURL(newURL)
142135
}
@@ -145,6 +138,11 @@ public class Manager {
145138
}
146139
return false
147140
}
141+
142+
// Handle url with manager shared instance
143+
public static func handleOpenURL(url: NSURL) -> Bool {
144+
return self.sharedInstance.handleOpenURL(url)
145+
}
148146

149147
// MARK: - perform action with temporary client
150148

@@ -174,8 +172,13 @@ public class Manager {
174172
guard let urlTypes = NSBundle.mainBundle().infoDictionary?["CFBundleURLTypes"] as? [[String: AnyObject]] else {
175173
return nil
176174
}
177-
let schemes = urlTypes.flatMap{ $0["CFBundleURLSchemes"] }
178-
return schemes as? [String]
175+
var result = [String]()
176+
for urlType in urlTypes {
177+
if let schemes = urlType["CFBundleURLSchemes"] as? [String] {
178+
result += schemes
179+
}
180+
}
181+
return result.isEmpty ? nil : result
179182
}
180183

181184
// MARK: internal
@@ -194,10 +197,8 @@ public class Manager {
194197
xcuComponents.scheme = scheme
195198
xcuComponents.host = kXCUHost
196199
xcuComponents.path = kResponse
197-
198-
199-
var xcuParams: Parameters = [:]
200-
xcuParams[kRequestID] = request.ID
200+
201+
let xcuParams: Parameters = [kRequestID: request.ID]
201202

202203
if request.successCallback != nil {
203204
xcuComponents.query = (xcuParams + [kResponseType: ResponseType.success.rawValue]).query
@@ -227,12 +228,12 @@ public class Manager {
227228
Manager.openURL(URL)
228229
}
229230

230-
static func filterProtocolParameters(dictionary: [String : String]) -> [String : String] {
231-
let resultArray: [(String, String)] = dictionary.filter { tuple in
231+
static func actionParameters(parameters: [String : String]) -> [String : String] {
232+
let resultArray: [(String, String)] = parameters.filter { tuple in
232233
return !(tuple.0.hasPrefix(kXCUPrefix) || protocolKeys.contains(tuple.0))
233234
}
234235
var result = [String: String](resultArray)
235-
if let source = dictionary[kXCUSource] {
236+
if let source = parameters[kXCUSource] {
236237
result[kXCUSource] = source
237238
}
238239
return result
@@ -253,4 +254,22 @@ public class Manager {
253254
return NSBundle.mainBundle().infoDictionary?["CFBundleDisplayName"] as? String ?? "CallbackURLKit"
254255
}
255256

256-
}
257+
}
258+
259+
260+
#if os(OSX)
261+
extension Manager {
262+
263+
public func registerToURLEvent() {
264+
NSAppleEventManager.sharedAppleEventManager().setEventHandler(self, andSelector:"handleGetURLEvent:withReplyEvent:", forEventClass: AEEventClass(kInternetEventClass), andEventID: AEEventID(kAEGetURL))
265+
}
266+
267+
public func handleGetURLEvent(event: NSAppleEventDescriptor!, withReplyEvent replyEvent: NSAppleEventDescriptor!)
268+
{
269+
if let urlString = event.paramDescriptorForKeyword(AEKeyword(keyDirectObject))?.stringValue, url = NSURL(string: urlString) {
270+
handleOpenURL(url)
271+
}
272+
}
273+
274+
}
275+
#endif

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,11 @@ func handleGetURLEvent(event: NSAppleEventDescriptor!, withReplyEvent: NSAppleEv
125125
}
126126
}
127127
```
128+
Or if you have no other need with URL events you can let manager do all the job by calling into `applicationDidFinishLaunching`
129+
```swift
130+
manager.registerToURLEvent()
131+
```
132+
128133
#### Add new action
129134
The client application will interact with your application using the following URL Structure.
130135
`[url-scheme]://x-callback-url/[action]?[x-callback parameters]&[action parameters]`

0 commit comments

Comments
 (0)