From df27538cafc96545c83c8f22c5502ad27e7f6498 Mon Sep 17 00:00:00 2001 From: phimage Date: Sat, 20 Aug 2016 17:50:13 +0200 Subject: [PATCH] Fix #3 by encoding correctly the query parameters into callback urls --- CallbackURLKit.podspec | 2 +- CallbackURLKit/CallbackURLKit.swift | 2 +- CallbackURLKit/Extensions.swift | 61 ++++++++++++++---- CallbackURLKit/Manager.swift | 62 +++++++++---------- CallbackURLKit/Request.swift | 32 +++++++++- README.md | 17 +---- .../project.pbxproj | 24 +++---- .../CallbackURLKitDemo/AppDelegate.swift | 35 ++++++----- .../Base.lproj/Main.storyboard | 21 +++++-- .../CallbackURLKitDemo.swift | 56 +++++++++++++++++ SampleApp/CallbackURLKitDemo/Info.plist | 1 + SampleApp/CallbackURLKitDemo/Shared.swift | 25 -------- .../CallbackURLKitDemo/ViewController.swift | 42 ++++++++++--- .../CallbackURLKitDemoOSX/AppDelegate.swift | 40 ------------ .../Base.lproj/Main.storyboard | 26 ++++++-- .../ViewController.swift | 42 ------------- 16 files changed, 266 insertions(+), 222 deletions(-) create mode 100644 SampleApp/CallbackURLKitDemo/CallbackURLKitDemo.swift delete mode 100644 SampleApp/CallbackURLKitDemo/Shared.swift delete mode 100644 SampleApp/CallbackURLKitDemoOSX/AppDelegate.swift delete mode 100644 SampleApp/CallbackURLKitDemoOSX/ViewController.swift diff --git a/CallbackURLKit.podspec b/CallbackURLKit.podspec index d8f63af..1c34ab7 100644 --- a/CallbackURLKit.podspec +++ b/CallbackURLKit.podspec @@ -2,7 +2,7 @@ Pod::Spec.new do |s| # ――― Spec Metadata ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # s.name = "CallbackURLKit" - s.version = "0.1.2" + s.version = "0.2.0" s.summary = "Implemenation of x-callback-url in swift" s.homepage = "https://github.com/phimage/CallbackURLKit" diff --git a/CallbackURLKit/CallbackURLKit.swift b/CallbackURLKit/CallbackURLKit.swift index bf994d5..5bd4139 100644 --- a/CallbackURLKit/CallbackURLKit.swift +++ b/CallbackURLKit/CallbackURLKit.swift @@ -69,7 +69,7 @@ extension FailureCallbackErrorType { return [kXCUErrorCode: "\(self.code)", kXCUErrorMessage: self.message] } public var XCUErrorQuery: String { - return XCUErrorParameters.query + return XCUErrorParameters.queryString } } diff --git a/CallbackURLKit/Extensions.swift b/CallbackURLKit/Extensions.swift index a7635a2..8b5dc29 100644 --- a/CallbackURLKit/Extensions.swift +++ b/CallbackURLKit/Extensions.swift @@ -23,8 +23,10 @@ SOFTWARE. import Foundation +// MARK: String extension String { - var parseURLParams: [String : String] { + + var toQueryDictionary: [String : String] { var result: [String : String] = [String : String]() let pairs: [String] = self.componentsSeparatedByString("&") for pair in pairs { @@ -32,28 +34,47 @@ extension String { if comps.count >= 2 { let key = comps[0] let value = comps.dropFirst().joinWithSeparator("=") - result[key] = value.stringByRemovingPercentEncoding + result[key.queryDecode] = value.queryDecode } } return result } + var queryEncodeRFC3986: String { + let generalDelimitersToEncode = ":#[]@" // does not include "?" or "/" due to RFC 3986 - Section 3.4 + let subDelimitersToEncode = "!$&'()*+,;=" + + let allowedCharacterSet = NSCharacterSet.URLQueryAllowedCharacterSet().mutableCopy() as! NSMutableCharacterSet + allowedCharacterSet.removeCharactersInString(generalDelimitersToEncode + subDelimitersToEncode) + + return self.stringByAddingPercentEncodingWithAllowedCharacters(allowedCharacterSet) ?? self + } + + var queryEncode: String { + return self.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet()) ?? self + } + + var queryDecode: String { + return self.stringByRemovingPercentEncoding ?? self + } + } +// MARK: Dictionary extension Dictionary { - var query: String { + var queryString: String { var parts = [String]() for (key, value) in self { - let keyString = "\(key)".stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())! - let valueString = "\(value)".stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())! + let keyString = "\(key)".queryEncodeRFC3986 + let valueString = "\(value)".queryEncodeRFC3986 let query = "\(keyString)=\(valueString)" parts.append(query) } return parts.joinWithSeparator("&") as String } - func join(other: Dictionary) -> Dictionary { + private func join(other: Dictionary) -> Dictionary { var joinedDictionary = Dictionary() for (key, value) in self { @@ -78,16 +99,34 @@ extension Dictionary { func + (left: [K : V], right: [K : V]) -> [K : V] { return left.join(right) } +// MARK: NSURLComponents extension NSURLComponents { - func addToQuery(add: String) { - if let query = self.query { - self.query = query + "&" + add + + var queryDictionary: [String: String] { + get { + guard let query = self.query else { + return [:] + } + return query.toQueryDictionary + } + set { + if newValue.isEmpty { + self.query = nil + } else { + self.percentEncodedQuery = newValue.queryString + } + } + } + + private func addToQuery(add: String) { + if let query = self.percentEncodedQuery { + self.percentEncodedQuery = query + "&" + add } else { - self.query = add + self.percentEncodedQuery = add } } } -func &= (left: NSURLComponents, right: String) { left.addToQuery(right) } +func &= (left: NSURLComponents, right: String) { left.addToQuery(right) } diff --git a/CallbackURLKit/Manager.swift b/CallbackURLKit/Manager.swift index f19fc7e..8912715 100644 --- a/CallbackURLKit/Manager.swift +++ b/CallbackURLKit/Manager.swift @@ -69,7 +69,7 @@ public class Manager { let action = String(path.characters.dropFirst()) // remove / - let parameters = url.query?.parseURLParams ?? [:] + let parameters = url.query?.toQueryDictionary ?? [:] let actionParameters = Manager.actionParameters(parameters) // is a reponse? @@ -93,31 +93,20 @@ public class Manager { return false } else if let actionHandler = actions[action] { // handle the action - let successCallback = { (returnParams: Parameters?) in - if let urlString = parameters[kXCUSuccess], url = NSURL(string: urlString) { - // returnParams - let comp = NSURLComponents(URL: url, resolvingAgainstBaseURL: false)! - if let query = returnParams?.query { + let successCallback: SuccessCallback = { [weak self] returnParams in + self?.openCallback(parameters, type: .success) { comp in + if let query = returnParams?.queryString { comp &= query } - if let newURL = comp.URL { - Manager.openURL(newURL) - } } } - let failureCallback = { (error: FailureCallbackErrorType) in - if let urlString = parameters[kXCUError], url = NSURL(string: urlString) { - let comp = NSURLComponents(URL: url, resolvingAgainstBaseURL: false)! + let failureCallback: FailureCallback = { [weak self] error in + self?.openCallback(parameters, type: .error) { comp in comp &= error.XCUErrorQuery - if let newURL = comp.URL { - Manager.openURL(newURL) - } } } - let cancelCallback = { - if let urlString = parameters[kXCUCancel], url = NSURL(string: urlString) { - Manager.openURL(url) - } + let cancelCallback: CancelCallback = { [weak self] in + self?.openCallback(parameters, type: .cancel) } actionHandler(actionParameters, successCallback, failureCallback, cancelCallback) @@ -138,6 +127,16 @@ public class Manager { } return false } + + private func openCallback(parameters: [String : String], type: ResponseType, handler: ((NSURLComponents) -> Void)? = nil ) { + if let urlString = parameters[type.key], url = NSURL(string: urlString), + comp = NSURLComponents(URL: url, resolvingAgainstBaseURL: false) { + handler?(comp) + if let newURL = comp.URL { + Manager.openURL(newURL) + } + } + } // Handle url with manager shared instance public static func handleOpenURL(url: NSURL) -> Bool { @@ -183,6 +182,7 @@ public class Manager { // MARK: internal + func sendRequest(request: Request) throws { if !request.client.appInstalled { throw CallbackURLKitError.AppWithSchemeNotInstalled(scheme: request.client.URLScheme) @@ -199,17 +199,12 @@ public class Manager { xcuComponents.path = "/" + kResponse let xcuParams: Parameters = [kRequestID: request.ID] - - if request.successCallback != nil { - xcuComponents.query = (xcuParams + [kResponseType: ResponseType.success.rawValue]).query - query[kXCUSuccess] = xcuComponents.URL?.absoluteString ?? "" - - xcuComponents.query = (xcuParams + [kResponseType: ResponseType.cancel.rawValue]).query - query[kXCUCancel] = xcuComponents.URL?.absoluteString ?? "" - } - if request.failureCallback != nil { - xcuComponents.query = (xcuParams + [kResponseType: ResponseType.error.rawValue]).query - query[kXCUError] = xcuComponents.URL?.absoluteString ?? "" + + for reponseType in request.responseTypes { + xcuComponents.queryDictionary = xcuParams + [kResponseType: reponseType.rawValue] + if let urlString = xcuComponents.URL?.absoluteString { + query[reponseType.key] = urlString + } } if request.hasCallback { @@ -248,7 +243,7 @@ public class Manager { } static var appName: String { - if let appName = NSBundle.mainBundle().localizedInfoDictionary?["CFBundleDisplayName"] as? String{ + if let appName = NSBundle.mainBundle().localizedInfoDictionary?["CFBundleDisplayName"] as? String { return appName } return NSBundle.mainBundle().infoDictionary?["CFBundleDisplayName"] as? String ?? "CallbackURLKit" @@ -261,11 +256,10 @@ public class Manager { extension Manager { public func registerToURLEvent() { - NSAppleEventManager.sharedAppleEventManager().setEventHandler(self, andSelector:"handleGetURLEvent:withReplyEvent:", forEventClass: AEEventClass(kInternetEventClass), andEventID: AEEventID(kAEGetURL)) + NSAppleEventManager.sharedAppleEventManager().setEventHandler(self, andSelector: #selector(Manager.handleURLEvent(_:withReply:)), forEventClass: AEEventClass(kInternetEventClass), andEventID: AEEventID(kAEGetURL)) } - public func handleGetURLEvent(event: NSAppleEventDescriptor!, withReplyEvent replyEvent: NSAppleEventDescriptor!) - { + @objc public func handleURLEvent(event: NSAppleEventDescriptor, withReply replyEvent: NSAppleEventDescriptor) { if let urlString = event.paramDescriptorForKeyword(AEKeyword(keyDirectObject))?.stringValue, url = NSURL(string: urlString) { handleOpenURL(url) } diff --git a/CallbackURLKit/Request.swift b/CallbackURLKit/Request.swift index f65bb4d..d4aff13 100644 --- a/CallbackURLKit/Request.swift +++ b/CallbackURLKit/Request.swift @@ -41,7 +41,7 @@ struct Request { components.scheme = self.client.URLScheme components.host = kXCUHost components.path = "/\(self.action)" - components.query = (parameters + query).query + components.queryDictionary = (parameters + query) return components } @@ -49,10 +49,36 @@ struct Request { return successCallback != nil || failureCallback != nil || cancelCallback != nil } -} + var responseTypes: [ResponseType] { + var responseTypes = [ResponseType]() + if self.successCallback != nil { + responseTypes.append(.success) + } + if self.cancelCallback != nil { + responseTypes.append(.cancel) + } + if self.failureCallback != nil { + responseTypes.append(.error) + } + return responseTypes + } +} +// Callback response type enum ResponseType: String { case success case error case cancel -} \ No newline at end of file + + var key: String { + switch self { + case .success: + return kXCUSuccess + case .error: + return kXCUError + case .cancel: + return kXCUCancel + } + } +} + diff --git a/README.md b/README.md index 5dfef37..1559427 100644 --- a/README.md +++ b/README.md @@ -113,21 +113,8 @@ func application(application: UIApplication, openURL url: NSURL, sourceApplicati return true } ``` -On OSX -```swift -func applicationDidFinishLaunching(aNotification: NSNotification) { - ... - NSAppleEventManager.sharedAppleEventManager().setEventHandler(self, andSelector:"handleGetURLEvent:withReplyEvent:", forEventClass: AEEventClass(kInternetEventClass), andEventID: AEEventID(kAEGetURL)) -} -func handleGetURLEvent(event: NSAppleEventDescriptor!, withReplyEvent: NSAppleEventDescriptor!) { - if let urlString = event.paramDescriptorForKeyword(AEKeyword(keyDirectObject))?.stringValue, url = NSURL(string: urlString) { - manager.handleOpenURL(url) - } -} -``` -Or in OSX if you have no other need with URL events you can let manager do all the job by calling into `applicationDidFinishLaunching` -the method `Manager.registerToURLEvent()` - +On OSX if you have no other need with URL events you can let manager do all the job by calling into `applicationDidFinishLaunching` +the method `Manager.instance.registerToURLEvent()` #### Add new action The client application will interact with your application using the following URL Structure. diff --git a/SampleApp/CallbackURLKitDemo.xcodeproj/project.pbxproj b/SampleApp/CallbackURLKitDemo.xcodeproj/project.pbxproj index dbb857c..95dd60a 100644 --- a/SampleApp/CallbackURLKitDemo.xcodeproj/project.pbxproj +++ b/SampleApp/CallbackURLKitDemo.xcodeproj/project.pbxproj @@ -9,10 +9,10 @@ /* Begin PBXBuildFile section */ 2D82E9831C46ED3DB8D898C8 /* Pods_CallbackURLKitDemoOSX.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BEFE74F8F5010842B34724E9 /* Pods_CallbackURLKitDemoOSX.framework */; }; 574DDA2DC910102F338C8BDB /* Pods_CallbackURLKitDemo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 899A43CB2504DC3678E479C9 /* Pods_CallbackURLKitDemo.framework */; }; - C46E5DA31C399EBF0061E818 /* Shared.swift in Sources */ = {isa = PBXBuildFile; fileRef = C46E5DA21C399EBF0061E818 /* Shared.swift */; }; - C46E5DA41C399EBF0061E818 /* Shared.swift in Sources */ = {isa = PBXBuildFile; fileRef = C46E5DA21C399EBF0061E818 /* Shared.swift */; }; - C4A4AA871C399A1500932E7D /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4A4AA861C399A1500932E7D /* AppDelegate.swift */; }; - C4A4AA891C399A1500932E7D /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4A4AA881C399A1500932E7D /* ViewController.swift */; }; + C46E5DA31C399EBF0061E818 /* CallbackURLKitDemo.swift in Sources */ = {isa = PBXBuildFile; fileRef = C46E5DA21C399EBF0061E818 /* CallbackURLKitDemo.swift */; }; + C46E5DA41C399EBF0061E818 /* CallbackURLKitDemo.swift in Sources */ = {isa = PBXBuildFile; fileRef = C46E5DA21C399EBF0061E818 /* CallbackURLKitDemo.swift */; }; + C47767001D68B01E00A66C25 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4E32D6B1C3999AE005CD033 /* AppDelegate.swift */; }; + C47767011D68B08000A66C25 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4E32D6D1C3999AE005CD033 /* ViewController.swift */; }; C4A4AA8E1C399A1500932E7D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C4A4AA8C1C399A1500932E7D /* Main.storyboard */; }; C4E32D6C1C3999AE005CD033 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4E32D6B1C3999AE005CD033 /* AppDelegate.swift */; }; C4E32D6E1C3999AE005CD033 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4E32D6D1C3999AE005CD033 /* ViewController.swift */; }; @@ -26,10 +26,8 @@ 899A43CB2504DC3678E479C9 /* Pods_CallbackURLKitDemo.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_CallbackURLKitDemo.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 94ACDE1068C6A2C95BE32518 /* Pods-CallbackURLKitDemo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CallbackURLKitDemo.release.xcconfig"; path = "Pods/Target Support Files/Pods-CallbackURLKitDemo/Pods-CallbackURLKitDemo.release.xcconfig"; sourceTree = ""; }; BEFE74F8F5010842B34724E9 /* Pods_CallbackURLKitDemoOSX.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_CallbackURLKitDemoOSX.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - C46E5DA21C399EBF0061E818 /* Shared.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Shared.swift; sourceTree = ""; }; + C46E5DA21C399EBF0061E818 /* CallbackURLKitDemo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CallbackURLKitDemo.swift; sourceTree = ""; }; C4A4AA841C399A1500932E7D /* CallbackURLKitDemoOSX.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CallbackURLKitDemoOSX.app; sourceTree = BUILT_PRODUCTS_DIR; }; - C4A4AA861C399A1500932E7D /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - C4A4AA881C399A1500932E7D /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; C4A4AA8D1C399A1500932E7D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; C4A4AA8F1C399A1500932E7D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; C4E32D681C3999AE005CD033 /* CallbackURLKitDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CallbackURLKitDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -84,8 +82,6 @@ C4A4AA851C399A1500932E7D /* CallbackURLKitDemoOSX */ = { isa = PBXGroup; children = ( - C4A4AA861C399A1500932E7D /* AppDelegate.swift */, - C4A4AA881C399A1500932E7D /* ViewController.swift */, C4A4AA8C1C399A1500932E7D /* Main.storyboard */, C4A4AA8F1C399A1500932E7D /* Info.plist */, ); @@ -115,12 +111,12 @@ C4E32D6A1C3999AE005CD033 /* CallbackURLKitDemo */ = { isa = PBXGroup; children = ( + C46E5DA21C399EBF0061E818 /* CallbackURLKitDemo.swift */, C4E32D6B1C3999AE005CD033 /* AppDelegate.swift */, C4E32D6D1C3999AE005CD033 /* ViewController.swift */, C4E32D6F1C3999AE005CD033 /* Main.storyboard */, C4E32D741C3999AE005CD033 /* LaunchScreen.storyboard */, C4E32D771C3999AE005CD033 /* Info.plist */, - C46E5DA21C399EBF0061E818 /* Shared.swift */, ); path = CallbackURLKitDemo; sourceTree = ""; @@ -323,9 +319,9 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - C46E5DA41C399EBF0061E818 /* Shared.swift in Sources */, - C4A4AA891C399A1500932E7D /* ViewController.swift in Sources */, - C4A4AA871C399A1500932E7D /* AppDelegate.swift in Sources */, + C47767001D68B01E00A66C25 /* AppDelegate.swift in Sources */, + C46E5DA41C399EBF0061E818 /* CallbackURLKitDemo.swift in Sources */, + C47767011D68B08000A66C25 /* ViewController.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -333,7 +329,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - C46E5DA31C399EBF0061E818 /* Shared.swift in Sources */, + C46E5DA31C399EBF0061E818 /* CallbackURLKitDemo.swift in Sources */, C4E32D6E1C3999AE005CD033 /* ViewController.swift in Sources */, C4E32D6C1C3999AE005CD033 /* AppDelegate.swift in Sources */, ); diff --git a/SampleApp/CallbackURLKitDemo/AppDelegate.swift b/SampleApp/CallbackURLKitDemo/AppDelegate.swift index 359758f..f47bf11 100644 --- a/SampleApp/CallbackURLKitDemo/AppDelegate.swift +++ b/SampleApp/CallbackURLKitDemo/AppDelegate.swift @@ -6,41 +6,42 @@ // Copyright © 2016 phimage. All rights reserved. // -import UIKit import CallbackURLKit - +#if os(iOS) +import UIKit @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { - var window: UIWindow? - - func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { - let manager = Manager.sharedInstance manager.callbackURLScheme = Manager.URLSchemes?.first - - - manager["print"] = { parameters, success, failed, cancel in - if let text = parameters["text"] { - print(text) - success(nil) - } else { - failed(DemoErrorType.NoText) - } - } + manager[CallbackURLKitDemo.PrintActionString] = CallbackURLKitDemo.PrintAction return true } - func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject) -> Bool { Manager.sharedInstance.handleOpenURL(url) return true } +} + +#elseif os(OSX) +import Cocoa + +@NSApplicationMain +class AppDelegate: NSObject, NSApplicationDelegate { + func applicationDidFinishLaunching(aNotification: NSNotification) { + let manager = Manager.sharedInstance + manager.registerToURLEvent() + manager.callbackURLScheme = Manager.URLSchemes?.first + manager[CallbackURLKitDemo.PrintActionString] = CallbackURLKitDemo.PrintAction + } + } +#endif diff --git a/SampleApp/CallbackURLKitDemo/Base.lproj/Main.storyboard b/SampleApp/CallbackURLKitDemo/Base.lproj/Main.storyboard index 78102b3..1eda41e 100644 --- a/SampleApp/CallbackURLKitDemo/Base.lproj/Main.storyboard +++ b/SampleApp/CallbackURLKitDemo/Base.lproj/Main.storyboard @@ -1,8 +1,8 @@ - + - + @@ -17,15 +17,28 @@ - + + + + + + + diff --git a/SampleApp/CallbackURLKitDemo/CallbackURLKitDemo.swift b/SampleApp/CallbackURLKitDemo/CallbackURLKitDemo.swift new file mode 100644 index 0000000..b8e4ab7 --- /dev/null +++ b/SampleApp/CallbackURLKitDemo/CallbackURLKitDemo.swift @@ -0,0 +1,56 @@ +// +// Shared.swift +// CallbackURLKitDemo +// +// Created by phimage on 03/01/16. +// Copyright © 2016 phimage. All rights reserved. +// + +import Foundation +import CallbackURLKit + +enum DemoErrorType: FailureCallbackErrorType { + case NoText + + var code: Int { + switch self { + case .NoText: return 0 + } + } + var message: String { + switch self { + case .NoText: return "You must defined text parameters" + } + } +} + +public class CallbackURLKitDemo: Client { + + public static let instance = CallbackURLKitDemo() + + public init() { + super.init(URLScheme: "callbackurlkit") + } + + public func printMessage(message: String, onSuccess: SuccessCallback? = nil, onFailure: FailureCallback? = nil, onCancel: CancelCallback? = nil) throws { + let parameters = ["text": message] + try self.performAction(CallbackURLKitDemo.PrintActionString, parameters: parameters, + onSuccess: onSuccess, onFailure: onFailure, onCancel: onCancel) + } + + public static let PrintActionString = "print" + public static let PrintAction: ActionHandler = { parameters, success, failed, cancel in + if let text = parameters["text"] { + print(text) + let formatter = NSDateFormatter() + formatter.dateStyle = NSDateFormatterStyle.LongStyle + formatter.timeStyle = .MediumStyle + + let dateString = formatter.stringFromDate(NSDate()) + success(["text": text, "date": dateString]) + } else { + failed(DemoErrorType.NoText) + } + } + +} diff --git a/SampleApp/CallbackURLKitDemo/Info.plist b/SampleApp/CallbackURLKitDemo/Info.plist index 8c2d13b..24eb99e 100644 --- a/SampleApp/CallbackURLKitDemo/Info.plist +++ b/SampleApp/CallbackURLKitDemo/Info.plist @@ -5,6 +5,7 @@ LSApplicationQueriesSchemes googlechrome-x-callback + callbackurlkit CFBundleDevelopmentRegion en diff --git a/SampleApp/CallbackURLKitDemo/Shared.swift b/SampleApp/CallbackURLKitDemo/Shared.swift deleted file mode 100644 index 7d8ae21..0000000 --- a/SampleApp/CallbackURLKitDemo/Shared.swift +++ /dev/null @@ -1,25 +0,0 @@ -// -// Shared.swift -// CallbackURLKitDemo -// -// Created by phimage on 03/01/16. -// Copyright © 2016 phimage. All rights reserved. -// - -import Foundation -import CallbackURLKit - -enum DemoErrorType: FailureCallbackErrorType { - case NoText - - var code: Int { - switch self { - case .NoText: return 0 - } - } - var message: String { - switch self { - case .NoText: return "You must defined text parameters" - } - } -} \ No newline at end of file diff --git a/SampleApp/CallbackURLKitDemo/ViewController.swift b/SampleApp/CallbackURLKitDemo/ViewController.swift index a5505e3..7ad5c9c 100644 --- a/SampleApp/CallbackURLKitDemo/ViewController.swift +++ b/SampleApp/CallbackURLKitDemo/ViewController.swift @@ -6,27 +6,49 @@ // Copyright © 2016 phimage. All rights reserved. // -import UIKit import CallbackURLKit -class ViewController: UIViewController { +#if os(iOS) + import UIKit + class ViewController: UIViewController {} +#elseif os(OSX) + import Cocoa + class ViewController: NSViewController {} +#endif +extension ViewController { + override func viewDidLoad() { super.viewDidLoad() - // Do any additional setup after loading the view, typically from a nib. } - override func didReceiveMemoryWarning() { - super.didReceiveMemoryWarning() - // Dispose of any resources that can be recreated. - } - @IBAction func openChrome(sender: AnyObject!) { let chrome = GoogleChrome() do { try chrome.openURL("http://www.google.com") - } catch CallbackURLKitError.AppWithSchemeNotInstalled { - print("chrome not installed or not implement x-callback-url in current os") + } catch CallbackURLKitError.AppWithSchemeNotInstalled(let scheme) { + print("chrome(\(scheme)) not installed or not implement x-callback-url in current os") + + } catch CallbackURLKitError.CallbackURLSchemeNotDefined { + print("current app scheme not defined") + } catch let e { + print("exception \(e)") + } + } + + @IBAction func printAction(sender: AnyObject!) { + do { + try CallbackURLKitDemo.instance.printMessage( + "a message %20 % = &toto=a", + onSuccess: { parameters in + print("parameters \(parameters)") + }, + onFailure: { error in + print("\(error)") + } + ) + } catch CallbackURLKitError.AppWithSchemeNotInstalled(let scheme) { + print("\(scheme) not installed or not implement x-callback-url in current os") } catch CallbackURLKitError.CallbackURLSchemeNotDefined { print("current app scheme not defined") diff --git a/SampleApp/CallbackURLKitDemoOSX/AppDelegate.swift b/SampleApp/CallbackURLKitDemoOSX/AppDelegate.swift deleted file mode 100644 index d4f9e18..0000000 --- a/SampleApp/CallbackURLKitDemoOSX/AppDelegate.swift +++ /dev/null @@ -1,40 +0,0 @@ -// -// AppDelegate.swift -// CallbackURLKitDemoOSX -// -// Created by phimage on 03/01/16. -// Copyright © 2016 phimage. All rights reserved. -// - -import Cocoa -import CallbackURLKit - -@NSApplicationMain -class AppDelegate: NSObject, NSApplicationDelegate { - - func applicationDidFinishLaunching(aNotification: NSNotification) { - NSAppleEventManager.sharedAppleEventManager().setEventHandler(self, andSelector:"handleGetURLEvent:withReplyEvent:", forEventClass: AEEventClass(kInternetEventClass), andEventID: AEEventID(kAEGetURL)) - - let manager = Manager.sharedInstance - manager.callbackURLScheme = Manager.URLSchemes?.first - - manager["print"] = { parameters, success, failed, cancel in - if let text = parameters["text"] { - print(text) - success(nil) - } else { - failed(DemoErrorType.NoText) - } - } - } - - func applicationWillTerminate(aNotification: NSNotification) { - } - - func handleGetURLEvent(event: NSAppleEventDescriptor!, withReplyEvent: NSAppleEventDescriptor!) { - if let urlString = event.paramDescriptorForKeyword(AEKeyword(keyDirectObject))?.stringValue, url = NSURL(string: urlString) { - Manager.sharedInstance.handleOpenURL(url) - } - } -} - diff --git a/SampleApp/CallbackURLKitDemoOSX/Base.lproj/Main.storyboard b/SampleApp/CallbackURLKitDemoOSX/Base.lproj/Main.storyboard index 87693e5..8d81b9e 100644 --- a/SampleApp/CallbackURLKitDemoOSX/Base.lproj/Main.storyboard +++ b/SampleApp/CallbackURLKitDemoOSX/Base.lproj/Main.storyboard @@ -1,8 +1,8 @@ - + - + @@ -673,9 +673,9 @@ - + + + + + + + diff --git a/SampleApp/CallbackURLKitDemoOSX/ViewController.swift b/SampleApp/CallbackURLKitDemoOSX/ViewController.swift deleted file mode 100644 index 6a67063..0000000 --- a/SampleApp/CallbackURLKitDemoOSX/ViewController.swift +++ /dev/null @@ -1,42 +0,0 @@ -// -// ViewController.swift -// CallbackURLKitDemoOSX -// -// Created by phimage on 03/01/16. -// Copyright © 2016 phimage. All rights reserved. -// - -import Cocoa -import CallbackURLKit - -class ViewController: NSViewController { - - override func viewDidLoad() { - super.viewDidLoad() - - // Do any additional setup after loading the view. - } - - override var representedObject: AnyObject? { - didSet { - // Update the view, if already loaded. - } - } - - @IBAction func openChrome(sender: AnyObject!) { - let chrome = GoogleChrome() - do { - try chrome.openURL("http://www.google.com") - } catch CallbackURLKitError.AppWithSchemeNotInstalled { - print("chrome not installed or not implement x-callback-url in current os") - - } catch CallbackURLKitError.CallbackURLSchemeNotDefined { - print("current app scheme not defined") - } catch let e { - print("exception \(e)") - } - } - - -} -