diff --git a/ActionCableClient.podspec b/ActionCableClient.podspec index 41e1082..8349d1d 100644 --- a/ActionCableClient.podspec +++ b/ActionCableClient.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "ActionCableClient" - s.version = "0.2.4" + s.version = "0.3.0" s.summary = "A Swift client for the Rails ActionCable WebSocket server." s.description = <<-DESC ActionCable is a new WebSocket server being released with Rails 5 which makes it easy to add real-time features to your app. This Swift client makes it dead-simple to connect with that server, abstracting away everything except what you need to get going. @@ -12,12 +12,14 @@ Pod::Spec.new do |s| s.source = { :git => "https://github.com/danielrhodes/Swift-ActionCableClient.git", :tag => s.version.to_s } s.social_media_url = 'https://twitter.com/danielrhodes' - s.pod_target_xcconfig = { 'SWIFT_VERSION' => '4.0' } + s.pod_target_xcconfig = { 'SWIFT_VERSION' => '5.0' } s.ios.deployment_target = '8.0' s.tvos.deployment_target = '9.0' s.requires_arc = true s.source_files = 'Source/Classes/**/*' s.frameworks = 'Foundation' - s.dependency 'Starscream', '~> 3.0.3' + s.dependency 'Starscream', '~> 3.1.0' + + s.swift_version = '5.0' end diff --git a/Example/ActionCableClient-Example.xcodeproj/project.pbxproj b/Example/ActionCableClient-Example.xcodeproj/project.pbxproj index ab47db8..606b1d6 100644 --- a/Example/ActionCableClient-Example.xcodeproj/project.pbxproj +++ b/Example/ActionCableClient-Example.xcodeproj/project.pbxproj @@ -154,7 +154,6 @@ 86D451531DC31BF9006A516E /* Frameworks */, 86D451541DC31BF9006A516E /* Resources */, 73670B087BDA56514C37256F /* [CP] Embed Pods Frameworks */, - 54AE2864EEF206764C29DEB5 /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -174,7 +173,6 @@ 86D4517E1DC31D73006A516E /* Frameworks */, 86D4517F1DC31D73006A516E /* Resources */, CB2674BAF940CAB39684678D /* [CP] Embed Pods Frameworks */, - 44C432A26A1306534DDB0E9A /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -192,12 +190,13 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0800; - LastUpgradeCheck = 0900; + LastUpgradeCheck = 1120; ORGANIZATIONNAME = "Daniel Rhodes"; TargetAttributes = { 86D451551DC31BF9006A516E = { CreatedOnToolsVersion = 8.0; - LastSwiftMigration = 0900; + DevelopmentTeam = 5K24DRTJ53; + LastSwiftMigration = 1120; ProvisioningStyle = Automatic; }; 86D451801DC31D73006A516E = { @@ -208,7 +207,7 @@ }; buildConfigurationList = 86D451511DC31BF9006A516E /* Build configuration list for PBXProject "ActionCableClient-Example" */; compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; + developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, @@ -265,36 +264,6 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - 44C432A26A1306534DDB0E9A /* [CP] Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "[CP] Copy Pods Resources"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-ActionCableClient-Example-tvOS/Pods-ActionCableClient-Example-tvOS-resources.sh\"\n"; - showEnvVarsInLog = 0; - }; - 54AE2864EEF206764C29DEB5 /* [CP] Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "[CP] Copy Pods Resources"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-ActionCableClient-Example-iOS/Pods-ActionCableClient-Example-iOS-resources.sh\"\n"; - showEnvVarsInLog = 0; - }; 714E8598059A7B374097B96E /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -319,7 +288,7 @@ files = ( ); inputPaths = ( - "${SRCROOT}/Pods/Target Support Files/Pods-ActionCableClient-Example-iOS/Pods-ActionCableClient-Example-iOS-frameworks.sh", + "${PODS_ROOT}/Target Support Files/Pods-ActionCableClient-Example-iOS/Pods-ActionCableClient-Example-iOS-frameworks.sh", "${BUILT_PRODUCTS_DIR}/ActionCableClient-iOS/ActionCableClient.framework", "${BUILT_PRODUCTS_DIR}/SnapKit-iOS/SnapKit.framework", "${BUILT_PRODUCTS_DIR}/Starscream-iOS/Starscream.framework", @@ -334,7 +303,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-ActionCableClient-Example-iOS/Pods-ActionCableClient-Example-iOS-frameworks.sh\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ActionCableClient-Example-iOS/Pods-ActionCableClient-Example-iOS-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; CB2674BAF940CAB39684678D /* [CP] Embed Pods Frameworks */ = { @@ -343,7 +312,7 @@ files = ( ); inputPaths = ( - "${SRCROOT}/Pods/Target Support Files/Pods-ActionCableClient-Example-tvOS/Pods-ActionCableClient-Example-tvOS-frameworks.sh", + "${PODS_ROOT}/Target Support Files/Pods-ActionCableClient-Example-tvOS/Pods-ActionCableClient-Example-tvOS-frameworks.sh", "${BUILT_PRODUCTS_DIR}/ActionCableClient-tvOS/ActionCableClient.framework", "${BUILT_PRODUCTS_DIR}/SnapKit-tvOS/SnapKit.framework", "${BUILT_PRODUCTS_DIR}/Starscream-tvOS/Starscream.framework", @@ -358,7 +327,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-ActionCableClient-Example-tvOS/Pods-ActionCableClient-Example-tvOS-frameworks.sh\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ActionCableClient-Example-tvOS/Pods-ActionCableClient-Example-tvOS-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ @@ -410,6 +379,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; @@ -419,6 +389,7 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; @@ -426,6 +397,7 @@ CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; @@ -466,6 +438,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; @@ -475,6 +448,7 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; @@ -482,6 +456,7 @@ CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; @@ -517,15 +492,16 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; + DEVELOPMENT_TEAM = 5K24DRTJ53; INFOPLIST_FILE = "$(SRCROOT)/ActionCableClient/Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "com.danielrhodes.ActionCableClient-Example-iOS"; + PRODUCT_BUNDLE_IDENTIFIER = "com.nicoskaralis.ActionCableClient-Example-iOS"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "ActionCableClient-Example-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_SWIFT3_OBJC_INFERENCE = Default; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 5.0; }; name = Debug; }; @@ -535,14 +511,15 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; + DEVELOPMENT_TEAM = 5K24DRTJ53; INFOPLIST_FILE = "$(SRCROOT)/ActionCableClient/Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "com.danielrhodes.ActionCableClient-Example-iOS"; + PRODUCT_BUNDLE_IDENTIFIER = "com.nicoskaralis.ActionCableClient-Example-iOS"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "ActionCableClient-Example-Bridging-Header.h"; SWIFT_SWIFT3_OBJC_INFERENCE = Default; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 5.0; }; name = Release; }; diff --git a/Example/ActionCableClient/AppDelegate.swift b/Example/ActionCableClient/AppDelegate.swift index c103a95..3b77c49 100644 --- a/Example/ActionCableClient/AppDelegate.swift +++ b/Example/ActionCableClient/AppDelegate.swift @@ -28,7 +28,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool { + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { let controller = ChatViewController() let navigationController = UINavigationController() navigationController.pushViewController(controller, animated: false) diff --git a/Example/ActionCableClient/ChatCell.swift b/Example/ActionCableClient/ChatCell.swift index 764d00a..328612b 100644 --- a/Example/ActionCableClient/ChatCell.swift +++ b/Example/ActionCableClient/ChatCell.swift @@ -35,7 +35,7 @@ class ChatCell: UITableViewCell { } } - override init(style: UITableViewCellStyle, reuseIdentifier: String?) { + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) textView.frame = CGRect.zero textView.lineBreakMode = NSLineBreakMode.byWordWrapping diff --git a/Example/ActionCableClient/ChatView.swift b/Example/ActionCableClient/ChatView.swift index d75206a..1bf1024 100644 --- a/Example/ActionCableClient/ChatView.swift +++ b/Example/ActionCableClient/ChatView.swift @@ -36,24 +36,24 @@ class ChatView : UIView { super.init(frame: frame) self.tableView.frame = CGRect.zero - self.tableView.contentInset = UIEdgeInsetsMake(0, -5, 0, 0); + self.tableView.contentInset = UIEdgeInsets.init(top: 0, left: -5, bottom: 0, right: 0); self.addSubview(self.tableView) self.textField.frame = CGRect.zero - self.textField.borderStyle = UITextBorderStyle.bezel + self.textField.borderStyle = UITextField.BorderStyle.bezel self.textField.returnKeyType = UIReturnKeyType.send self.textField.placeholder = "Say something..." self.addSubview(self.textField) self.backgroundColor = UIColor.white - NotificationCenter.default.addObserver(self, selector: #selector(ChatView.keyboardWillShowNotification(_:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil) - NotificationCenter.default.addObserver(self, selector: #selector(ChatView.keyboardWillHideNotification(_:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(ChatView.keyboardWillShowNotification(_:)), name: UIResponder.keyboardWillShowNotification, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(ChatView.keyboardWillHideNotification(_:)), name: UIResponder.keyboardWillHideNotification, object: nil) } deinit { - NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: nil) - NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil) + NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillShowNotification, object: nil) + NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil) } required init?(coder aDecoder: NSCoder) { @@ -86,9 +86,9 @@ class ChatView : UIView { extension ChatView { @objc func keyboardWillHideNotification(_ notification: Notification) { let userInfo = (notification as NSNotification).userInfo! - let animationDuration = (userInfo[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber).doubleValue - let rawAnimationCurve = ((notification as NSNotification).userInfo![UIKeyboardAnimationCurveUserInfoKey] as! NSNumber).uint32Value << 16 - let animationCurve = UIViewAnimationOptions(rawValue: UInt(rawAnimationCurve)) + let animationDuration = (userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as! NSNumber).doubleValue + let rawAnimationCurve = ((notification as NSNotification).userInfo![UIResponder.keyboardAnimationCurveUserInfoKey] as! NSNumber).uint32Value << 16 + let animationCurve = UIView.AnimationOptions(rawValue: UInt(rawAnimationCurve)) UIView.animate(withDuration: animationDuration, delay: 0.0, options: [.beginFromCurrentState, animationCurve], animations: { self.bottomLayoutConstraint?.update(offset: 0) @@ -98,11 +98,11 @@ extension ChatView { @objc func keyboardWillShowNotification(_ notification: Notification) { let userInfo = (notification as NSNotification).userInfo! - let animationDuration = (userInfo[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber).doubleValue - let keyboardEndFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue + let animationDuration = (userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as! NSNumber).doubleValue + let keyboardEndFrame = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue let convertedKeyboardEndFrame = self.convert(keyboardEndFrame, from: self.window) - let rawAnimationCurve = ((notification as NSNotification).userInfo![UIKeyboardAnimationCurveUserInfoKey] as! NSNumber).uint32Value << 16 - let animationCurve = UIViewAnimationOptions(rawValue: UInt(rawAnimationCurve)) + let rawAnimationCurve = ((notification as NSNotification).userInfo![UIResponder.keyboardAnimationCurveUserInfoKey] as! NSNumber).uint32Value << 16 + let animationCurve = UIView.AnimationOptions(rawValue: UInt(rawAnimationCurve)) UIView.animate(withDuration: animationDuration, delay: 0.0, options: [.beginFromCurrentState, animationCurve], animations: { self.bottomLayoutConstraint?.update(offset: -convertedKeyboardEndFrame.height) self.updateConstraintsIfNeeded() diff --git a/Example/ActionCableClient/ChatViewController.swift b/Example/ActionCableClient/ChatViewController.swift index 73f00b7..60d6195 100644 --- a/Example/ActionCableClient/ChatViewController.swift +++ b/Example/ActionCableClient/ChatViewController.swift @@ -66,7 +66,7 @@ class ChatViewController: UIViewController { override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) - let alert = UIAlertController(title: "Chat", message: "What's Your Name?", preferredStyle: UIAlertControllerStyle.alert) + let alert = UIAlertController(title: "Chat", message: "What's Your Name?", preferredStyle: UIAlertController.Style.alert) var nameTextField: UITextField? alert.addTextField(configurationHandler: {(textField: UITextField!) in @@ -75,7 +75,7 @@ class ChatViewController: UIViewController { nameTextField = textField }) - alert.addAction(UIAlertAction(title: "Start", style: UIAlertActionStyle.default) {(action: UIAlertAction) in + alert.addAction(UIAlertAction(title: "Start", style: UIAlertAction.Style.default) {(action: UIAlertAction) in self.name = nameTextField?.text self.chatView?.textField.becomeFirstResponder() }) @@ -187,14 +187,14 @@ struct ChatMessage { func attributedString() -> NSAttributedString { let messageString: String = "\(self.name) \(self.message)" - let nameRange = NSRange(location: 0, length: self.name.characters.count) - let nonNameRange = NSRange(location: nameRange.length, length: messageString.characters.count - nameRange.length) + let nameRange = NSRange(location: 0, length: self.name.count) + let nonNameRange = NSRange(location: nameRange.length, length: messageString.count - nameRange.length) let string: NSMutableAttributedString = NSMutableAttributedString(string: messageString) - string.addAttribute(NSAttributedStringKey.font, + string.addAttribute(NSAttributedString.Key.font, value: UIFont.boldSystemFont(ofSize: 18.0), range: nameRange) - string.addAttribute(NSAttributedStringKey.font, value: UIFont.systemFont(ofSize: 18.0), range: nonNameRange) + string.addAttribute(NSAttributedString.Key.font, value: UIFont.systemFont(ofSize: 18.0), range: nonNameRange) return string } } diff --git a/Example/Podfile.lock b/Example/Podfile.lock index 4e98259..83dfc55 100644 --- a/Example/Podfile.lock +++ b/Example/Podfile.lock @@ -1,25 +1,31 @@ PODS: - - ActionCableClient (0.2.3): - - Starscream (~> 2.1.1) - - SnapKit (3.2.0) - - Starscream (2.1.1) - - SwiftyJSON (3.1.4) + - ActionCableClient (0.3.0): + - Starscream (~> 3.1.0) + - SnapKit (4.2.0) + - Starscream (3.1.1) + - SwiftyJSON (5.0.0) DEPENDENCIES: - ActionCableClient (from `../`) - SnapKit - SwiftyJSON +SPEC REPOS: + https://github.com/CocoaPods/Specs.git: + - SnapKit + - Starscream + - SwiftyJSON + EXTERNAL SOURCES: ActionCableClient: - :path: ../ + :path: "../" SPEC CHECKSUMS: - ActionCableClient: b292c0cb95490f0a5d417729b8052764b1d6babe - SnapKit: 1ca44df72cfa543218d177cb8aab029d10d86ea7 - Starscream: 142bd8ef24592d985daee9fa48c936070b85b15f - SwiftyJSON: c2842d878f95482ffceec5709abc3d05680c0220 + ActionCableClient: ead548377601e260e7c024ccbbab3d22ea1ea82d + SnapKit: fe8a619752f3f27075cc9a90244d75c6c3f27e2a + Starscream: 4bb2f9942274833f7b4d296a55504dcfc7edb7b0 + SwiftyJSON: 36413e04c44ee145039d332b4f4e2d3e8d6c4db7 PODFILE CHECKSUM: dbc0283d807753c3c71ad17b82e66d2742059690 -COCOAPODS: 1.3.1 +COCOAPODS: 1.8.4 diff --git a/Source/Classes/ActionCableClient.swift b/Source/Classes/ActionCableClient.swift index 19e1822..9f6302c 100644 --- a/Source/Classes/ActionCableClient.swift +++ b/Source/Classes/ActionCableClient.swift @@ -74,7 +74,7 @@ open class ActionCableClient { open var headers : [String: String]? { get { return socket.request.allHTTPHeaderFields } set { - for (field, value) in headers ?? [:] { + for (field, value) in newValue ?? [:] { socket.request.setValue(value, forHTTPHeaderField: field) } } @@ -229,9 +229,13 @@ extension ActionCableClient { var channelUID = name //if identifier isn't empty, fetch the first value as the channel unique identifier - if let dictionary = identifier?.first { - channelUID = dictionary.value as! String + if let dictionary = identifier, dictionary.count > 1 { + var identifier = name + for key in dictionary.keys.sorted() { + identifier += "-\(key):\(dictionary[key] as? String ?? "")" } + channelUID = identifier + } // Look in existing channels and return that if let channel = channels[channelUID] { return channel } @@ -429,7 +433,8 @@ extension ActionCableClient { DispatchQueue.main.async(execute: callback) } case .message: - if let channel = channels[message.channelName!] { + if let channelName = message.channelName, + let channel = channels[channelName] { // Notify Channel channel.onMessage(message) @@ -438,7 +443,8 @@ extension ActionCableClient { } } case .confirmSubscription: - if let channel = unconfirmedChannels.removeValue(forKey: message.channelName!) { + if let channelName = message.channelName, + let channel = unconfirmedChannels.removeValue(forKey: channelName) { self.channels.updateValue(channel, forKey: channel.uid) // Notify Channel @@ -491,10 +497,10 @@ extension ActionCableClient : CustomDebugStringConvertible { } } -extension ActionCableClient : CustomPlaygroundQuickLookable { - public var customPlaygroundQuickLook: PlaygroundQuickLook { - return PlaygroundQuickLook.url(socket.currentURL.absoluteString) - } +extension ActionCableClient : CustomPlaygroundDisplayConvertible { + public var playgroundDescription: Any { + return socket.currentURL + } } extension ActionCableClient { diff --git a/Source/Classes/Channel.swift b/Source/Classes/Channel.swift index d3ecb6e..a7201c1 100644 --- a/Source/Classes/Channel.swift +++ b/Source/Classes/Channel.swift @@ -51,12 +51,16 @@ open class Channel: Hashable, Equatable { get { //defaults to channel name var channelUID = name - + //if identifier isn't empty, fetch the first value as the channel unique identifier - if let dictionary = identifier?.first { - channelUID = dictionary.value as! String + if let dictionary = identifier, dictionary.count > 1 { + var identifier = name + for key in dictionary.keys.sorted() { + identifier += "-\(key):\(dictionary[key] as? String ?? "")" + } + channelUID = identifier } - + return channelUID } } @@ -193,7 +197,11 @@ open class Channel: Hashable, Equatable { internal var onReceiveActionHooks: Dictionary = Dictionary() internal unowned var client: ActionCableClient internal var actionBuffer: Array = Array() - open let hashValue: Int = Int(arc4random_uniform(UInt32(Int32.max))) +// public let hashValue: Int = Int(arc4random_uniform(UInt32(Int32.max))) + + public func hash(into hasher: inout Hasher) { + hasher.combine( Int(arc4random_uniform(UInt32(Int32.max))) ) + } } public func ==(lhs: Channel, rhs: Channel) -> Bool { @@ -259,12 +267,12 @@ extension Channel: CustomDebugStringConvertible { } } -extension Channel: CustomPlaygroundQuickLookable { +extension Channel: CustomPlaygroundDisplayConvertible { /// A custom playground quick look for this instance. /// /// If this type has value semantics, the `PlaygroundQuickLook` instance /// should be unaffected by subsequent mutations. - public var customPlaygroundQuickLook: PlaygroundQuickLook { - return PlaygroundQuickLook.text(self.name) - } + public var playgroundDescription: Any { + return self.name + } } diff --git a/Source/Classes/Error.swift b/Source/Classes/Error.swift index b819fee..af8427b 100644 --- a/Source/Classes/Error.swift +++ b/Source/Classes/Error.swift @@ -21,6 +21,7 @@ // import Foundation +import Starscream enum SerializationError : Swift.Error { case json @@ -67,7 +68,14 @@ public enum ConnectionError : Swift.Error { } init(from error: Swift.Error) { - switch error._code { + let error_code: Int + if let ws_error = error as? WSError { + error_code = ws_error.code + } else { + error_code = error._code + } + + switch error_code { case 2: self = ConnectionError.unknownDomain(error) case 61: self = ConnectionError.refused(error) case 404: self = ConnectionError.notFound(error) diff --git a/Source/Classes/JSONSerializer.swift b/Source/Classes/JSONSerializer.swift index 79dabad..85da89d 100644 --- a/Source/Classes/JSONSerializer.swift +++ b/Source/Classes/JSONSerializer.swift @@ -96,16 +96,20 @@ internal class JSONSerializer { } else { throw SerializationError.protocolViolation } - - if let item = idJSON.first { - channelIdentifier = item.value as? String - } - + if let nameStr = idJSON["channel"], let name = nameStr as? String { - channelName = name + channelName = name + + if idJSON.count > 1 { + var identifier = name + for key in idJSON.keys.filter({ $0 != "channel" }).sorted() { + identifier += "-\(key):\(idJSON[key] as? String ?? "")" + } + channelIdentifier = identifier + } } - - if channelIdentifier != nil { + + if let channelIdentifier = channelIdentifier { channelName = channelIdentifier } }