├── Deeplinks.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── stanislavostrovskiy.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── stanislavostrovskiy.xcuserdatad │ └── xcschemes │ ├── Deeplinks.xcscheme │ └── xcschememanagement.plist ├── Deeplinks.xcworkspace ├── contents.xcworkspacedata └── xcuserdata │ └── stanislavostrovskiy.xcuserdatad │ ├── UserInterfaceState.xcuserstate │ └── xcdebugger │ └── Breakpoints_v2.xcbkptlist ├── Deeplinks ├── AppDelegate.swift ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── DeepLinkManager.swift ├── DeeplinkNavigator.swift ├── DeeplinkParser.swift ├── Deeplinks.entitlements ├── Info.plist ├── NotificationParser.swift ├── ShortcutParser.swift └── ViewController.swift ├── Podfile ├── Podfile.lock └── Pods ├── Manifest.lock ├── Pods.xcodeproj ├── project.pbxproj └── xcuserdata │ └── stanislavostrovskiy.xcuserdatad │ └── xcschemes │ ├── Pods-Deeplinks.xcscheme │ ├── PusherSwift.xcscheme │ └── xcschememanagement.plist ├── PusherSwift ├── LICENSE.md ├── README.md └── Source │ ├── CryptoSwiftHMACModule.swift │ ├── NativePusher.swift │ ├── ObjectiveC.swift │ ├── PusherChannel.swift │ ├── PusherChannels.swift │ ├── PusherClientOptions.swift │ ├── PusherConnection.swift │ ├── PusherDelegate.swift │ ├── PusherGlobalChannel.swift │ ├── PusherPresenceChannel.swift │ ├── PusherSwift.swift │ ├── PusherWebsocketDelegate.swift │ ├── Reachability.swift │ ├── Starscream.swift │ └── TaskQueue.swift └── Target Support Files ├── Pods-Deeplinks ├── Info.plist ├── Pods-Deeplinks-acknowledgements.markdown ├── Pods-Deeplinks-acknowledgements.plist ├── Pods-Deeplinks-dummy.m ├── Pods-Deeplinks-frameworks.sh ├── Pods-Deeplinks-resources.sh ├── Pods-Deeplinks-umbrella.h ├── Pods-Deeplinks.debug.xcconfig ├── Pods-Deeplinks.modulemap └── Pods-Deeplinks.release.xcconfig └── PusherSwift ├── Info.plist ├── PusherSwift-dummy.m ├── PusherSwift-prefix.pch ├── PusherSwift-umbrella.h ├── PusherSwift.modulemap └── PusherSwift.xcconfig /Deeplinks.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 360F411F1ED720F500B1479A /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 360F411E1ED720F500B1479A /* AppDelegate.swift */; }; 11 | 360F41211ED720F500B1479A /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 360F41201ED720F500B1479A /* ViewController.swift */; }; 12 | 360F41241ED720F500B1479A /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 360F41221ED720F500B1479A /* Main.storyboard */; }; 13 | 360F41261ED720F500B1479A /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 360F41251ED720F500B1479A /* Assets.xcassets */; }; 14 | 360F41291ED720F500B1479A /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 360F41271ED720F500B1479A /* LaunchScreen.storyboard */; }; 15 | 360F41311ED7299100B1479A /* DeepLinkManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 360F41301ED7299100B1479A /* DeepLinkManager.swift */; }; 16 | 360F41331ED7363400B1479A /* ShortcutParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 360F41321ED7363400B1479A /* ShortcutParser.swift */; }; 17 | 360F41351ED7389900B1479A /* NotificationParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 360F41341ED7389900B1479A /* NotificationParser.swift */; }; 18 | 360F41371ED7393E00B1479A /* DeeplinkParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 360F41361ED7393E00B1479A /* DeeplinkParser.swift */; }; 19 | 360F41391ED73BCE00B1479A /* DeeplinkNavigator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 360F41381ED73BCE00B1479A /* DeeplinkNavigator.swift */; }; 20 | 4500474BFC74FBF1CCFFB6B0 /* Pods_Deeplinks.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B6985F35C96AB1DB682E65A4 /* Pods_Deeplinks.framework */; }; 21 | /* End PBXBuildFile section */ 22 | 23 | /* Begin PBXFileReference section */ 24 | 1920AFCBD8340050C172A02F /* Pods-Deeplinks.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Deeplinks.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Deeplinks/Pods-Deeplinks.debug.xcconfig"; sourceTree = ""; }; 25 | 360F411B1ED720F500B1479A /* Deeplinks.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Deeplinks.app; sourceTree = BUILT_PRODUCTS_DIR; }; 26 | 360F411E1ED720F500B1479A /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 27 | 360F41201ED720F500B1479A /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 28 | 360F41231ED720F500B1479A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 29 | 360F41251ED720F500B1479A /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 30 | 360F41281ED720F500B1479A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 31 | 360F412A1ED720F500B1479A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 32 | 360F41301ED7299100B1479A /* DeepLinkManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeepLinkManager.swift; sourceTree = ""; }; 33 | 360F41321ED7363400B1479A /* ShortcutParser.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShortcutParser.swift; sourceTree = ""; }; 34 | 360F41341ED7389900B1479A /* NotificationParser.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NotificationParser.swift; sourceTree = ""; }; 35 | 360F41361ED7393E00B1479A /* DeeplinkParser.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeeplinkParser.swift; sourceTree = ""; }; 36 | 360F41381ED73BCE00B1479A /* DeeplinkNavigator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeeplinkNavigator.swift; sourceTree = ""; }; 37 | 360F413A1ED7473C00B1479A /* Deeplinks.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Deeplinks.entitlements; sourceTree = ""; }; 38 | 3A146DBEA93B5A4B1F3B6175 /* Pods-Deeplinks.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Deeplinks.release.xcconfig"; path = "Pods/Target Support Files/Pods-Deeplinks/Pods-Deeplinks.release.xcconfig"; sourceTree = ""; }; 39 | B6985F35C96AB1DB682E65A4 /* Pods_Deeplinks.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Deeplinks.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 40 | /* End PBXFileReference section */ 41 | 42 | /* Begin PBXFrameworksBuildPhase section */ 43 | 360F41181ED720F500B1479A /* Frameworks */ = { 44 | isa = PBXFrameworksBuildPhase; 45 | buildActionMask = 2147483647; 46 | files = ( 47 | 4500474BFC74FBF1CCFFB6B0 /* Pods_Deeplinks.framework in Frameworks */, 48 | ); 49 | runOnlyForDeploymentPostprocessing = 0; 50 | }; 51 | /* End PBXFrameworksBuildPhase section */ 52 | 53 | /* Begin PBXGroup section */ 54 | 010EAFF9B85186E7259DF225 /* Pods */ = { 55 | isa = PBXGroup; 56 | children = ( 57 | 1920AFCBD8340050C172A02F /* Pods-Deeplinks.debug.xcconfig */, 58 | 3A146DBEA93B5A4B1F3B6175 /* Pods-Deeplinks.release.xcconfig */, 59 | ); 60 | name = Pods; 61 | sourceTree = ""; 62 | }; 63 | 360F41121ED720F500B1479A = { 64 | isa = PBXGroup; 65 | children = ( 66 | 360F411D1ED720F500B1479A /* Deeplinks */, 67 | 360F411C1ED720F500B1479A /* Products */, 68 | 010EAFF9B85186E7259DF225 /* Pods */, 69 | BC0015EAD79CE08133FCF136 /* Frameworks */, 70 | ); 71 | sourceTree = ""; 72 | }; 73 | 360F411C1ED720F500B1479A /* Products */ = { 74 | isa = PBXGroup; 75 | children = ( 76 | 360F411B1ED720F500B1479A /* Deeplinks.app */, 77 | ); 78 | name = Products; 79 | sourceTree = ""; 80 | }; 81 | 360F411D1ED720F500B1479A /* Deeplinks */ = { 82 | isa = PBXGroup; 83 | children = ( 84 | 360F413A1ED7473C00B1479A /* Deeplinks.entitlements */, 85 | 360F411E1ED720F500B1479A /* AppDelegate.swift */, 86 | 360F41201ED720F500B1479A /* ViewController.swift */, 87 | 360F41221ED720F500B1479A /* Main.storyboard */, 88 | 360F41251ED720F500B1479A /* Assets.xcassets */, 89 | 360F41271ED720F500B1479A /* LaunchScreen.storyboard */, 90 | 360F412A1ED720F500B1479A /* Info.plist */, 91 | 360F41301ED7299100B1479A /* DeepLinkManager.swift */, 92 | 360F41321ED7363400B1479A /* ShortcutParser.swift */, 93 | 360F41341ED7389900B1479A /* NotificationParser.swift */, 94 | 360F41361ED7393E00B1479A /* DeeplinkParser.swift */, 95 | 360F41381ED73BCE00B1479A /* DeeplinkNavigator.swift */, 96 | ); 97 | path = Deeplinks; 98 | sourceTree = ""; 99 | }; 100 | BC0015EAD79CE08133FCF136 /* Frameworks */ = { 101 | isa = PBXGroup; 102 | children = ( 103 | B6985F35C96AB1DB682E65A4 /* Pods_Deeplinks.framework */, 104 | ); 105 | name = Frameworks; 106 | sourceTree = ""; 107 | }; 108 | /* End PBXGroup section */ 109 | 110 | /* Begin PBXNativeTarget section */ 111 | 360F411A1ED720F500B1479A /* Deeplinks */ = { 112 | isa = PBXNativeTarget; 113 | buildConfigurationList = 360F412D1ED720F500B1479A /* Build configuration list for PBXNativeTarget "Deeplinks" */; 114 | buildPhases = ( 115 | 3EDDD74EC16DE769F0B43098 /* [CP] Check Pods Manifest.lock */, 116 | 360F41171ED720F500B1479A /* Sources */, 117 | 360F41181ED720F500B1479A /* Frameworks */, 118 | 360F41191ED720F500B1479A /* Resources */, 119 | 16840ADDA79C746FE6F44A35 /* [CP] Embed Pods Frameworks */, 120 | 759914D855B99D81F8A24FC0 /* [CP] Copy Pods Resources */, 121 | ); 122 | buildRules = ( 123 | ); 124 | dependencies = ( 125 | ); 126 | name = Deeplinks; 127 | productName = Deeplinks; 128 | productReference = 360F411B1ED720F500B1479A /* Deeplinks.app */; 129 | productType = "com.apple.product-type.application"; 130 | }; 131 | /* End PBXNativeTarget section */ 132 | 133 | /* Begin PBXProject section */ 134 | 360F41131ED720F500B1479A /* Project object */ = { 135 | isa = PBXProject; 136 | attributes = { 137 | LastSwiftUpdateCheck = 0830; 138 | LastUpgradeCheck = 0830; 139 | ORGANIZATIONNAME = "Stanislav Ostrovskiy"; 140 | TargetAttributes = { 141 | 360F411A1ED720F500B1479A = { 142 | CreatedOnToolsVersion = 8.3.2; 143 | DevelopmentTeam = 5YJM63K9RT; 144 | ProvisioningStyle = Automatic; 145 | SystemCapabilities = { 146 | com.apple.BackgroundModes = { 147 | enabled = 1; 148 | }; 149 | com.apple.Push = { 150 | enabled = 1; 151 | }; 152 | }; 153 | }; 154 | }; 155 | }; 156 | buildConfigurationList = 360F41161ED720F500B1479A /* Build configuration list for PBXProject "Deeplinks" */; 157 | compatibilityVersion = "Xcode 3.2"; 158 | developmentRegion = English; 159 | hasScannedForEncodings = 0; 160 | knownRegions = ( 161 | en, 162 | Base, 163 | ); 164 | mainGroup = 360F41121ED720F500B1479A; 165 | productRefGroup = 360F411C1ED720F500B1479A /* Products */; 166 | projectDirPath = ""; 167 | projectRoot = ""; 168 | targets = ( 169 | 360F411A1ED720F500B1479A /* Deeplinks */, 170 | ); 171 | }; 172 | /* End PBXProject section */ 173 | 174 | /* Begin PBXResourcesBuildPhase section */ 175 | 360F41191ED720F500B1479A /* Resources */ = { 176 | isa = PBXResourcesBuildPhase; 177 | buildActionMask = 2147483647; 178 | files = ( 179 | 360F41291ED720F500B1479A /* LaunchScreen.storyboard in Resources */, 180 | 360F41261ED720F500B1479A /* Assets.xcassets in Resources */, 181 | 360F41241ED720F500B1479A /* Main.storyboard in Resources */, 182 | ); 183 | runOnlyForDeploymentPostprocessing = 0; 184 | }; 185 | /* End PBXResourcesBuildPhase section */ 186 | 187 | /* Begin PBXShellScriptBuildPhase section */ 188 | 16840ADDA79C746FE6F44A35 /* [CP] Embed Pods Frameworks */ = { 189 | isa = PBXShellScriptBuildPhase; 190 | buildActionMask = 2147483647; 191 | files = ( 192 | ); 193 | inputPaths = ( 194 | ); 195 | name = "[CP] Embed Pods Frameworks"; 196 | outputPaths = ( 197 | ); 198 | runOnlyForDeploymentPostprocessing = 0; 199 | shellPath = /bin/sh; 200 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Deeplinks/Pods-Deeplinks-frameworks.sh\"\n"; 201 | showEnvVarsInLog = 0; 202 | }; 203 | 3EDDD74EC16DE769F0B43098 /* [CP] Check Pods Manifest.lock */ = { 204 | isa = PBXShellScriptBuildPhase; 205 | buildActionMask = 2147483647; 206 | files = ( 207 | ); 208 | inputPaths = ( 209 | ); 210 | name = "[CP] Check Pods Manifest.lock"; 211 | outputPaths = ( 212 | ); 213 | runOnlyForDeploymentPostprocessing = 0; 214 | shellPath = /bin/sh; 215 | shellScript = "diff \"${PODS_ROOT}/../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"; 216 | showEnvVarsInLog = 0; 217 | }; 218 | 759914D855B99D81F8A24FC0 /* [CP] Copy Pods Resources */ = { 219 | isa = PBXShellScriptBuildPhase; 220 | buildActionMask = 2147483647; 221 | files = ( 222 | ); 223 | inputPaths = ( 224 | ); 225 | name = "[CP] Copy Pods Resources"; 226 | outputPaths = ( 227 | ); 228 | runOnlyForDeploymentPostprocessing = 0; 229 | shellPath = /bin/sh; 230 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Deeplinks/Pods-Deeplinks-resources.sh\"\n"; 231 | showEnvVarsInLog = 0; 232 | }; 233 | /* End PBXShellScriptBuildPhase section */ 234 | 235 | /* Begin PBXSourcesBuildPhase section */ 236 | 360F41171ED720F500B1479A /* Sources */ = { 237 | isa = PBXSourcesBuildPhase; 238 | buildActionMask = 2147483647; 239 | files = ( 240 | 360F41211ED720F500B1479A /* ViewController.swift in Sources */, 241 | 360F411F1ED720F500B1479A /* AppDelegate.swift in Sources */, 242 | 360F41371ED7393E00B1479A /* DeeplinkParser.swift in Sources */, 243 | 360F41351ED7389900B1479A /* NotificationParser.swift in Sources */, 244 | 360F41311ED7299100B1479A /* DeepLinkManager.swift in Sources */, 245 | 360F41391ED73BCE00B1479A /* DeeplinkNavigator.swift in Sources */, 246 | 360F41331ED7363400B1479A /* ShortcutParser.swift in Sources */, 247 | ); 248 | runOnlyForDeploymentPostprocessing = 0; 249 | }; 250 | /* End PBXSourcesBuildPhase section */ 251 | 252 | /* Begin PBXVariantGroup section */ 253 | 360F41221ED720F500B1479A /* Main.storyboard */ = { 254 | isa = PBXVariantGroup; 255 | children = ( 256 | 360F41231ED720F500B1479A /* Base */, 257 | ); 258 | name = Main.storyboard; 259 | sourceTree = ""; 260 | }; 261 | 360F41271ED720F500B1479A /* LaunchScreen.storyboard */ = { 262 | isa = PBXVariantGroup; 263 | children = ( 264 | 360F41281ED720F500B1479A /* Base */, 265 | ); 266 | name = LaunchScreen.storyboard; 267 | sourceTree = ""; 268 | }; 269 | /* End PBXVariantGroup section */ 270 | 271 | /* Begin XCBuildConfiguration section */ 272 | 360F412B1ED720F500B1479A /* Debug */ = { 273 | isa = XCBuildConfiguration; 274 | buildSettings = { 275 | ALWAYS_SEARCH_USER_PATHS = NO; 276 | CLANG_ANALYZER_NONNULL = YES; 277 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 278 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 279 | CLANG_CXX_LIBRARY = "libc++"; 280 | CLANG_ENABLE_MODULES = YES; 281 | CLANG_ENABLE_OBJC_ARC = YES; 282 | CLANG_WARN_BOOL_CONVERSION = YES; 283 | CLANG_WARN_CONSTANT_CONVERSION = YES; 284 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 285 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 286 | CLANG_WARN_EMPTY_BODY = YES; 287 | CLANG_WARN_ENUM_CONVERSION = YES; 288 | CLANG_WARN_INFINITE_RECURSION = YES; 289 | CLANG_WARN_INT_CONVERSION = YES; 290 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 291 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 292 | CLANG_WARN_UNREACHABLE_CODE = YES; 293 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 294 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 295 | COPY_PHASE_STRIP = NO; 296 | DEBUG_INFORMATION_FORMAT = dwarf; 297 | ENABLE_STRICT_OBJC_MSGSEND = YES; 298 | ENABLE_TESTABILITY = YES; 299 | GCC_C_LANGUAGE_STANDARD = gnu99; 300 | GCC_DYNAMIC_NO_PIC = NO; 301 | GCC_NO_COMMON_BLOCKS = YES; 302 | GCC_OPTIMIZATION_LEVEL = 0; 303 | GCC_PREPROCESSOR_DEFINITIONS = ( 304 | "DEBUG=1", 305 | "$(inherited)", 306 | ); 307 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 308 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 309 | GCC_WARN_UNDECLARED_SELECTOR = YES; 310 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 311 | GCC_WARN_UNUSED_FUNCTION = YES; 312 | GCC_WARN_UNUSED_VARIABLE = YES; 313 | IPHONEOS_DEPLOYMENT_TARGET = 10.3; 314 | MTL_ENABLE_DEBUG_INFO = YES; 315 | ONLY_ACTIVE_ARCH = YES; 316 | SDKROOT = iphoneos; 317 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 318 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 319 | }; 320 | name = Debug; 321 | }; 322 | 360F412C1ED720F500B1479A /* Release */ = { 323 | isa = XCBuildConfiguration; 324 | buildSettings = { 325 | ALWAYS_SEARCH_USER_PATHS = NO; 326 | CLANG_ANALYZER_NONNULL = YES; 327 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 328 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 329 | CLANG_CXX_LIBRARY = "libc++"; 330 | CLANG_ENABLE_MODULES = YES; 331 | CLANG_ENABLE_OBJC_ARC = YES; 332 | CLANG_WARN_BOOL_CONVERSION = YES; 333 | CLANG_WARN_CONSTANT_CONVERSION = YES; 334 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 335 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 336 | CLANG_WARN_EMPTY_BODY = YES; 337 | CLANG_WARN_ENUM_CONVERSION = YES; 338 | CLANG_WARN_INFINITE_RECURSION = YES; 339 | CLANG_WARN_INT_CONVERSION = YES; 340 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 341 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 342 | CLANG_WARN_UNREACHABLE_CODE = YES; 343 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 344 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 345 | COPY_PHASE_STRIP = NO; 346 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 347 | ENABLE_NS_ASSERTIONS = NO; 348 | ENABLE_STRICT_OBJC_MSGSEND = YES; 349 | GCC_C_LANGUAGE_STANDARD = gnu99; 350 | GCC_NO_COMMON_BLOCKS = YES; 351 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 352 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 353 | GCC_WARN_UNDECLARED_SELECTOR = YES; 354 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 355 | GCC_WARN_UNUSED_FUNCTION = YES; 356 | GCC_WARN_UNUSED_VARIABLE = YES; 357 | IPHONEOS_DEPLOYMENT_TARGET = 10.3; 358 | MTL_ENABLE_DEBUG_INFO = NO; 359 | SDKROOT = iphoneos; 360 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 361 | VALIDATE_PRODUCT = YES; 362 | }; 363 | name = Release; 364 | }; 365 | 360F412E1ED720F500B1479A /* Debug */ = { 366 | isa = XCBuildConfiguration; 367 | baseConfigurationReference = 1920AFCBD8340050C172A02F /* Pods-Deeplinks.debug.xcconfig */; 368 | buildSettings = { 369 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 370 | CODE_SIGN_ENTITLEMENTS = Deeplinks/Deeplinks.entitlements; 371 | DEVELOPMENT_TEAM = 5YJM63K9RT; 372 | INFOPLIST_FILE = Deeplinks/Info.plist; 373 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 374 | PRODUCT_BUNDLE_IDENTIFIER = com.stan.ostrovskiy.deeplinkTut; 375 | PRODUCT_NAME = "$(TARGET_NAME)"; 376 | SWIFT_VERSION = 3.0; 377 | }; 378 | name = Debug; 379 | }; 380 | 360F412F1ED720F500B1479A /* Release */ = { 381 | isa = XCBuildConfiguration; 382 | baseConfigurationReference = 3A146DBEA93B5A4B1F3B6175 /* Pods-Deeplinks.release.xcconfig */; 383 | buildSettings = { 384 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 385 | CODE_SIGN_ENTITLEMENTS = Deeplinks/Deeplinks.entitlements; 386 | DEVELOPMENT_TEAM = 5YJM63K9RT; 387 | INFOPLIST_FILE = Deeplinks/Info.plist; 388 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 389 | PRODUCT_BUNDLE_IDENTIFIER = com.stan.ostrovskiy.deeplinkTut; 390 | PRODUCT_NAME = "$(TARGET_NAME)"; 391 | SWIFT_VERSION = 3.0; 392 | }; 393 | name = Release; 394 | }; 395 | /* End XCBuildConfiguration section */ 396 | 397 | /* Begin XCConfigurationList section */ 398 | 360F41161ED720F500B1479A /* Build configuration list for PBXProject "Deeplinks" */ = { 399 | isa = XCConfigurationList; 400 | buildConfigurations = ( 401 | 360F412B1ED720F500B1479A /* Debug */, 402 | 360F412C1ED720F500B1479A /* Release */, 403 | ); 404 | defaultConfigurationIsVisible = 0; 405 | defaultConfigurationName = Release; 406 | }; 407 | 360F412D1ED720F500B1479A /* Build configuration list for PBXNativeTarget "Deeplinks" */ = { 408 | isa = XCConfigurationList; 409 | buildConfigurations = ( 410 | 360F412E1ED720F500B1479A /* Debug */, 411 | 360F412F1ED720F500B1479A /* Release */, 412 | ); 413 | defaultConfigurationIsVisible = 0; 414 | defaultConfigurationName = Release; 415 | }; 416 | /* End XCConfigurationList section */ 417 | }; 418 | rootObject = 360F41131ED720F500B1479A /* Project object */; 419 | } 420 | -------------------------------------------------------------------------------- /Deeplinks.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Deeplinks.xcodeproj/project.xcworkspace/xcuserdata/stanislavostrovskiy.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Stan-Ost/Deeplinks/46d6af047507d35b684621b08d55082585bd6ae2/Deeplinks.xcodeproj/project.xcworkspace/xcuserdata/stanislavostrovskiy.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Deeplinks.xcodeproj/xcuserdata/stanislavostrovskiy.xcuserdatad/xcschemes/Deeplinks.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /Deeplinks.xcodeproj/xcuserdata/stanislavostrovskiy.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Deeplinks.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 360F411A1ED720F500B1479A 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Deeplinks.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Deeplinks.xcworkspace/xcuserdata/stanislavostrovskiy.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Stan-Ost/Deeplinks/46d6af047507d35b684621b08d55082585bd6ae2/Deeplinks.xcworkspace/xcuserdata/stanislavostrovskiy.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Deeplinks.xcworkspace/xcuserdata/stanislavostrovskiy.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /Deeplinks/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // Deeplinks 4 | // 5 | // Created by Stanislav Ostrovskiy on 5/25/17. 6 | // Copyright © 2017 Stanislav Ostrovskiy. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import PusherSwift 11 | import UserNotifications 12 | 13 | fileprivate let pusherSecretKey = "paste you pisher key here" 14 | 15 | @UIApplicationMain 16 | class AppDelegate: UIResponder, UIApplicationDelegate { 17 | 18 | var window: UIWindow? 19 | 20 | fileprivate let pusher = Pusher(key: pusherSecretKey) 21 | 22 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 23 | 24 | let center = UNUserNotificationCenter.current() 25 | center.requestAuthorization(options: [.alert, .sound]) { (granted, error) in 26 | if let error = error { 27 | print(error.localizedDescription) 28 | } 29 | } 30 | application.registerForRemoteNotifications() 31 | 32 | return true 33 | } 34 | 35 | func applicationWillResignActive(_ application: UIApplication) { 36 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 37 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 38 | } 39 | 40 | func applicationDidEnterBackground(_ application: UIApplication) { 41 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 42 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 43 | } 44 | 45 | func applicationWillEnterForeground(_ application: UIApplication) { 46 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 47 | } 48 | 49 | func applicationDidBecomeActive(_ application: UIApplication) { 50 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 51 | 52 | // handle any deeplink 53 | Deeplinker.checkDeepLink() 54 | } 55 | 56 | func applicationWillTerminate(_ application: UIApplication) { 57 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 58 | } 59 | 60 | 61 | // MARK: Notificatons 62 | func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { 63 | pusher.nativePusher.register(deviceToken: deviceToken) 64 | pusher.nativePusher.subscribe(interestName: "activity") 65 | } 66 | 67 | func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) { 68 | print("failed registration for remote notifications \(error)") 69 | } 70 | 71 | func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { 72 | Deeplinker.handleRemoteNotification(userInfo) 73 | } 74 | 75 | 76 | // MARK: Shortcuts 77 | func application(_ application: UIApplication, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) { 78 | completionHandler(Deeplinker.handleShortcut(item: shortcutItem)) 79 | } 80 | 81 | 82 | // MARK: Deeplinks 83 | func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool { 84 | Deeplinker.handleDeeplink(url: url) 85 | return true 86 | } 87 | 88 | // MARK: Universal Links 89 | func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([Any]?) -> Void) -> Bool { 90 | if userActivity.activityType == NSUserActivityTypeBrowsingWeb { 91 | if let url = userActivity.webpageURL { 92 | Deeplinker.handleDeeplink(url: url) 93 | } 94 | } 95 | return true 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /Deeplinks/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /Deeplinks/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Deeplinks/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /Deeplinks/DeepLinkManager.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DeepLinkManager.swift 3 | // Deeplinks 4 | // 5 | // Created by Stanislav Ostrovskiy on 5/25/17. 6 | // Copyright © 2017 Stanislav Ostrovskiy. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | enum DeeplinkType { 13 | enum Messages { 14 | case root 15 | case details(id: String) 16 | } 17 | case messages(Messages) 18 | case activity 19 | case newListing 20 | case request(id: String) 21 | } 22 | 23 | let Deeplinker = DeepLinkManager() 24 | class DeepLinkManager { 25 | fileprivate init() {} 26 | 27 | private var deeplinkType: DeeplinkType? 28 | 29 | func handleRemoteNotification(_ notification: [AnyHashable: Any]) { 30 | deeplinkType = NotificationParser.shared.handleNotification(notification) 31 | } 32 | 33 | @discardableResult 34 | func handleShortcut(item: UIApplicationShortcutItem) -> Bool { 35 | deeplinkType = ShortcutParser.shared.handleShortcut(item) 36 | return deeplinkType != nil 37 | } 38 | 39 | @discardableResult 40 | func handleDeeplink(url: URL) -> Bool { 41 | deeplinkType = DeeplinkParser.shared.parseDeepLink(url) 42 | return deeplinkType != nil 43 | } 44 | 45 | // check existing deepling and perform action 46 | func checkDeepLink() { 47 | guard let deeplinkType = deeplinkType else { 48 | return 49 | } 50 | 51 | DeeplinkNavigator.shared.proceedToDeeplink(deeplinkType) 52 | 53 | // reset deeplink after handling 54 | self.deeplinkType = nil 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Deeplinks/DeeplinkNavigator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DeeplinkNavigator.swift 3 | // Deeplinks 4 | // 5 | // Created by Stanislav Ostrovskiy on 5/25/17. 6 | // Copyright © 2017 Stanislav Ostrovskiy. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | class DeeplinkNavigator { 13 | 14 | static let shared = DeeplinkNavigator() 15 | private init() { } 16 | 17 | var alertController = UIAlertController() 18 | 19 | func proceedToDeeplink(_ type: DeeplinkType) { 20 | switch type { 21 | case .activity: 22 | displayAlert(title: "Activity") 23 | case .messages(.root): 24 | displayAlert(title: "Messages Root") 25 | case .messages(.details(id: let id)): 26 | displayAlert(title: "Messages Details \(id)") 27 | case .newListing: 28 | displayAlert(title: "New Listing") 29 | case .request(id: let id): 30 | displayAlert(title: "Request Details \(id)") 31 | 32 | } 33 | } 34 | 35 | private func displayAlert(title: String) { 36 | alertController = UIAlertController(title: nil, message: nil, preferredStyle: .alert) 37 | let okButton = UIAlertAction(title: "Ok", style: .default, handler: nil) 38 | alertController.addAction(okButton) 39 | alertController.title = title 40 | if let vc = UIApplication.shared.keyWindow?.rootViewController { 41 | if vc.presentedViewController != nil { 42 | alertController.dismiss(animated: false, completion: { 43 | vc.present(self.alertController, animated: true, completion: nil) 44 | }) 45 | } else { 46 | vc.present(alertController, animated: true, completion: nil) 47 | } 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Deeplinks/DeeplinkParser.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DeeplinkParser.swift 3 | // Deeplinks 4 | // 5 | // Created by Stanislav Ostrovskiy on 5/25/17. 6 | // Copyright © 2017 Stanislav Ostrovskiy. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class DeeplinkParser { 12 | static let shared = DeeplinkParser() 13 | private init() { } 14 | 15 | func parseDeepLink(_ url: URL) -> DeeplinkType? { 16 | guard let components = URLComponents(url: url, resolvingAgainstBaseURL: true), let host = components.host else { 17 | return nil 18 | } 19 | 20 | var pathComponents = components.path.components(separatedBy: "/") 21 | 22 | // the first component is empty 23 | pathComponents.removeFirst() 24 | 25 | switch host { 26 | case "messages": 27 | if let messageId = pathComponents.first { 28 | return DeeplinkType.messages(.details(id: messageId)) 29 | } 30 | case "request": 31 | if let requestId = pathComponents.first { 32 | return DeeplinkType.request(id: requestId) 33 | } 34 | default: 35 | break 36 | } 37 | return nil 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Deeplinks/Deeplinks.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | aps-environment 6 | development 7 | 8 | 9 | -------------------------------------------------------------------------------- /Deeplinks/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UIBackgroundModes 24 | 25 | remote-notification 26 | 27 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIMainStoryboardFile 30 | Main 31 | UIRequiredDeviceCapabilities 32 | 33 | armv7 34 | 35 | UISupportedInterfaceOrientations 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationLandscapeLeft 39 | UIInterfaceOrientationLandscapeRight 40 | 41 | CFBundleURLTypes 42 | 43 | 44 | CFBundleURLName 45 | com.deeplinkTut.Deeplink 46 | CFBundleURLSchemes 47 | 48 | deeplinkTutorial 49 | 50 | 51 | 52 | LSApplicationCategoryType 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /Deeplinks/NotificationParser.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NotificationParser.swift 3 | // Deeplinks 4 | // 5 | // Created by Stanislav Ostrovskiy on 5/25/17. 6 | // Copyright © 2017 Stanislav Ostrovskiy. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class NotificationParser { 12 | static let shared = NotificationParser() 13 | private init() { } 14 | 15 | func handleNotification(_ userInfo: [AnyHashable : Any]) -> DeeplinkType? { 16 | if let data = userInfo["data"] as? [String: Any] { 17 | if let messageId = data["messageId"] as? String { 18 | return DeeplinkType.messages(.details(id: messageId)) 19 | } 20 | } 21 | 22 | return nil 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Deeplinks/ShortcutParser.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ShortcutParser.swift 3 | // Deeplinks 4 | // 5 | // Created by Stanislav Ostrovskiy on 5/25/17. 6 | // Copyright © 2017 Stanislav Ostrovskiy. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | enum ShortcutKey: String { 13 | case newListing = "com.myApp.newListing" 14 | case activity = "com.myApp.activity" 15 | case messages = "com.MyApp.messages" 16 | } 17 | 18 | class ShortcutParser { 19 | static let shared = ShortcutParser() 20 | private init() { } 21 | 22 | func registerShortcuts(for profileType: ProfileType) { 23 | let activityIcon = UIApplicationShortcutIcon(templateImageName: "Alert Icon") 24 | let activityShortcutItem = UIApplicationShortcutItem(type: ShortcutKey.activity.rawValue, localizedTitle: "Recent Activity", localizedSubtitle: nil, icon: activityIcon, userInfo: nil) 25 | 26 | let messageIcon = UIApplicationShortcutIcon(templateImageName: "Messenger Icon") 27 | let messageShortcutItem = UIApplicationShortcutItem(type: ShortcutKey.messages.rawValue, localizedTitle: "Messages", localizedSubtitle: nil, icon: messageIcon, userInfo: nil) 28 | 29 | UIApplication.shared.shortcutItems = [activityShortcutItem, messageShortcutItem] 30 | 31 | switch profileType { 32 | case .host: 33 | let newListingIcon = UIApplicationShortcutIcon(templateImageName: "New Listing Icon") 34 | let newListingShortcutItem = UIApplicationShortcutItem(type: ShortcutKey.newListing.rawValue, localizedTitle: "New Listing", localizedSubtitle: nil, icon: newListingIcon, userInfo: nil) 35 | UIApplication.shared.shortcutItems?.append(newListingShortcutItem) 36 | case .guest: 37 | break 38 | } 39 | } 40 | 41 | func handleShortcut(_ shortcut: UIApplicationShortcutItem) -> DeeplinkType? { 42 | switch shortcut.type { 43 | case ShortcutKey.activity.rawValue: 44 | return .activity 45 | case ShortcutKey.messages.rawValue: 46 | return .messages(.root) 47 | case ShortcutKey.newListing.rawValue: 48 | return .newListing 49 | default: 50 | return nil 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Deeplinks/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // Deeplinks 4 | // 5 | // Created by Stanislav Ostrovskiy on 5/25/17. 6 | // Copyright © 2017 Stanislav Ostrovskiy. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | enum ProfileType: String { 12 | case guest = "Guest" 13 | case host = "Host" 14 | } 15 | 16 | class ViewController: UIViewController { 17 | 18 | var currentProfile = ProfileType.guest 19 | 20 | override func viewDidLoad() { 21 | super.viewDidLoad() 22 | 23 | configureFor(profileType: currentProfile) 24 | } 25 | 26 | @IBAction func didPressSwitchProfile(_ sender: Any) { 27 | currentProfile = currentProfile == .guest ? .host : .guest 28 | configureFor(profileType: currentProfile) 29 | } 30 | 31 | func configureFor(profileType: ProfileType) { 32 | title = profileType.rawValue 33 | ShortcutParser.shared.registerShortcuts(for: profileType) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | platform :ios, ’10.0’ 2 | 3 | target 'Deeplinks' do 4 | use_frameworks! 5 | 6 | pod 'PusherSwift' 7 | 8 | end 9 | -------------------------------------------------------------------------------- /Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - PusherSwift (4.1.0) 3 | 4 | DEPENDENCIES: 5 | - PusherSwift 6 | 7 | SPEC CHECKSUMS: 8 | PusherSwift: 13257260d77445f44ee26d7843e9311186b26e79 9 | 10 | PODFILE CHECKSUM: c130faa23fcd21caa03214c9cf82c70a3e78bcb0 11 | 12 | COCOAPODS: 1.2.0 13 | -------------------------------------------------------------------------------- /Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - PusherSwift (4.1.0) 3 | 4 | DEPENDENCIES: 5 | - PusherSwift 6 | 7 | SPEC CHECKSUMS: 8 | PusherSwift: 13257260d77445f44ee26d7843e9311186b26e79 9 | 10 | PODFILE CHECKSUM: c130faa23fcd21caa03214c9cf82c70a3e78bcb0 11 | 12 | COCOAPODS: 1.2.0 13 | -------------------------------------------------------------------------------- /Pods/Pods.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 02CFFC5304A670C7FE75B99AE6DDD1C7 /* PusherSwift-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 2B48728C6B18A655D23F7D56DA36D671 /* PusherSwift-dummy.m */; }; 11 | 291D6DFE7B93A51B15B5C2794C8F8023 /* PusherChannel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F60B85CCE2A182CFDB3C1FF22F7E5950 /* PusherChannel.swift */; }; 12 | 2FA9FE27CB1EAF9F3B9CC65F63483445 /* Pods-Deeplinks-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 245707380DC6BA1FA9DEB9D17DDC0E79 /* Pods-Deeplinks-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; 13 | 39282269B271C04EA04E4DA20BD98728 /* PusherPresenceChannel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FE4BA8925C80C6518B7FC6595EF0B70 /* PusherPresenceChannel.swift */; }; 14 | 4800C2D41B1ED5238FB7AC76E1167950 /* PusherWebsocketDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 560B4934C8EA8F2F5C1454F1EF945F1F /* PusherWebsocketDelegate.swift */; }; 15 | 5D69EFA02E94866CC27C0FE7FB9CF94B /* Reachability.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07975EB083E212C0D63A2C5B4FE9666A /* Reachability.swift */; }; 16 | 5D91B178E9CED5B8755DDEFA61868A78 /* PusherChannels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67112AE47677D3604B8417FCE22ADF72 /* PusherChannels.swift */; }; 17 | 685A2A2D5A7C53B1DDB199F87BB49D4F /* ObjectiveC.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5B944EFDE4B14D6869F2D8355573401 /* ObjectiveC.swift */; }; 18 | 6D13E39920E7181BB94264A6881DE6F5 /* PusherSwift.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BBDD2E06F8D2C65E487ABB83DEFC6C /* PusherSwift.swift */; }; 19 | 7D88AF13FFD3C16ECEB25A723B5497DF /* PusherDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 520C6581044568021198D5D8F08DAC06 /* PusherDelegate.swift */; }; 20 | 90146064F6247A7C9D32172FEE4180C4 /* NativePusher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BBC28B056E66CED0690095968A3FC46 /* NativePusher.swift */; }; 21 | 93ABDED860287084348A27EEE57001A0 /* PusherClientOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C93B62A15D82C4A2A51783AFBC38AF5E /* PusherClientOptions.swift */; }; 22 | AC02AC1CAF82E3ADE004A454CA555468 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CBB3DE36805AF21409EC968A9691732F /* Foundation.framework */; }; 23 | AF1EB8E2D32FC64172D7A933CFC7214E /* PusherConnection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C9463AD92E0ADFA413D96F575A37A22 /* PusherConnection.swift */; }; 24 | B393600A7670789B083C75AD9F2601DA /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CBB3DE36805AF21409EC968A9691732F /* Foundation.framework */; }; 25 | B3FEEE9818785CAF50EAF2AC21FD3799 /* CryptoSwiftHMACModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = B11BFC9C0348DE4A00CE6FBEDFAFA956 /* CryptoSwiftHMACModule.swift */; }; 26 | C495374D83E6574D02F4D14DD4238679 /* PusherGlobalChannel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B758DCC76BA0E7E38E186B2B1084450B /* PusherGlobalChannel.swift */; }; 27 | C5C8D389B53E3F96D5E580EE9CD6BD06 /* TaskQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0A9FFFDAD4E96B0145BE2669943FA9E /* TaskQueue.swift */; }; 28 | CC742CA962006C36F4554C48CFF123B8 /* PusherSwift-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = AE012CD8FD70753FD52E587549E8140E /* PusherSwift-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; 29 | F85B427324253FD28C4C6D6AA84CE742 /* Pods-Deeplinks-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = B6233BB271E6096496247CEA9FE66BD0 /* Pods-Deeplinks-dummy.m */; }; 30 | FC38D39DF058A947A70EAA1B1979CFF6 /* Starscream.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64B220B536E624CBCE406FD769F0F69F /* Starscream.swift */; }; 31 | /* End PBXBuildFile section */ 32 | 33 | /* Begin PBXContainerItemProxy section */ 34 | 02F965B1CF3EE17A78BFBEC424085B11 /* PBXContainerItemProxy */ = { 35 | isa = PBXContainerItemProxy; 36 | containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; 37 | proxyType = 1; 38 | remoteGlobalIDString = B2499C604716BBAE5BCFA7A1EA85329B; 39 | remoteInfo = PusherSwift; 40 | }; 41 | /* End PBXContainerItemProxy section */ 42 | 43 | /* Begin PBXFileReference section */ 44 | 05EB365DC9A24D81F214174656AE001B /* Pods-Deeplinks-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-Deeplinks-frameworks.sh"; sourceTree = ""; }; 45 | 07975EB083E212C0D63A2C5B4FE9666A /* Reachability.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Reachability.swift; path = Source/Reachability.swift; sourceTree = ""; }; 46 | 0F52FFEDFF1F7F348851B439BDE48118 /* PusherSwift.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = PusherSwift.xcconfig; sourceTree = ""; }; 47 | 245707380DC6BA1FA9DEB9D17DDC0E79 /* Pods-Deeplinks-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-Deeplinks-umbrella.h"; sourceTree = ""; }; 48 | 2B48728C6B18A655D23F7D56DA36D671 /* PusherSwift-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "PusherSwift-dummy.m"; sourceTree = ""; }; 49 | 4A75334D43C0BA77CA84B53D0A3201CD /* Pods-Deeplinks-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-Deeplinks-acknowledgements.markdown"; sourceTree = ""; }; 50 | 520C6581044568021198D5D8F08DAC06 /* PusherDelegate.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PusherDelegate.swift; path = Source/PusherDelegate.swift; sourceTree = ""; }; 51 | 53BBDD2E06F8D2C65E487ABB83DEFC6C /* PusherSwift.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PusherSwift.swift; path = Source/PusherSwift.swift; sourceTree = ""; }; 52 | 54EF3B6986F60C6EA21B9CA10DA16063 /* Pods-Deeplinks-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-Deeplinks-resources.sh"; sourceTree = ""; }; 53 | 560B4934C8EA8F2F5C1454F1EF945F1F /* PusherWebsocketDelegate.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PusherWebsocketDelegate.swift; path = Source/PusherWebsocketDelegate.swift; sourceTree = ""; }; 54 | 64B220B536E624CBCE406FD769F0F69F /* Starscream.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Starscream.swift; path = Source/Starscream.swift; sourceTree = ""; }; 55 | 67112AE47677D3604B8417FCE22ADF72 /* PusherChannels.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PusherChannels.swift; path = Source/PusherChannels.swift; sourceTree = ""; }; 56 | 70E441C9FA9847F3DAF6EC4B9614001D /* PusherSwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = PusherSwift.framework; path = PusherSwift.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 57 | 7BBC28B056E66CED0690095968A3FC46 /* NativePusher.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = NativePusher.swift; path = Source/NativePusher.swift; sourceTree = ""; }; 58 | 7C9463AD92E0ADFA413D96F575A37A22 /* PusherConnection.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PusherConnection.swift; path = Source/PusherConnection.swift; sourceTree = ""; }; 59 | 7D7E000513EBE061EB303C959DA1169A /* PusherSwift.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; path = PusherSwift.modulemap; sourceTree = ""; }; 60 | 7FE4BA8925C80C6518B7FC6595EF0B70 /* PusherPresenceChannel.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PusherPresenceChannel.swift; path = Source/PusherPresenceChannel.swift; sourceTree = ""; }; 61 | 81E38E7AD65274F6F6C6E413DDB3C709 /* Pods-Deeplinks.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; path = "Pods-Deeplinks.modulemap"; sourceTree = ""; }; 62 | 91FA712B1E665B72D2A63B2D808DD58A /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 63 | 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 64 | 9407E47B3334CB9C489F1FF3CA23ADAC /* Pods_Deeplinks.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_Deeplinks.framework; path = "Pods-Deeplinks.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; 65 | AE012CD8FD70753FD52E587549E8140E /* PusherSwift-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "PusherSwift-umbrella.h"; sourceTree = ""; }; 66 | B11BFC9C0348DE4A00CE6FBEDFAFA956 /* CryptoSwiftHMACModule.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CryptoSwiftHMACModule.swift; path = Source/CryptoSwiftHMACModule.swift; sourceTree = ""; }; 67 | B6233BB271E6096496247CEA9FE66BD0 /* Pods-Deeplinks-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-Deeplinks-dummy.m"; sourceTree = ""; }; 68 | B758DCC76BA0E7E38E186B2B1084450B /* PusherGlobalChannel.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PusherGlobalChannel.swift; path = Source/PusherGlobalChannel.swift; sourceTree = ""; }; 69 | B9A4360EDE42D6871AE28D958E138CD1 /* Pods-Deeplinks.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-Deeplinks.debug.xcconfig"; sourceTree = ""; }; 70 | C6CAEC209FF3F32F31A27EA8927623A0 /* Pods-Deeplinks-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-Deeplinks-acknowledgements.plist"; sourceTree = ""; }; 71 | C93B62A15D82C4A2A51783AFBC38AF5E /* PusherClientOptions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PusherClientOptions.swift; path = Source/PusherClientOptions.swift; sourceTree = ""; }; 72 | CBB3DE36805AF21409EC968A9691732F /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; 73 | D5B944EFDE4B14D6869F2D8355573401 /* ObjectiveC.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ObjectiveC.swift; path = Source/ObjectiveC.swift; sourceTree = ""; }; 74 | E9A9C7EBBAC6EB7C3BA0E1E8864F20E7 /* Pods-Deeplinks.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-Deeplinks.release.xcconfig"; sourceTree = ""; }; 75 | F0A9FFFDAD4E96B0145BE2669943FA9E /* TaskQueue.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TaskQueue.swift; path = Source/TaskQueue.swift; sourceTree = ""; }; 76 | F60B85CCE2A182CFDB3C1FF22F7E5950 /* PusherChannel.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PusherChannel.swift; path = Source/PusherChannel.swift; sourceTree = ""; }; 77 | F6ECE4E688B7809DFFF0757B0F0418CC /* PusherSwift-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "PusherSwift-prefix.pch"; sourceTree = ""; }; 78 | F94D2D3C869211CFC69FFF7B6F26FD52 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 79 | /* End PBXFileReference section */ 80 | 81 | /* Begin PBXFrameworksBuildPhase section */ 82 | 93238982ADC52867CEA2F7DAADBBD581 /* Frameworks */ = { 83 | isa = PBXFrameworksBuildPhase; 84 | buildActionMask = 2147483647; 85 | files = ( 86 | B393600A7670789B083C75AD9F2601DA /* Foundation.framework in Frameworks */, 87 | ); 88 | runOnlyForDeploymentPostprocessing = 0; 89 | }; 90 | AB6EDEEF7720F8318DD5EEBF28CEEDC1 /* Frameworks */ = { 91 | isa = PBXFrameworksBuildPhase; 92 | buildActionMask = 2147483647; 93 | files = ( 94 | AC02AC1CAF82E3ADE004A454CA555468 /* Foundation.framework in Frameworks */, 95 | ); 96 | runOnlyForDeploymentPostprocessing = 0; 97 | }; 98 | /* End PBXFrameworksBuildPhase section */ 99 | 100 | /* Begin PBXGroup section */ 101 | 2CF6A830C732B6F3ECDB5E3D1E5D908B /* Targets Support Files */ = { 102 | isa = PBXGroup; 103 | children = ( 104 | EAFD0F06DEBCEED8264335C6D9470700 /* Pods-Deeplinks */, 105 | ); 106 | name = "Targets Support Files"; 107 | sourceTree = ""; 108 | }; 109 | 2CF89217173CBE1FBFF4F331F7221FC8 /* Support Files */ = { 110 | isa = PBXGroup; 111 | children = ( 112 | 91FA712B1E665B72D2A63B2D808DD58A /* Info.plist */, 113 | 7D7E000513EBE061EB303C959DA1169A /* PusherSwift.modulemap */, 114 | 0F52FFEDFF1F7F348851B439BDE48118 /* PusherSwift.xcconfig */, 115 | 2B48728C6B18A655D23F7D56DA36D671 /* PusherSwift-dummy.m */, 116 | F6ECE4E688B7809DFFF0757B0F0418CC /* PusherSwift-prefix.pch */, 117 | AE012CD8FD70753FD52E587549E8140E /* PusherSwift-umbrella.h */, 118 | ); 119 | name = "Support Files"; 120 | path = "../Target Support Files/PusherSwift"; 121 | sourceTree = ""; 122 | }; 123 | 5EEC0F6A87073D20513C2287BCAFAF02 /* Products */ = { 124 | isa = PBXGroup; 125 | children = ( 126 | 9407E47B3334CB9C489F1FF3CA23ADAC /* Pods_Deeplinks.framework */, 127 | 70E441C9FA9847F3DAF6EC4B9614001D /* PusherSwift.framework */, 128 | ); 129 | name = Products; 130 | sourceTree = ""; 131 | }; 132 | 7531C8F8DE19F1AA3C8A7AC97A91DC29 /* iOS */ = { 133 | isa = PBXGroup; 134 | children = ( 135 | CBB3DE36805AF21409EC968A9691732F /* Foundation.framework */, 136 | ); 137 | name = iOS; 138 | sourceTree = ""; 139 | }; 140 | 7DB346D0F39D3F0E887471402A8071AB = { 141 | isa = PBXGroup; 142 | children = ( 143 | 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */, 144 | BC3CA7F9E30CC8F7E2DD044DD34432FC /* Frameworks */, 145 | 7FE271583D49B40292C1066A7080206A /* Pods */, 146 | 5EEC0F6A87073D20513C2287BCAFAF02 /* Products */, 147 | 2CF6A830C732B6F3ECDB5E3D1E5D908B /* Targets Support Files */, 148 | ); 149 | sourceTree = ""; 150 | }; 151 | 7FE271583D49B40292C1066A7080206A /* Pods */ = { 152 | isa = PBXGroup; 153 | children = ( 154 | 9D9C3140D6D685F6978B111053234C4D /* PusherSwift */, 155 | ); 156 | name = Pods; 157 | sourceTree = ""; 158 | }; 159 | 9D9C3140D6D685F6978B111053234C4D /* PusherSwift */ = { 160 | isa = PBXGroup; 161 | children = ( 162 | B11BFC9C0348DE4A00CE6FBEDFAFA956 /* CryptoSwiftHMACModule.swift */, 163 | 7BBC28B056E66CED0690095968A3FC46 /* NativePusher.swift */, 164 | D5B944EFDE4B14D6869F2D8355573401 /* ObjectiveC.swift */, 165 | F60B85CCE2A182CFDB3C1FF22F7E5950 /* PusherChannel.swift */, 166 | 67112AE47677D3604B8417FCE22ADF72 /* PusherChannels.swift */, 167 | C93B62A15D82C4A2A51783AFBC38AF5E /* PusherClientOptions.swift */, 168 | 7C9463AD92E0ADFA413D96F575A37A22 /* PusherConnection.swift */, 169 | 520C6581044568021198D5D8F08DAC06 /* PusherDelegate.swift */, 170 | B758DCC76BA0E7E38E186B2B1084450B /* PusherGlobalChannel.swift */, 171 | 7FE4BA8925C80C6518B7FC6595EF0B70 /* PusherPresenceChannel.swift */, 172 | 53BBDD2E06F8D2C65E487ABB83DEFC6C /* PusherSwift.swift */, 173 | 560B4934C8EA8F2F5C1454F1EF945F1F /* PusherWebsocketDelegate.swift */, 174 | 07975EB083E212C0D63A2C5B4FE9666A /* Reachability.swift */, 175 | 64B220B536E624CBCE406FD769F0F69F /* Starscream.swift */, 176 | F0A9FFFDAD4E96B0145BE2669943FA9E /* TaskQueue.swift */, 177 | 2CF89217173CBE1FBFF4F331F7221FC8 /* Support Files */, 178 | ); 179 | name = PusherSwift; 180 | path = PusherSwift; 181 | sourceTree = ""; 182 | }; 183 | BC3CA7F9E30CC8F7E2DD044DD34432FC /* Frameworks */ = { 184 | isa = PBXGroup; 185 | children = ( 186 | 7531C8F8DE19F1AA3C8A7AC97A91DC29 /* iOS */, 187 | ); 188 | name = Frameworks; 189 | sourceTree = ""; 190 | }; 191 | EAFD0F06DEBCEED8264335C6D9470700 /* Pods-Deeplinks */ = { 192 | isa = PBXGroup; 193 | children = ( 194 | F94D2D3C869211CFC69FFF7B6F26FD52 /* Info.plist */, 195 | 81E38E7AD65274F6F6C6E413DDB3C709 /* Pods-Deeplinks.modulemap */, 196 | 4A75334D43C0BA77CA84B53D0A3201CD /* Pods-Deeplinks-acknowledgements.markdown */, 197 | C6CAEC209FF3F32F31A27EA8927623A0 /* Pods-Deeplinks-acknowledgements.plist */, 198 | B6233BB271E6096496247CEA9FE66BD0 /* Pods-Deeplinks-dummy.m */, 199 | 05EB365DC9A24D81F214174656AE001B /* Pods-Deeplinks-frameworks.sh */, 200 | 54EF3B6986F60C6EA21B9CA10DA16063 /* Pods-Deeplinks-resources.sh */, 201 | 245707380DC6BA1FA9DEB9D17DDC0E79 /* Pods-Deeplinks-umbrella.h */, 202 | B9A4360EDE42D6871AE28D958E138CD1 /* Pods-Deeplinks.debug.xcconfig */, 203 | E9A9C7EBBAC6EB7C3BA0E1E8864F20E7 /* Pods-Deeplinks.release.xcconfig */, 204 | ); 205 | name = "Pods-Deeplinks"; 206 | path = "Target Support Files/Pods-Deeplinks"; 207 | sourceTree = ""; 208 | }; 209 | /* End PBXGroup section */ 210 | 211 | /* Begin PBXHeadersBuildPhase section */ 212 | 477010E7AE4368D8DE851EBE826F6B5D /* Headers */ = { 213 | isa = PBXHeadersBuildPhase; 214 | buildActionMask = 2147483647; 215 | files = ( 216 | CC742CA962006C36F4554C48CFF123B8 /* PusherSwift-umbrella.h in Headers */, 217 | ); 218 | runOnlyForDeploymentPostprocessing = 0; 219 | }; 220 | 85555A70F985B1B48BB75C9678A5CCFE /* Headers */ = { 221 | isa = PBXHeadersBuildPhase; 222 | buildActionMask = 2147483647; 223 | files = ( 224 | 2FA9FE27CB1EAF9F3B9CC65F63483445 /* Pods-Deeplinks-umbrella.h in Headers */, 225 | ); 226 | runOnlyForDeploymentPostprocessing = 0; 227 | }; 228 | /* End PBXHeadersBuildPhase section */ 229 | 230 | /* Begin PBXNativeTarget section */ 231 | B2499C604716BBAE5BCFA7A1EA85329B /* PusherSwift */ = { 232 | isa = PBXNativeTarget; 233 | buildConfigurationList = E32EB233088FD4D48BD0245A5C341C0F /* Build configuration list for PBXNativeTarget "PusherSwift" */; 234 | buildPhases = ( 235 | 105CF780673845AF0D99B30AB7B9F861 /* Sources */, 236 | AB6EDEEF7720F8318DD5EEBF28CEEDC1 /* Frameworks */, 237 | 477010E7AE4368D8DE851EBE826F6B5D /* Headers */, 238 | ); 239 | buildRules = ( 240 | ); 241 | dependencies = ( 242 | ); 243 | name = PusherSwift; 244 | productName = PusherSwift; 245 | productReference = 70E441C9FA9847F3DAF6EC4B9614001D /* PusherSwift.framework */; 246 | productType = "com.apple.product-type.framework"; 247 | }; 248 | C9965FDFA6D85A2611D815D9540CECD3 /* Pods-Deeplinks */ = { 249 | isa = PBXNativeTarget; 250 | buildConfigurationList = CA7CB4FCC17C1591A79BBCB70506C888 /* Build configuration list for PBXNativeTarget "Pods-Deeplinks" */; 251 | buildPhases = ( 252 | BAE7DDE88E0FC12A5F786E38ED7801BB /* Sources */, 253 | 93238982ADC52867CEA2F7DAADBBD581 /* Frameworks */, 254 | 85555A70F985B1B48BB75C9678A5CCFE /* Headers */, 255 | ); 256 | buildRules = ( 257 | ); 258 | dependencies = ( 259 | E905979D5120C1DCE1D6843DF3BE2CB3 /* PBXTargetDependency */, 260 | ); 261 | name = "Pods-Deeplinks"; 262 | productName = "Pods-Deeplinks"; 263 | productReference = 9407E47B3334CB9C489F1FF3CA23ADAC /* Pods_Deeplinks.framework */; 264 | productType = "com.apple.product-type.framework"; 265 | }; 266 | /* End PBXNativeTarget section */ 267 | 268 | /* Begin PBXProject section */ 269 | D41D8CD98F00B204E9800998ECF8427E /* Project object */ = { 270 | isa = PBXProject; 271 | attributes = { 272 | LastSwiftUpdateCheck = 0730; 273 | LastUpgradeCheck = 0700; 274 | }; 275 | buildConfigurationList = 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */; 276 | compatibilityVersion = "Xcode 3.2"; 277 | developmentRegion = English; 278 | hasScannedForEncodings = 0; 279 | knownRegions = ( 280 | en, 281 | ); 282 | mainGroup = 7DB346D0F39D3F0E887471402A8071AB; 283 | productRefGroup = 5EEC0F6A87073D20513C2287BCAFAF02 /* Products */; 284 | projectDirPath = ""; 285 | projectRoot = ""; 286 | targets = ( 287 | C9965FDFA6D85A2611D815D9540CECD3 /* Pods-Deeplinks */, 288 | B2499C604716BBAE5BCFA7A1EA85329B /* PusherSwift */, 289 | ); 290 | }; 291 | /* End PBXProject section */ 292 | 293 | /* Begin PBXSourcesBuildPhase section */ 294 | 105CF780673845AF0D99B30AB7B9F861 /* Sources */ = { 295 | isa = PBXSourcesBuildPhase; 296 | buildActionMask = 2147483647; 297 | files = ( 298 | B3FEEE9818785CAF50EAF2AC21FD3799 /* CryptoSwiftHMACModule.swift in Sources */, 299 | 90146064F6247A7C9D32172FEE4180C4 /* NativePusher.swift in Sources */, 300 | 685A2A2D5A7C53B1DDB199F87BB49D4F /* ObjectiveC.swift in Sources */, 301 | 291D6DFE7B93A51B15B5C2794C8F8023 /* PusherChannel.swift in Sources */, 302 | 5D91B178E9CED5B8755DDEFA61868A78 /* PusherChannels.swift in Sources */, 303 | 93ABDED860287084348A27EEE57001A0 /* PusherClientOptions.swift in Sources */, 304 | AF1EB8E2D32FC64172D7A933CFC7214E /* PusherConnection.swift in Sources */, 305 | 7D88AF13FFD3C16ECEB25A723B5497DF /* PusherDelegate.swift in Sources */, 306 | C495374D83E6574D02F4D14DD4238679 /* PusherGlobalChannel.swift in Sources */, 307 | 39282269B271C04EA04E4DA20BD98728 /* PusherPresenceChannel.swift in Sources */, 308 | 02CFFC5304A670C7FE75B99AE6DDD1C7 /* PusherSwift-dummy.m in Sources */, 309 | 6D13E39920E7181BB94264A6881DE6F5 /* PusherSwift.swift in Sources */, 310 | 4800C2D41B1ED5238FB7AC76E1167950 /* PusherWebsocketDelegate.swift in Sources */, 311 | 5D69EFA02E94866CC27C0FE7FB9CF94B /* Reachability.swift in Sources */, 312 | FC38D39DF058A947A70EAA1B1979CFF6 /* Starscream.swift in Sources */, 313 | C5C8D389B53E3F96D5E580EE9CD6BD06 /* TaskQueue.swift in Sources */, 314 | ); 315 | runOnlyForDeploymentPostprocessing = 0; 316 | }; 317 | BAE7DDE88E0FC12A5F786E38ED7801BB /* Sources */ = { 318 | isa = PBXSourcesBuildPhase; 319 | buildActionMask = 2147483647; 320 | files = ( 321 | F85B427324253FD28C4C6D6AA84CE742 /* Pods-Deeplinks-dummy.m in Sources */, 322 | ); 323 | runOnlyForDeploymentPostprocessing = 0; 324 | }; 325 | /* End PBXSourcesBuildPhase section */ 326 | 327 | /* Begin PBXTargetDependency section */ 328 | E905979D5120C1DCE1D6843DF3BE2CB3 /* PBXTargetDependency */ = { 329 | isa = PBXTargetDependency; 330 | name = PusherSwift; 331 | target = B2499C604716BBAE5BCFA7A1EA85329B /* PusherSwift */; 332 | targetProxy = 02F965B1CF3EE17A78BFBEC424085B11 /* PBXContainerItemProxy */; 333 | }; 334 | /* End PBXTargetDependency section */ 335 | 336 | /* Begin XCBuildConfiguration section */ 337 | 12914D756594D15C6F2CA12FE5F89F1B /* Debug */ = { 338 | isa = XCBuildConfiguration; 339 | buildSettings = { 340 | ALWAYS_SEARCH_USER_PATHS = NO; 341 | CLANG_ANALYZER_NONNULL = YES; 342 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 343 | CLANG_CXX_LIBRARY = "libc++"; 344 | CLANG_ENABLE_MODULES = YES; 345 | CLANG_ENABLE_OBJC_ARC = YES; 346 | CLANG_WARN_BOOL_CONVERSION = YES; 347 | CLANG_WARN_CONSTANT_CONVERSION = YES; 348 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; 349 | CLANG_WARN_EMPTY_BODY = YES; 350 | CLANG_WARN_ENUM_CONVERSION = YES; 351 | CLANG_WARN_INT_CONVERSION = YES; 352 | CLANG_WARN_OBJC_ROOT_CLASS = YES; 353 | CLANG_WARN_UNREACHABLE_CODE = YES; 354 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 355 | CODE_SIGNING_REQUIRED = NO; 356 | COPY_PHASE_STRIP = NO; 357 | ENABLE_TESTABILITY = YES; 358 | GCC_C_LANGUAGE_STANDARD = gnu99; 359 | GCC_DYNAMIC_NO_PIC = NO; 360 | GCC_OPTIMIZATION_LEVEL = 0; 361 | GCC_PREPROCESSOR_DEFINITIONS = ( 362 | "POD_CONFIGURATION_DEBUG=1", 363 | "DEBUG=1", 364 | "$(inherited)", 365 | ); 366 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 367 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 368 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 369 | GCC_WARN_UNDECLARED_SELECTOR = YES; 370 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 371 | GCC_WARN_UNUSED_FUNCTION = YES; 372 | GCC_WARN_UNUSED_VARIABLE = YES; 373 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 374 | ONLY_ACTIVE_ARCH = YES; 375 | PROVISIONING_PROFILE_SPECIFIER = NO_SIGNING/; 376 | STRIP_INSTALLED_PRODUCT = NO; 377 | SYMROOT = "${SRCROOT}/../build"; 378 | }; 379 | name = Debug; 380 | }; 381 | 13B567EBB0B9AA3D28BEDCBB355BD9E7 /* Debug */ = { 382 | isa = XCBuildConfiguration; 383 | baseConfigurationReference = 0F52FFEDFF1F7F348851B439BDE48118 /* PusherSwift.xcconfig */; 384 | buildSettings = { 385 | "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; 386 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 387 | "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; 388 | CURRENT_PROJECT_VERSION = 1; 389 | DEBUG_INFORMATION_FORMAT = dwarf; 390 | DEFINES_MODULE = YES; 391 | DYLIB_COMPATIBILITY_VERSION = 1; 392 | DYLIB_CURRENT_VERSION = 1; 393 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 394 | ENABLE_STRICT_OBJC_MSGSEND = YES; 395 | GCC_NO_COMMON_BLOCKS = YES; 396 | GCC_PREFIX_HEADER = "Target Support Files/PusherSwift/PusherSwift-prefix.pch"; 397 | INFOPLIST_FILE = "Target Support Files/PusherSwift/Info.plist"; 398 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 399 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 400 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 401 | MODULEMAP_FILE = "Target Support Files/PusherSwift/PusherSwift.modulemap"; 402 | MTL_ENABLE_DEBUG_INFO = YES; 403 | PRODUCT_NAME = PusherSwift; 404 | SDKROOT = iphoneos; 405 | SKIP_INSTALL = YES; 406 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 407 | SWIFT_VERSION = 3.0; 408 | TARGETED_DEVICE_FAMILY = "1,2"; 409 | VERSIONING_SYSTEM = "apple-generic"; 410 | VERSION_INFO_PREFIX = ""; 411 | }; 412 | name = Debug; 413 | }; 414 | 339D595AAFCBD812AB8052F95D4A5B34 /* Release */ = { 415 | isa = XCBuildConfiguration; 416 | baseConfigurationReference = E9A9C7EBBAC6EB7C3BA0E1E8864F20E7 /* Pods-Deeplinks.release.xcconfig */; 417 | buildSettings = { 418 | "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; 419 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 420 | "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; 421 | CURRENT_PROJECT_VERSION = 1; 422 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 423 | DEFINES_MODULE = YES; 424 | DYLIB_COMPATIBILITY_VERSION = 1; 425 | DYLIB_CURRENT_VERSION = 1; 426 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 427 | ENABLE_STRICT_OBJC_MSGSEND = YES; 428 | GCC_NO_COMMON_BLOCKS = YES; 429 | INFOPLIST_FILE = "Target Support Files/Pods-Deeplinks/Info.plist"; 430 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 431 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 432 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 433 | MACH_O_TYPE = staticlib; 434 | MODULEMAP_FILE = "Target Support Files/Pods-Deeplinks/Pods-Deeplinks.modulemap"; 435 | MTL_ENABLE_DEBUG_INFO = NO; 436 | OTHER_LDFLAGS = ""; 437 | OTHER_LIBTOOLFLAGS = ""; 438 | PODS_ROOT = "$(SRCROOT)"; 439 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; 440 | PRODUCT_NAME = Pods_Deeplinks; 441 | SDKROOT = iphoneos; 442 | SKIP_INSTALL = YES; 443 | TARGETED_DEVICE_FAMILY = "1,2"; 444 | VERSIONING_SYSTEM = "apple-generic"; 445 | VERSION_INFO_PREFIX = ""; 446 | }; 447 | name = Release; 448 | }; 449 | 5D1AD2B19F5B292D870156D0559975F5 /* Debug */ = { 450 | isa = XCBuildConfiguration; 451 | baseConfigurationReference = B9A4360EDE42D6871AE28D958E138CD1 /* Pods-Deeplinks.debug.xcconfig */; 452 | buildSettings = { 453 | "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; 454 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 455 | "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; 456 | CURRENT_PROJECT_VERSION = 1; 457 | DEBUG_INFORMATION_FORMAT = dwarf; 458 | DEFINES_MODULE = YES; 459 | DYLIB_COMPATIBILITY_VERSION = 1; 460 | DYLIB_CURRENT_VERSION = 1; 461 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 462 | ENABLE_STRICT_OBJC_MSGSEND = YES; 463 | GCC_NO_COMMON_BLOCKS = YES; 464 | INFOPLIST_FILE = "Target Support Files/Pods-Deeplinks/Info.plist"; 465 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 466 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 467 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 468 | MACH_O_TYPE = staticlib; 469 | MODULEMAP_FILE = "Target Support Files/Pods-Deeplinks/Pods-Deeplinks.modulemap"; 470 | MTL_ENABLE_DEBUG_INFO = YES; 471 | OTHER_LDFLAGS = ""; 472 | OTHER_LIBTOOLFLAGS = ""; 473 | PODS_ROOT = "$(SRCROOT)"; 474 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; 475 | PRODUCT_NAME = Pods_Deeplinks; 476 | SDKROOT = iphoneos; 477 | SKIP_INSTALL = YES; 478 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 479 | TARGETED_DEVICE_FAMILY = "1,2"; 480 | VERSIONING_SYSTEM = "apple-generic"; 481 | VERSION_INFO_PREFIX = ""; 482 | }; 483 | name = Debug; 484 | }; 485 | D946AF56AA9F04231582CE2F38C1748E /* Release */ = { 486 | isa = XCBuildConfiguration; 487 | baseConfigurationReference = 0F52FFEDFF1F7F348851B439BDE48118 /* PusherSwift.xcconfig */; 488 | buildSettings = { 489 | "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; 490 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 491 | "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; 492 | CURRENT_PROJECT_VERSION = 1; 493 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 494 | DEFINES_MODULE = YES; 495 | DYLIB_COMPATIBILITY_VERSION = 1; 496 | DYLIB_CURRENT_VERSION = 1; 497 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 498 | ENABLE_STRICT_OBJC_MSGSEND = YES; 499 | GCC_NO_COMMON_BLOCKS = YES; 500 | GCC_PREFIX_HEADER = "Target Support Files/PusherSwift/PusherSwift-prefix.pch"; 501 | INFOPLIST_FILE = "Target Support Files/PusherSwift/Info.plist"; 502 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 503 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 504 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 505 | MODULEMAP_FILE = "Target Support Files/PusherSwift/PusherSwift.modulemap"; 506 | MTL_ENABLE_DEBUG_INFO = NO; 507 | PRODUCT_NAME = PusherSwift; 508 | SDKROOT = iphoneos; 509 | SKIP_INSTALL = YES; 510 | SWIFT_VERSION = 3.0; 511 | TARGETED_DEVICE_FAMILY = "1,2"; 512 | VERSIONING_SYSTEM = "apple-generic"; 513 | VERSION_INFO_PREFIX = ""; 514 | }; 515 | name = Release; 516 | }; 517 | E72E7977875C2D251FC62736BBDDC389 /* Release */ = { 518 | isa = XCBuildConfiguration; 519 | buildSettings = { 520 | ALWAYS_SEARCH_USER_PATHS = NO; 521 | CLANG_ANALYZER_NONNULL = YES; 522 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 523 | CLANG_CXX_LIBRARY = "libc++"; 524 | CLANG_ENABLE_MODULES = YES; 525 | CLANG_ENABLE_OBJC_ARC = YES; 526 | CLANG_WARN_BOOL_CONVERSION = YES; 527 | CLANG_WARN_CONSTANT_CONVERSION = YES; 528 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; 529 | CLANG_WARN_EMPTY_BODY = YES; 530 | CLANG_WARN_ENUM_CONVERSION = YES; 531 | CLANG_WARN_INT_CONVERSION = YES; 532 | CLANG_WARN_OBJC_ROOT_CLASS = YES; 533 | CLANG_WARN_UNREACHABLE_CODE = YES; 534 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 535 | CODE_SIGNING_REQUIRED = NO; 536 | COPY_PHASE_STRIP = YES; 537 | ENABLE_NS_ASSERTIONS = NO; 538 | GCC_C_LANGUAGE_STANDARD = gnu99; 539 | GCC_PREPROCESSOR_DEFINITIONS = ( 540 | "POD_CONFIGURATION_RELEASE=1", 541 | "$(inherited)", 542 | ); 543 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 544 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 545 | GCC_WARN_UNDECLARED_SELECTOR = YES; 546 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 547 | GCC_WARN_UNUSED_FUNCTION = YES; 548 | GCC_WARN_UNUSED_VARIABLE = YES; 549 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 550 | PROVISIONING_PROFILE_SPECIFIER = NO_SIGNING/; 551 | STRIP_INSTALLED_PRODUCT = NO; 552 | SYMROOT = "${SRCROOT}/../build"; 553 | VALIDATE_PRODUCT = YES; 554 | }; 555 | name = Release; 556 | }; 557 | /* End XCBuildConfiguration section */ 558 | 559 | /* Begin XCConfigurationList section */ 560 | 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */ = { 561 | isa = XCConfigurationList; 562 | buildConfigurations = ( 563 | 12914D756594D15C6F2CA12FE5F89F1B /* Debug */, 564 | E72E7977875C2D251FC62736BBDDC389 /* Release */, 565 | ); 566 | defaultConfigurationIsVisible = 0; 567 | defaultConfigurationName = Release; 568 | }; 569 | CA7CB4FCC17C1591A79BBCB70506C888 /* Build configuration list for PBXNativeTarget "Pods-Deeplinks" */ = { 570 | isa = XCConfigurationList; 571 | buildConfigurations = ( 572 | 5D1AD2B19F5B292D870156D0559975F5 /* Debug */, 573 | 339D595AAFCBD812AB8052F95D4A5B34 /* Release */, 574 | ); 575 | defaultConfigurationIsVisible = 0; 576 | defaultConfigurationName = Release; 577 | }; 578 | E32EB233088FD4D48BD0245A5C341C0F /* Build configuration list for PBXNativeTarget "PusherSwift" */ = { 579 | isa = XCConfigurationList; 580 | buildConfigurations = ( 581 | 13B567EBB0B9AA3D28BEDCBB355BD9E7 /* Debug */, 582 | D946AF56AA9F04231582CE2F38C1748E /* Release */, 583 | ); 584 | defaultConfigurationIsVisible = 0; 585 | defaultConfigurationName = Release; 586 | }; 587 | /* End XCConfigurationList section */ 588 | }; 589 | rootObject = D41D8CD98F00B204E9800998ECF8427E /* Project object */; 590 | } 591 | -------------------------------------------------------------------------------- /Pods/Pods.xcodeproj/xcuserdata/stanislavostrovskiy.xcuserdatad/xcschemes/Pods-Deeplinks.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 66 | 67 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /Pods/Pods.xcodeproj/xcuserdata/stanislavostrovskiy.xcuserdatad/xcschemes/PusherSwift.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 44 | 45 | 46 | 52 | 53 | 55 | 56 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /Pods/Pods.xcodeproj/xcuserdata/stanislavostrovskiy.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Pods-Deeplinks.xcscheme 8 | 9 | isShown 10 | 11 | 12 | PusherSwift.xcscheme 13 | 14 | isShown 15 | 16 | 17 | 18 | SuppressBuildableAutocreation 19 | 20 | B2499C604716BBAE5BCFA7A1EA85329B 21 | 22 | primary 23 | 24 | 25 | C9965FDFA6D85A2611D815D9540CECD3 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /Pods/PusherSwift/LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 Pusher Ltd. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. -------------------------------------------------------------------------------- /Pods/PusherSwift/Source/NativePusher.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NativePusher.swift 3 | // PusherSwift 4 | // 5 | // Created by James Fisher on 09/06/2016. 6 | // 7 | // 8 | 9 | #if os(iOS) || os(OSX) 10 | 11 | /** 12 | An interface to Pusher's native push notification service. 13 | The service is a pub-sub system for push notifications. 14 | Notifications are published to "interests". 15 | Clients (such as this app instance) subscribe to those interests. 16 | 17 | A per-app instance NativePusher is available via an instance of Pusher. 18 | */ 19 | @objc open class NativePusher: NSObject { 20 | private static let PLATFORM_TYPE = "apns" 21 | private let CLIENT_API_V1_ENDPOINT = "https://nativepushclient-cluster1.pusher.com/client_api/v1" 22 | private let LIBRARY_NAME_AND_VERSION = "pusher-websocket-swift " + VERSION 23 | 24 | public var URLSession = Foundation.URLSession.shared 25 | private var failedRequestAttempts: Int = 0 26 | private let maxFailedRequestAttempts: Int = 6 27 | 28 | internal weak var delegate: PusherDelegate? = nil 29 | 30 | internal var requestQueue = TaskQueue() 31 | 32 | /** 33 | Identifies a Pusher app, which should have push notifications enabled 34 | and a certificate added for the push notifications to work 35 | */ 36 | private var pusherAppKey: String? = nil 37 | 38 | /** 39 | The id issued to this app instance by Pusher, which is received upon 40 | registrations. It's used to identify a client when subscribe / 41 | unsubscribe requests are made 42 | */ 43 | internal var clientId: String? = nil 44 | 45 | /** 46 | Normal clients should access the instance via Pusher.nativePusher() 47 | */ 48 | internal override init() {} 49 | 50 | /** 51 | Sets the pusherAppKey property and then attempts to flush 52 | the outbox of any pending requests 53 | 54 | - parameter pusherAppKey: The Pusher app key 55 | */ 56 | open func setPusherAppKey(pusherAppKey: String) { 57 | self.pusherAppKey = pusherAppKey 58 | 59 | if self.clientId != nil { 60 | requestQueue.run() 61 | } 62 | } 63 | 64 | /** 65 | Makes device token presentable to server 66 | 67 | - parameter deviceToken: the deviceToken received when registering 68 | to receive push notifications, as Data 69 | 70 | - returns: the deviceToken formatted as a String 71 | */ 72 | private func deviceTokenToString(deviceToken: Data) -> String { 73 | var deviceTokenString: String = "" 74 | for i in 0..= 200 && httpResponse.statusCode < 300) { 105 | /** 106 | We expect to get a JSON response in the form: 107 | 108 | { 109 | "id": string, 110 | "pusher_app_key": string, 111 | "platform_type": either "apns" or "gcm", 112 | "token": string 113 | } 114 | 115 | Currently, we only care about the "id" value, which is our new client id. 116 | We store our id so that we can use it to subscribe/unsubscribe. 117 | */ 118 | if let json = try! JSONSerialization.jsonObject(with: data!, options: []) 119 | as? [String: AnyObject] { 120 | if let clientIdJson = json["id"] { 121 | if let clientId = clientIdJson as? String { 122 | self.clientId = clientId 123 | self.delegate?.registeredForPushNotifications?(clientId: clientId) 124 | self.delegate?.debugLog?(message: "Successfully registered for push notifications and got clientId: \(clientId)") 125 | self.requestQueue.run() 126 | } else { 127 | self.delegate?.debugLog?(message: "Value at \"id\" key in JSON response was not a string: \(json)") 128 | } 129 | } else { 130 | self.delegate?.debugLog?(message: "No \"id\" key in JSON response: \(json)") 131 | } 132 | } else { 133 | self.delegate?.debugLog?(message: "Could not parse body as JSON object: \(String(describing: data))") 134 | } 135 | } else { 136 | if data != nil && response != nil { 137 | let responseBody = String(data: data!, encoding: .utf8) 138 | self.delegate?.failedToRegisterForPushNotifications?(response: response!, responseBody: responseBody) 139 | self.delegate?.debugLog?(message: "Bad HTTP response: \(response!) with body: \(String(describing: responseBody))") 140 | } 141 | } 142 | }) 143 | 144 | task.resume() 145 | } 146 | 147 | /** 148 | Subscribe to an interest with Pusher's Push Notification Service 149 | 150 | - parameter interestName: the name of the interest you want to subscribe to 151 | */ 152 | open func subscribe(interestName: String) { 153 | addSubscriptionChangeToTaskQueue(interestName: interestName, change: .subscribe) 154 | } 155 | 156 | /** 157 | Unsubscribe from an interest with Pusher's Push Notification Service 158 | 159 | - parameter interestName: the name of the interest you want to unsubscribe 160 | from 161 | */ 162 | open func unsubscribe(interestName: String) { 163 | addSubscriptionChangeToTaskQueue(interestName: interestName, change: .unsubscribe) 164 | } 165 | 166 | /** 167 | Adds subscribe / unsubscribe tasts to task queue 168 | 169 | - parameter interestName: the name of the interest you want to interact with 170 | - parameter change: specifies whether the change is to subscribe or 171 | unsubscribe 172 | 173 | */ 174 | private func addSubscriptionChangeToTaskQueue(interestName: String, change: SubscriptionChange) { 175 | requestQueue.tasks += { _, next in 176 | self.modifySubscription( 177 | interest: interestName, 178 | change: change, 179 | successCallback: next 180 | ) 181 | } 182 | 183 | requestQueue.run() 184 | } 185 | 186 | /** 187 | Makes either a POST or DELETE request for a given interest 188 | 189 | - parameter pusherAppKey: The app key for the Pusher app 190 | - parameter clientId: The clientId returned by Pusher's server 191 | - parameter interest: The name of the interest to be subscribed to / 192 | unsunscribed from 193 | - parameter change: Whether to subscribe or unsubscribe 194 | - parameter callback: Callback to be called upon success 195 | */ 196 | private func modifySubscription(interest: String, change: SubscriptionChange, successCallback: @escaping (Any?) -> Void) { 197 | guard pusherAppKey != nil && clientId != nil else { 198 | self.delegate?.debugLog?(message: "pusherAppKey \(String(describing: pusherAppKey)) or clientId \(String(describing: clientId)) not set - waiting for both to be set") 199 | self.requestQueue.pauseAndResetCurrentTask() 200 | return 201 | } 202 | 203 | self.delegate?.debugLog?(message: "Attempt number: \(self.failedRequestAttempts + 1) of \(maxFailedRequestAttempts)") 204 | 205 | let url = "\(CLIENT_API_V1_ENDPOINT)/clients/\(clientId!)/interests/\(interest)" 206 | var request = URLRequest(url: URL(string: url)!) 207 | request.httpMethod = change.httpMethod() 208 | 209 | let params: [String: Any] = ["app_key": pusherAppKey!] 210 | try! request.httpBody = JSONSerialization.data(withJSONObject: params, options: []) 211 | 212 | request.addValue("application/json", forHTTPHeaderField: "Content-Type") 213 | request.addValue(LIBRARY_NAME_AND_VERSION, forHTTPHeaderField: "X-Pusher-Library") 214 | 215 | let task = URLSession.dataTask( 216 | with: request, 217 | completionHandler: { data, response, error in 218 | guard let httpResponse = response as? HTTPURLResponse, 219 | (200 <= httpResponse.statusCode && httpResponse.statusCode < 300) && 220 | error == nil 221 | else { 222 | self.failedRequestAttempts += 1 223 | 224 | if error != nil { 225 | self.delegate?.debugLog?(message: "Error when trying to modify subscription to interest: \(String(describing: error?.localizedDescription))") 226 | } else if data != nil && response != nil { 227 | let responseBody = String(data: data!, encoding: .utf8) 228 | self.delegate?.debugLog?(message: "Bad response from server: \(response!) with body: \(String(describing: responseBody))") 229 | } else { 230 | self.delegate?.debugLog?(message: "Bad response from server when trying to modify subscription to interest: \(interest)") 231 | } 232 | 233 | if self.failedRequestAttempts >= self.maxFailedRequestAttempts { 234 | self.delegate?.debugLog?(message: "Max number of failed native service requests reached") 235 | 236 | self.requestQueue.paused = true 237 | } else { 238 | self.delegate?.debugLog?(message: "Retrying subscription modification request for interest: \(interest)") 239 | self.requestQueue.retry(Double(self.failedRequestAttempts * self.failedRequestAttempts)) 240 | } 241 | 242 | return 243 | } 244 | 245 | switch change { 246 | case .subscribe: 247 | self.delegate?.subscribedToInterest?(name: interest) 248 | case .unsubscribe: 249 | self.delegate?.unsubscribedFromInterest?(name: interest) 250 | } 251 | 252 | self.delegate?.debugLog?(message: "Success making \(change.stringValue) to \(interest)") 253 | 254 | self.failedRequestAttempts = 0 255 | successCallback(nil) 256 | } 257 | ) 258 | 259 | task.resume() 260 | } 261 | } 262 | 263 | internal enum SubscriptionChange { 264 | case subscribe 265 | case unsubscribe 266 | 267 | internal func stringValue() -> String { 268 | switch self { 269 | case .subscribe: 270 | return "subscribe" 271 | case .unsubscribe: 272 | return "unsubscribe" 273 | } 274 | } 275 | 276 | internal func httpMethod() -> String { 277 | switch self { 278 | case .subscribe: 279 | return "POST" 280 | case .unsubscribe: 281 | return "DELETE" 282 | } 283 | } 284 | } 285 | 286 | #endif 287 | -------------------------------------------------------------------------------- /Pods/PusherSwift/Source/ObjectiveC.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ObjectiveC.swift 3 | // PusherSwift 4 | // 5 | // Created by Hamilton Chapman on 20/08/2016. 6 | // 7 | // 8 | 9 | public extension Pusher { 10 | @objc public func subscribe(channelName: String) -> PusherChannel { 11 | return self.subscribe(channelName, onMemberAdded: nil, onMemberRemoved: nil) 12 | } 13 | 14 | @objc public func subscribe( 15 | channelName: String, 16 | onMemberAdded: ((PusherPresenceChannelMember) -> ())? = nil, 17 | onMemberRemoved: ((PusherPresenceChannelMember) -> ())? = nil) -> PusherChannel { 18 | return self.subscribe(channelName, auth: nil, onMemberAdded: onMemberAdded, onMemberRemoved: onMemberRemoved) 19 | } 20 | 21 | @objc public func subscribeToPresenceChannel(channelName: String) -> PusherPresenceChannel { 22 | return self.subscribeToPresenceChannel(channelName: channelName, auth: nil, onMemberAdded: nil, onMemberRemoved: nil) 23 | } 24 | 25 | @objc public func subscribeToPresenceChannel( 26 | channelName: String, 27 | onMemberAdded: ((PusherPresenceChannelMember) -> ())? = nil, 28 | onMemberRemoved: ((PusherPresenceChannelMember) -> ())? = nil) -> PusherPresenceChannel { 29 | return self.subscribeToPresenceChannel(channelName: channelName, auth: nil, onMemberAdded: onMemberAdded, onMemberRemoved: onMemberRemoved) 30 | } 31 | 32 | @objc public convenience init(withAppKey key: String, options: PusherClientOptions) { 33 | self.init(key: key, options: options) 34 | } 35 | 36 | @objc public convenience init(withKey key: String) { 37 | self.init(key: key) 38 | } 39 | } 40 | 41 | public extension PusherClientOptions { 42 | public convenience init( 43 | ocAuthMethod authMethod: OCAuthMethod, 44 | attemptToReturnJSONObject: Bool = true, 45 | autoReconnect: Bool = true, 46 | ocHost host: OCPusherHost = PusherHost.host("ws.pusherapp.com").toObjc(), 47 | port: NSNumber? = nil, 48 | encrypted: Bool = true) { 49 | self.init( 50 | authMethod: AuthMethod.fromObjc(source: authMethod), 51 | attemptToReturnJSONObject: attemptToReturnJSONObject, 52 | autoReconnect: autoReconnect, 53 | host: PusherHost.fromObjc(source: host), 54 | port: port as? Int, 55 | encrypted: encrypted 56 | ) 57 | } 58 | 59 | public convenience init(authMethod: OCAuthMethod) { 60 | self.init(authMethod: AuthMethod.fromObjc(source: authMethod)) 61 | } 62 | 63 | public func setAuthMethod(authMethod: OCAuthMethod) { 64 | self.authMethod = AuthMethod.fromObjc(source: authMethod) 65 | } 66 | } 67 | 68 | 69 | public extension PusherHost { 70 | func toObjc() -> OCPusherHost { 71 | switch self { 72 | case let .host(host): 73 | return OCPusherHost(host: host) 74 | case let .cluster(cluster): 75 | return OCPusherHost(cluster: "ws-\(cluster).pusher.com") 76 | } 77 | } 78 | 79 | static func fromObjc(source: OCPusherHost) -> PusherHost { 80 | switch (source.type) { 81 | case 0: return PusherHost.host(source.host!) 82 | case 1: return PusherHost.cluster(source.cluster!) 83 | default: return PusherHost.host("ws.pusherapp.com") 84 | } 85 | } 86 | } 87 | 88 | @objc public class OCPusherHost: NSObject { 89 | var type: Int 90 | var host: String? = nil 91 | var cluster: String? = nil 92 | 93 | public override init() { 94 | self.type = 2 95 | } 96 | 97 | public init(host: String) { 98 | self.type = 0 99 | self.host = host 100 | } 101 | 102 | public init(cluster: String) { 103 | self.type = 1 104 | self.cluster = cluster 105 | } 106 | } 107 | 108 | public extension AuthMethod { 109 | func toObjc() -> OCAuthMethod { 110 | switch self { 111 | case let .endpoint(authEndpoint): 112 | return OCAuthMethod(authEndpoint: authEndpoint) 113 | case let .authRequestBuilder(authRequestBuilder): 114 | return OCAuthMethod(authRequestBuilder: authRequestBuilder) 115 | case let .inline(secret): 116 | return OCAuthMethod(secret: secret) 117 | case .noMethod: 118 | return OCAuthMethod(type: 3) 119 | } 120 | } 121 | 122 | static func fromObjc(source: OCAuthMethod) -> AuthMethod { 123 | switch (source.type) { 124 | case 0: return AuthMethod.endpoint(authEndpoint: source.authEndpoint!) 125 | case 1: return AuthMethod.authRequestBuilder(authRequestBuilder: source.authRequestBuilder!) 126 | case 2: return AuthMethod.inline(secret: source.secret!) 127 | case 3: return AuthMethod.noMethod 128 | default: return AuthMethod.noMethod 129 | } 130 | } 131 | } 132 | 133 | @objc public class OCAuthMethod: NSObject { 134 | var type: Int 135 | var secret: String? = nil 136 | var authEndpoint: String? = nil 137 | var authRequestBuilder: AuthRequestBuilderProtocol? = nil 138 | 139 | public init(type: Int) { 140 | self.type = type 141 | } 142 | 143 | public init(authEndpoint: String) { 144 | self.type = 0 145 | self.authEndpoint = authEndpoint 146 | } 147 | 148 | public init(authRequestBuilder: AuthRequestBuilderProtocol) { 149 | self.type = 1 150 | self.authRequestBuilder = authRequestBuilder 151 | } 152 | 153 | public init(secret: String) { 154 | self.type = 2 155 | self.secret = secret 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /Pods/PusherSwift/Source/PusherChannel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PusherChannel.swift 3 | // PusherSwift 4 | // 5 | // Created by Hamilton Chapman on 01/04/2016. 6 | // 7 | // 8 | 9 | public enum PusherChannelType { 10 | case `private` 11 | case presence 12 | case normal 13 | 14 | public init(name: String) { 15 | self = type(of: self).type(forName: name) 16 | } 17 | 18 | public static func type(forName name: String) -> PusherChannelType { 19 | if (name.components(separatedBy: "-")[0] == "presence") { 20 | return .presence 21 | } else if (name.components(separatedBy: "-")[0] == "private") { 22 | return .private 23 | } else { 24 | return .normal 25 | } 26 | } 27 | 28 | public static func isPresenceChannel(name: String) -> Bool { 29 | return PusherChannelType(name: name) == .presence 30 | } 31 | } 32 | 33 | open class PusherChannel: NSObject { 34 | open var eventHandlers: [String: [EventHandler]] = [:] 35 | open var subscribed = false 36 | open let name: String 37 | open weak var connection: PusherConnection? 38 | open var unsentEvents = [PusherEvent]() 39 | open let type: PusherChannelType 40 | public var auth: PusherAuth? 41 | 42 | /** 43 | Initializes a new PusherChannel with a given name and conenction 44 | 45 | - parameter name: The name of the channel 46 | - parameter connection: The connection that this channel is relevant to 47 | - parameter auth: A PusherAuth value if subscription is being made to an 48 | authenticated channel without using the default auth methods 49 | 50 | - returns: A new PusherChannel instance 51 | */ 52 | public init(name: String, connection: PusherConnection, auth: PusherAuth? = nil) { 53 | self.name = name 54 | self.connection = connection 55 | self.auth = auth 56 | self.type = PusherChannelType(name: name) 57 | } 58 | 59 | /** 60 | Binds a callback to a given event name, scoped to the PusherChannel the function is 61 | called on 62 | 63 | - parameter eventName: The name of the event to bind to 64 | - parameter callback: The function to call when a message is received with the relevant 65 | channel and event names 66 | 67 | - returns: A unique callbackId that can be used to unbind the callback at a later time 68 | */ 69 | @discardableResult open func bind(eventName: String, callback: @escaping (Any?) -> Void) -> String { 70 | let randomId = UUID().uuidString 71 | let eventHandler = EventHandler(id: randomId, callback: callback) 72 | if self.eventHandlers[eventName] != nil { 73 | self.eventHandlers[eventName]?.append(eventHandler) 74 | } else { 75 | self.eventHandlers[eventName] = [eventHandler] 76 | } 77 | return randomId 78 | } 79 | 80 | /** 81 | Unbinds the callback with the given callbackId from the given eventName, in the scope 82 | of the channel being acted upon 83 | 84 | - parameter eventName: The name of the event from which to unbind 85 | - parameter callbackId: The unique callbackId string used to identify which callback to unbind 86 | */ 87 | open func unbind(eventName: String, callbackId: String) { 88 | if let eventSpecificHandlers = self.eventHandlers[eventName] { 89 | self.eventHandlers[eventName] = eventSpecificHandlers.filter({ $0.id != callbackId }) 90 | } 91 | } 92 | 93 | /** 94 | Unbinds all callbacks from the channel 95 | */ 96 | open func unbindAll() { 97 | self.eventHandlers = [:] 98 | } 99 | 100 | /** 101 | Unbinds all callbacks for the given eventName from the channel 102 | 103 | - parameter eventName: The name of the event from which to unbind 104 | */ 105 | open func unbindAll(forEventName eventName: String) { 106 | self.eventHandlers[eventName] = [] 107 | } 108 | 109 | /** 110 | Calls the appropriate callbacks for the given eventName in the scope of the acted upon channel 111 | 112 | - parameter name: The name of the received event 113 | - parameter data: The data associated with the received message 114 | */ 115 | open func handleEvent(name: String, data: String) { 116 | if let eventHandlerArray = self.eventHandlers[name] { 117 | let jsonize = connection?.options.attemptToReturnJSONObject ?? true 118 | 119 | for eventHandler in eventHandlerArray { 120 | eventHandler.callback(jsonize ? connection?.getEventDataJSON(from: data) : data) 121 | } 122 | } 123 | } 124 | 125 | /** 126 | If subscribed, immediately call the connection to trigger a client event with the given 127 | eventName and data, otherwise queue it up to be triggered upon successful subscription 128 | 129 | - parameter eventName: The name of the event to trigger 130 | - parameter data: The data to be sent as the message payload 131 | */ 132 | open func trigger(eventName: String, data: Any) { 133 | if subscribed { 134 | connection?.sendEvent(event: eventName, data: data, channel: self) 135 | } else { 136 | unsentEvents.insert(PusherEvent(name: eventName, data: data), at: 0) 137 | } 138 | } 139 | } 140 | 141 | public struct EventHandler { 142 | let id: String 143 | let callback: (Any?) -> Void 144 | } 145 | 146 | public struct PusherEvent { 147 | public let name: String 148 | public let data: Any 149 | } 150 | -------------------------------------------------------------------------------- /Pods/PusherSwift/Source/PusherChannels.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PusherGlobalChannel.swift 3 | // PusherSwift 4 | // 5 | // Created by Hamilton Chapman on 01/04/2016. 6 | // 7 | // 8 | 9 | open class PusherChannels: NSObject { 10 | open var channels = [String: PusherChannel]() 11 | 12 | /** 13 | Create a new PusherChannel, which is returned, and add it to the PusherChannels list 14 | of channels 15 | 16 | - parameter name: The name of the channel to create 17 | - parameter connection: The connection associated with the channel being created 18 | - parameter auth: A PusherAuth value if subscription is being made to an 19 | authenticated channel without using the default auth methods 20 | - parameter onMemberAdded: A function that will be called with information about the 21 | member who has just joined the presence channel 22 | - parameter onMemberRemoved: A function that will be called with information about the 23 | member who has just left the presence channel 24 | 25 | - returns: A new PusherChannel instance 26 | */ 27 | internal func add( 28 | name: String, 29 | connection: PusherConnection, 30 | auth: PusherAuth? = nil, 31 | onMemberAdded: ((PusherPresenceChannelMember) -> ())? = nil, 32 | onMemberRemoved: ((PusherPresenceChannelMember) -> ())? = nil) -> PusherChannel { 33 | if let channel = self.channels[name] { 34 | return channel 35 | } else { 36 | var newChannel: PusherChannel 37 | if PusherChannelType.isPresenceChannel(name: name) { 38 | newChannel = PusherPresenceChannel( 39 | name: name, 40 | connection: connection, 41 | auth: auth, 42 | onMemberAdded: onMemberAdded, 43 | onMemberRemoved: onMemberRemoved 44 | ) 45 | } else { 46 | newChannel = PusherChannel(name: name, connection: connection, auth: auth) 47 | } 48 | self.channels[name] = newChannel 49 | return newChannel 50 | } 51 | } 52 | 53 | /** 54 | Create a new PresencPusherChannel, which is returned, and add it to the PusherChannels 55 | list of channels 56 | 57 | - parameter channelName: The name of the channel to create 58 | - parameter connection: The connection associated with the channel being created 59 | - parameter auth: A PusherAuth value if subscription is being made to an 60 | authenticated channel without using the default auth methods 61 | - parameter onMemberAdded: A function that will be called with information about the 62 | member who has just joined the presence channel 63 | - parameter onMemberRemoved: A function that will be called with information about the 64 | member who has just left the presence channel 65 | 66 | - returns: A new PusherPresenceChannel instance 67 | */ 68 | internal func addPresence( 69 | channelName: String, 70 | connection: PusherConnection, 71 | auth: PusherAuth? = nil, 72 | onMemberAdded: ((PusherPresenceChannelMember) -> ())? = nil, 73 | onMemberRemoved: ((PusherPresenceChannelMember) -> ())? = nil) -> PusherPresenceChannel { 74 | if let channel = self.channels[channelName] as? PusherPresenceChannel { 75 | return channel 76 | } else { 77 | let newChannel = PusherPresenceChannel( 78 | name: channelName, 79 | connection: connection, 80 | auth: auth, 81 | onMemberAdded: onMemberAdded, 82 | onMemberRemoved: onMemberRemoved 83 | ) 84 | self.channels[channelName] = newChannel 85 | return newChannel 86 | } 87 | } 88 | 89 | /** 90 | Remove the PusherChannel with the given channelName from the channels list 91 | 92 | - parameter name: The name of the channel to remove 93 | */ 94 | internal func remove(name: String) { 95 | self.channels.removeValue(forKey: name) 96 | } 97 | 98 | /** 99 | Return the PusherChannel with the given channelName from the channels list, if it exists 100 | 101 | - parameter name: The name of the channel to return 102 | 103 | - returns: A PusherChannel instance, if a channel with the given name existed, otherwise nil 104 | */ 105 | public func find(name: String) -> PusherChannel? { 106 | return self.channels[name] 107 | } 108 | 109 | /** 110 | Return the PusherPresenceChannel with the given channelName from the channels list, if it exists 111 | 112 | - parameter name: The name of the presence channel to return 113 | 114 | - returns: A PusherPresenceChannel instance, if a channel with the given name existed, 115 | otherwise nil 116 | */ 117 | public func findPresence(name: String) -> PusherPresenceChannel? { 118 | return self.channels[name] as? PusherPresenceChannel 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /Pods/PusherSwift/Source/PusherClientOptions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PusherClientOptions.swift 3 | // PusherSwift 4 | // 5 | // Created by Hamilton Chapman on 01/04/2016. 6 | // 7 | // 8 | 9 | public enum PusherHost { 10 | case host(String) 11 | case cluster(String) 12 | 13 | public var stringValue: String { 14 | switch self { 15 | case .host(let host): return host 16 | case .cluster(let cluster): return "ws-\(cluster).pusher.com" 17 | } 18 | } 19 | } 20 | 21 | @objc public protocol AuthRequestBuilderProtocol { 22 | @available(*, deprecated: 4.0.2, message: "use requestFor(socketID: String, channelName: String) -> URLRequest? instead") 23 | @objc optional func requestFor(socketID: String, channel: PusherChannel) -> NSMutableURLRequest? 24 | 25 | @objc optional func requestFor(socketID: String, channelName: String) -> URLRequest? 26 | } 27 | 28 | public enum AuthMethod { 29 | case endpoint(authEndpoint: String) 30 | case authRequestBuilder(authRequestBuilder: AuthRequestBuilderProtocol) 31 | case inline(secret: String) 32 | case noMethod 33 | } 34 | 35 | @objc public class PusherClientOptions: NSObject { 36 | public var authMethod: AuthMethod 37 | public let attemptToReturnJSONObject: Bool 38 | public let autoReconnect: Bool 39 | public let host: String 40 | public let port: Int 41 | public let encrypted: Bool 42 | 43 | @nonobjc public init( 44 | authMethod: AuthMethod = .noMethod, 45 | attemptToReturnJSONObject: Bool = true, 46 | autoReconnect: Bool = true, 47 | host: PusherHost = .host("ws.pusherapp.com"), 48 | port: Int? = nil, 49 | encrypted: Bool = true) { 50 | self.authMethod = authMethod 51 | self.attemptToReturnJSONObject = attemptToReturnJSONObject 52 | self.autoReconnect = autoReconnect 53 | self.host = host.stringValue 54 | self.port = port ?? (encrypted ? 443 : 80) 55 | self.encrypted = encrypted 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Pods/PusherSwift/Source/PusherConnection.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PusherConnection.swift 3 | // PusherSwift 4 | // 5 | // Created by Hamilton Chapman on 01/04/2016. 6 | // 7 | // 8 | 9 | public typealias PusherEventJSON = [String: AnyObject] 10 | 11 | open class PusherConnection: NSObject { 12 | open let url: String 13 | open let key: String 14 | open var options: PusherClientOptions 15 | open var globalChannel: GlobalChannel! 16 | open var socketId: String? 17 | open var connectionState = ConnectionState.disconnected 18 | open var channels = PusherChannels() 19 | open var socket: WebSocket! 20 | open var URLSession: Foundation.URLSession 21 | open var userDataFetcher: (() -> PusherPresenceChannelMember)? 22 | open var reconnectAttemptsMax: Int? = 6 23 | open var reconnectAttempts: Int = 0 24 | open var maxReconnectGapInSeconds: Double? = nil 25 | open weak var delegate: PusherDelegate? 26 | internal var reconnectTimer: Timer? = nil 27 | 28 | open var socketConnected: Bool = false { 29 | didSet { 30 | updateConnectionStateAndAttemptSubscriptions() 31 | } 32 | } 33 | open var connectionEstablishedMessageReceived: Bool = false { 34 | didSet { 35 | updateConnectionStateAndAttemptSubscriptions() 36 | } 37 | } 38 | 39 | open lazy var reachability: Reachability? = { 40 | let reachability = Reachability.init() 41 | reachability?.whenReachable = { [weak self] reachability in 42 | guard self != nil else { 43 | print("Your Pusher instance has probably become deallocated. See https://github.com/pusher/pusher-websocket-swift/issues/109 for more information") 44 | return 45 | } 46 | 47 | self!.delegate?.debugLog?(message: "[PUSHER DEBUG] Network reachable") 48 | if self!.connectionState == .disconnected || self!.connectionState == .reconnectingWhenNetworkBecomesReachable { 49 | self!.attemptReconnect() 50 | } 51 | } 52 | reachability?.whenUnreachable = { [weak self] reachability in 53 | guard self != nil else { 54 | print("Your Pusher instance has probably become deallocated. See https://github.com/pusher/pusher-websocket-swift/issues/109 for more information") 55 | return 56 | } 57 | 58 | self!.delegate?.debugLog?(message: "[PUSHER DEBUG] Network unreachable") 59 | } 60 | return reachability 61 | }() 62 | 63 | /** 64 | Initializes a new PusherConnection with an app key, websocket, URL, options and URLSession 65 | 66 | - parameter key: The Pusher app key 67 | - parameter socket: The websocket object 68 | - parameter url: The URL the connection is made to 69 | - parameter options: A PusherClientOptions instance containing all of the user-speficied 70 | client options 71 | - parameter URLSession: An NSURLSession instance for the connection to use for making 72 | authentication requests 73 | 74 | - returns: A new PusherConnection instance 75 | */ 76 | public init( 77 | key: String, 78 | socket: WebSocket, 79 | url: String, 80 | options: PusherClientOptions, 81 | URLSession: Foundation.URLSession = Foundation.URLSession.shared) { 82 | self.url = url 83 | self.key = key 84 | self.options = options 85 | self.URLSession = URLSession 86 | self.socket = socket 87 | super.init() 88 | self.socket.delegate = self 89 | } 90 | 91 | /** 92 | Initializes a new PusherChannel with a given name 93 | 94 | - parameter channelName: The name of the channel 95 | - parameter auth: A PusherAuth value if subscription is being made to an 96 | authenticated channel without using the default auth methods 97 | - parameter onMemberAdded: A function that will be called with information about the 98 | member who has just joined the presence channel 99 | - parameter onMemberRemoved: A function that will be called with information about the 100 | member who has just left the presence channel 101 | 102 | - returns: A new PusherChannel instance 103 | */ 104 | internal func subscribe( 105 | channelName: String, 106 | auth: PusherAuth? = nil, 107 | onMemberAdded: ((PusherPresenceChannelMember) -> ())? = nil, 108 | onMemberRemoved: ((PusherPresenceChannelMember) -> ())? = nil) -> PusherChannel { 109 | let newChannel = channels.add( 110 | name: channelName, 111 | connection: self, 112 | auth: auth, 113 | onMemberAdded: onMemberAdded, 114 | onMemberRemoved: onMemberRemoved 115 | ) 116 | 117 | guard self.connectionState == .connected else { return newChannel } 118 | 119 | if !self.authorize(newChannel, auth: auth) { 120 | print("Unable to subscribe to channel: \(newChannel.name)") 121 | } 122 | 123 | return newChannel 124 | } 125 | 126 | /** 127 | Initializes a new PusherChannel with a given name 128 | 129 | - parameter channelName: The name of the channel 130 | - parameter auth: A PusherAuth value if subscription is being made to an 131 | authenticated channel without using the default auth methods 132 | - parameter onMemberAdded: A function that will be called with information about the 133 | member who has just joined the presence channel 134 | - parameter onMemberRemoved: A function that will be called with information about the 135 | member who has just left the presence channel 136 | 137 | - returns: A new PusherChannel instance 138 | */ 139 | internal func subscribeToPresenceChannel( 140 | channelName: String, 141 | auth: PusherAuth? = nil, 142 | onMemberAdded: ((PusherPresenceChannelMember) -> ())? = nil, 143 | onMemberRemoved: ((PusherPresenceChannelMember) -> ())? = nil) -> PusherPresenceChannel { 144 | let newChannel = channels.addPresence( 145 | channelName: channelName, 146 | connection: self, 147 | auth: auth, 148 | onMemberAdded: onMemberAdded, 149 | onMemberRemoved: onMemberRemoved 150 | ) 151 | 152 | guard self.connectionState == .connected else { return newChannel } 153 | 154 | if !self.authorize(newChannel, auth: auth) { 155 | print("Unable to subscribe to channel: \(newChannel.name)") 156 | } 157 | 158 | return newChannel 159 | } 160 | 161 | /** 162 | Unsubscribes from a PusherChannel with a given name 163 | 164 | - parameter channelName: The name of the channel 165 | */ 166 | internal func unsubscribe(channelName: String) { 167 | if let chan = self.channels.find(name: channelName), chan.subscribed { 168 | self.sendEvent(event: "pusher:unsubscribe", 169 | data: [ 170 | "channel": channelName 171 | ] as [String : Any] 172 | ) 173 | self.channels.remove(name: channelName) 174 | } 175 | } 176 | 177 | /** 178 | Either writes a string directly to the websocket with the given event name 179 | and data, or calls a client event to be sent if the event is prefixed with 180 | "client" 181 | 182 | - parameter event: The name of the event 183 | - parameter data: The data to be stringified and sent 184 | - parameter channelName: The name of the channel 185 | */ 186 | open func sendEvent(event: String, data: Any, channel: PusherChannel? = nil) { 187 | if event.components(separatedBy: "-")[0] == "client" { 188 | sendClientEvent(event: event, data: data, channel: channel) 189 | } else { 190 | let dataString = JSONStringify(["event": event, "data": data]) 191 | self.delegate?.debugLog?(message: "[PUSHER DEBUG] sendEvent \(dataString)") 192 | self.socket.write(string: dataString) 193 | } 194 | } 195 | 196 | /** 197 | Sends a client event with the given event, data, and channel name 198 | 199 | - parameter event: The name of the event 200 | - parameter data: The data to be stringified and sent 201 | - parameter channelName: The name of the channel 202 | */ 203 | fileprivate func sendClientEvent(event: String, data: Any, channel: PusherChannel?) { 204 | if let channel = channel { 205 | if channel.type == .presence || channel.type == .private { 206 | let dataString = JSONStringify(["event": event, "data": data, "channel": channel.name] as [String : Any]) 207 | self.delegate?.debugLog?(message: "[PUSHER DEBUG] sendClientEvent \(dataString)") 208 | self.socket.write(string: dataString) 209 | } else { 210 | print("You must be subscribed to a private or presence channel to send client events") 211 | } 212 | } 213 | } 214 | 215 | /** 216 | JSON stringifies an object 217 | 218 | - parameter value: The value to be JSON stringified 219 | 220 | - returns: A JSON-stringified version of the value 221 | */ 222 | fileprivate func JSONStringify(_ value: Any) -> String { 223 | if JSONSerialization.isValidJSONObject(value) { 224 | do { 225 | let data = try JSONSerialization.data(withJSONObject: value, options: []) 226 | let string = String(data: data, encoding: .utf8) 227 | if string != nil { 228 | return string! 229 | } 230 | } catch _ { 231 | } 232 | } 233 | return "" 234 | } 235 | 236 | /** 237 | Disconnects the websocket 238 | */ 239 | open func disconnect() { 240 | if self.connectionState == .connected { 241 | self.reachability?.stopNotifier() 242 | updateConnectionState(to: .disconnecting) 243 | self.socket.disconnect() 244 | } 245 | } 246 | 247 | /** 248 | Establish a websocket connection 249 | */ 250 | @objc open func connect() { 251 | if self.connectionState == .connected { 252 | return 253 | } else { 254 | updateConnectionState(to: .connecting) 255 | self.socket.connect() 256 | if self.options.autoReconnect { 257 | // can call this multiple times and only one notifier will be started 258 | _ = try? reachability?.startNotifier() 259 | } 260 | } 261 | } 262 | 263 | /** 264 | Instantiate a new GloblalChannel instance for the connection 265 | */ 266 | internal func createGlobalChannel() { 267 | self.globalChannel = GlobalChannel(connection: self) 268 | } 269 | 270 | /** 271 | Add callback to the connection's global channel 272 | 273 | - parameter callback: The callback to be stored 274 | 275 | - returns: A callbackId that can be used to remove the callback from the connection 276 | */ 277 | internal func addCallbackToGlobalChannel(_ callback: @escaping (Any?) -> Void) -> String { 278 | return globalChannel.bind(callback) 279 | } 280 | 281 | /** 282 | Remove the callback with id of callbackId from the connection's global channel 283 | 284 | - parameter callbackId: The unique string representing the callback to be removed 285 | */ 286 | internal func removeCallbackFromGlobalChannel(callbackId: String) { 287 | globalChannel.unbind(callbackId: callbackId) 288 | } 289 | 290 | /** 291 | Remove all callbacks from the connection's global channel 292 | */ 293 | internal func removeAllCallbacksFromGlobalChannel() { 294 | globalChannel.unbindAll() 295 | } 296 | 297 | /** 298 | Set the connection state and call the stateChangeDelegate, if set 299 | 300 | - parameter newState: The new ConnectionState value 301 | */ 302 | internal func updateConnectionState(to newState: ConnectionState) { 303 | let oldState = self.connectionState 304 | self.connectionState = newState 305 | self.delegate?.changedConnectionState?(from: oldState, to: newState) 306 | } 307 | 308 | /** 309 | Update connection state and attempt subscriptions to unsubscribed channels 310 | */ 311 | fileprivate func updateConnectionStateAndAttemptSubscriptions() { 312 | if self.connectionEstablishedMessageReceived && self.socketConnected && self.connectionState != .connected { 313 | updateConnectionState(to: .connected) 314 | attemptSubscriptionsToUnsubscribedChannels() 315 | } 316 | } 317 | 318 | /** 319 | Handle setting channel state and triggering unsent client events, if applicable, 320 | upon receiving a successful subscription event 321 | 322 | - parameter json: The PusherEventJSON containing successful subscription data 323 | */ 324 | fileprivate func handleSubscriptionSucceededEvent(json: PusherEventJSON) { 325 | if let channelName = json["channel"] as? String, let chan = self.channels.find(name: channelName) { 326 | chan.subscribed = true 327 | 328 | guard let eventData = json["data"] as? String else { 329 | self.delegate?.debugLog?(message: "Subscription succeeded event received without data key in payload") 330 | return 331 | } 332 | 333 | if PusherChannelType.isPresenceChannel(name: channelName) { 334 | if let presChan = self.channels.find(name: channelName) as? PusherPresenceChannel { 335 | if let dataJSON = getPusherEventJSON(from: eventData) { 336 | if let presenceData = dataJSON["presence"] as? [String : AnyObject], 337 | let presenceHash = presenceData["hash"] as? [String : AnyObject] 338 | { 339 | presChan.addExistingMembers(memberHash: presenceHash) 340 | } 341 | } 342 | } 343 | } 344 | 345 | callGlobalCallbacks(forEvent: "pusher:subscription_succeeded", jsonObject: json) 346 | chan.handleEvent(name: "pusher:subscription_succeeded", data: eventData) 347 | 348 | self.delegate?.subscribedToChannel?(name: channelName) 349 | 350 | chan.auth = nil 351 | 352 | while chan.unsentEvents.count > 0 { 353 | if let pusherEvent = chan.unsentEvents.popLast() { 354 | chan.trigger(eventName: pusherEvent.name, data: pusherEvent.data) 355 | } 356 | } 357 | } 358 | } 359 | 360 | /** 361 | Handle setting connection state and making subscriptions that couldn't be 362 | attempted while the connection was not in a connected state 363 | 364 | - parameter json: The PusherEventJSON containing connection established data 365 | */ 366 | fileprivate func handleConnectionEstablishedEvent(json: PusherEventJSON) { 367 | if let data = json["data"] as? String { 368 | if let connectionData = getPusherEventJSON(from: data), let socketId = connectionData["socket_id"] as? String { 369 | self.socketId = socketId 370 | self.reconnectAttempts = 0 371 | self.reconnectTimer?.invalidate() 372 | 373 | self.connectionEstablishedMessageReceived = true 374 | } 375 | } 376 | } 377 | 378 | /** 379 | Attempts to make subscriptions that couldn't be attempted while the 380 | connection was not in a connected state 381 | */ 382 | fileprivate func attemptSubscriptionsToUnsubscribedChannels() { 383 | for (_, channel) in self.channels.channels { 384 | if !channel.subscribed { 385 | if !self.authorize(channel, auth: channel.auth) { 386 | print("Unable to subscribe to channel: \(channel.name)") 387 | } 388 | } 389 | } 390 | } 391 | 392 | /** 393 | Handle a new member subscribing to a presence channel 394 | 395 | - parameter json: The PusherEventJSON containing the member data 396 | */ 397 | fileprivate func handleMemberAddedEvent(json: PusherEventJSON) { 398 | if let data = json["data"] as? String { 399 | if let channelName = json["channel"] as? String, let chan = self.channels.find(name: channelName) as? PusherPresenceChannel { 400 | if let memberJSON = getPusherEventJSON(from: data) { 401 | chan.addMember(memberJSON: memberJSON) 402 | } else { 403 | print("Unable to add member") 404 | } 405 | } 406 | } 407 | } 408 | 409 | /** 410 | Handle a member unsubscribing from a presence channel 411 | 412 | - parameter json: The PusherEventJSON containing the member data 413 | */ 414 | fileprivate func handleMemberRemovedEvent(json: PusherEventJSON) { 415 | if let data = json["data"] as? String { 416 | if let channelName = json["channel"] as? String, let chan = self.channels.find(name: channelName) as? PusherPresenceChannel { 417 | if let memberJSON = getPusherEventJSON(from: data) { 418 | chan.removeMember(memberJSON: memberJSON) 419 | } else { 420 | print("Unable to remove member") 421 | } 422 | } 423 | } 424 | } 425 | 426 | /** 427 | Handle failure of our auth endpoint 428 | 429 | - parameter channelName: The name of channel for which authorization failed 430 | - parameter data: The error returned by the auth endpoint 431 | */ 432 | fileprivate func handleAuthorizationError(forChannel channelName: String, response: URLResponse?, data: String?, error: NSError?) { 433 | let eventName = "pusher:subscription_error" 434 | let json = [ 435 | "event": eventName, 436 | "channel": channelName, 437 | "data": data ?? "" 438 | ] 439 | DispatchQueue.main.async { 440 | // TODO: Consider removing in favour of exclusively using delegate 441 | self.handleEvent(eventName: eventName, jsonObject: json as [String : AnyObject]) 442 | } 443 | 444 | self.delegate?.failedToSubscribeToChannel?(name: channelName, response: response, data: data, error: error) 445 | } 446 | 447 | /** 448 | Parse a string to extract Pusher event information from it 449 | 450 | - parameter string: The string received over the websocket connection containing 451 | Pusher event information 452 | 453 | - returns: A dictionary of Pusher-relevant event data 454 | */ 455 | open func getPusherEventJSON(from string: String) -> [String : AnyObject]? { 456 | let data = (string as NSString).data(using: String.Encoding.utf8.rawValue, allowLossyConversion: false) 457 | 458 | do { 459 | if let jsonData = data, let jsonObject = try JSONSerialization.jsonObject(with: jsonData, options: []) as? [String : AnyObject] { 460 | return jsonObject 461 | } else { 462 | print("Unable to parse string from WebSocket: \(string)") 463 | } 464 | } catch let error as NSError { 465 | print("Error: \(error.localizedDescription)") 466 | } 467 | return nil 468 | } 469 | 470 | /** 471 | Parse a string to extract Pusher event data from it 472 | 473 | - parameter string: The data string received as part of a Pusher message 474 | 475 | - returns: The object sent as the payload part of the Pusher message 476 | */ 477 | open func getEventDataJSON(from string: String) -> Any { 478 | let data = (string as NSString).data(using: String.Encoding.utf8.rawValue, allowLossyConversion: false) 479 | 480 | do { 481 | if let jsonData = data, let jsonObject = try? JSONSerialization.jsonObject(with: jsonData, options: []) { 482 | return jsonObject 483 | } else { 484 | print("Returning data string instead because unable to parse string as JSON - check that your JSON is valid.") 485 | } 486 | } 487 | return string 488 | } 489 | 490 | /** 491 | Handles incoming events and passes them on to be handled by the appropriate function 492 | 493 | - parameter eventName: The name of the incoming event 494 | - parameter jsonObject: The event-specific data related to the incoming event 495 | */ 496 | open func handleEvent(eventName: String, jsonObject: [String : AnyObject]) { 497 | switch eventName { 498 | case "pusher_internal:subscription_succeeded": 499 | handleSubscriptionSucceededEvent(json: jsonObject) 500 | case "pusher:connection_established": 501 | handleConnectionEstablishedEvent(json: jsonObject) 502 | case "pusher_internal:member_added": 503 | handleMemberAddedEvent(json: jsonObject) 504 | case "pusher_internal:member_removed": 505 | handleMemberRemovedEvent(json: jsonObject) 506 | default: 507 | callGlobalCallbacks(forEvent: eventName, jsonObject: jsonObject) 508 | if let channelName = jsonObject["channel"] as? String, let internalChannel = self.channels.find(name: channelName) { 509 | if let eName = jsonObject["event"] as? String, let eData = jsonObject["data"] as? String { 510 | internalChannel.handleEvent(name: eName, data: eData) 511 | } 512 | } 513 | } 514 | } 515 | 516 | /** 517 | Call any global callbacks 518 | 519 | - parameter eventName: The name of the incoming event 520 | - parameter jsonObject: The event-specific data related to the incoming event 521 | */ 522 | fileprivate func callGlobalCallbacks(forEvent eventName: String, jsonObject: [String : AnyObject]) { 523 | if let globalChannel = self.globalChannel { 524 | if let eData = jsonObject["data"] as? String { 525 | let channelName = jsonObject["channel"] as! String? 526 | globalChannel.handleEvent(name: eventName, data: eData, channelName: channelName) 527 | } else if let eData = jsonObject["data"] as? [String: AnyObject] { 528 | globalChannel.handleErrorEvent(name: eventName, data: eData) 529 | } 530 | } 531 | } 532 | 533 | /** 534 | Uses the appropriate authentication method to authenticate subscriptions to private and 535 | presence channels 536 | 537 | - parameter channel: The PusherChannel to authenticate 538 | - parameter auth: A PusherAuth value if subscription is being made to an 539 | authenticated channel without using the default auth methods 540 | 541 | - returns: A Bool indicating whether or not the authentication request was made 542 | successfully 543 | */ 544 | fileprivate func authorize(_ channel: PusherChannel, auth: PusherAuth? = nil) -> Bool { 545 | if channel.type != .presence && channel.type != .private { 546 | subscribeToNormalChannel(channel) 547 | return true 548 | } else if let auth = auth { 549 | // Don't go through normal auth flow if auth value provided 550 | if channel.type == .private { 551 | self.handlePrivateChannelAuth(authValue: auth.auth, channel: channel) 552 | } else if let channelData = auth.channelData { 553 | self.handlePresenceChannelAuth(authValue: auth.auth, channel: channel, channelData: channelData) 554 | } else { 555 | self.delegate?.debugLog?(message: "Attempting to subscribe to presence channel but no channelData value provided") 556 | return false 557 | } 558 | 559 | return true 560 | } else { 561 | guard let socketId = self.socketId else { 562 | print("socketId value not found. You may not be connected.") 563 | return false 564 | } 565 | 566 | switch self.options.authMethod { 567 | case .noMethod: 568 | let errorMessage = "Authentication method required for private / presence channels but none provided." 569 | let error = NSError(domain: "com.pusher.PusherSwift", code: 0, userInfo: [NSLocalizedFailureReasonErrorKey: errorMessage]) 570 | 571 | print(errorMessage) 572 | 573 | handleAuthorizationError(forChannel: channel.name, response: nil, data: nil, error: error) 574 | 575 | return false 576 | case .endpoint(authEndpoint: let authEndpoint): 577 | let request = requestForAuthValue(from: authEndpoint, socketId: socketId, channelName: channel.name) 578 | sendAuthorisationRequest(request: request, channel: channel) 579 | return true 580 | 581 | case .authRequestBuilder(authRequestBuilder: let builder): 582 | if let request = builder.requestFor?(socketID: socketId, channel: channel) { 583 | sendAuthorisationRequest(request: request as URLRequest, channel: channel) 584 | 585 | return true 586 | } else if let request = builder.requestFor?(socketID: socketId, channelName: channel.name) { 587 | sendAuthorisationRequest(request: request, channel: channel) 588 | 589 | return true 590 | } else { 591 | let errorMessage = "Authentication request could not be built" 592 | let error = NSError(domain: "com.pusher.PusherSwift", code: 0, userInfo: [NSLocalizedFailureReasonErrorKey: errorMessage]) 593 | 594 | handleAuthorizationError(forChannel: channel.name, response: nil, data: nil, error: error) 595 | 596 | return false 597 | } 598 | case .inline(secret: let secret): 599 | var msg = "" 600 | var channelData = "" 601 | if channel.type == .presence { 602 | channelData = getUserDataJSON() 603 | msg = "\(self.socketId!):\(channel.name):\(channelData)" 604 | } else { 605 | msg = "\(self.socketId!):\(channel.name)" 606 | } 607 | 608 | let secretBuff: [UInt8] = Array(secret.utf8) 609 | let msgBuff: [UInt8] = Array(msg.utf8) 610 | 611 | if let hmac = try? HMAC(key: secretBuff, variant: .sha256).authenticate(msgBuff) { 612 | let signature = Data(bytes: hmac).toHexString() 613 | let auth = "\(self.key):\(signature)".lowercased() 614 | 615 | if channel.type == .private { 616 | self.handlePrivateChannelAuth(authValue: auth, channel: channel) 617 | } else { 618 | self.handlePresenceChannelAuth(authValue: auth, channel: channel, channelData: channelData) 619 | } 620 | } 621 | 622 | return true 623 | } 624 | } 625 | } 626 | 627 | /** 628 | Calls the provided userDataFetcher function, if provided, otherwise will 629 | use the socketId as the user_id and return that stringified 630 | 631 | - returns: A JSON stringified user data object 632 | */ 633 | fileprivate func getUserDataJSON() -> String { 634 | if let userDataFetcher = self.userDataFetcher { 635 | let userData = userDataFetcher() 636 | if let userInfo: Any = userData.userInfo { 637 | return JSONStringify(["user_id": userData.userId, "user_info": userInfo]) 638 | } else { 639 | return JSONStringify(["user_id": userData.userId]) 640 | } 641 | } else { 642 | if let socketId = self.socketId { 643 | return JSONStringify(["user_id": socketId]) 644 | } else { 645 | print("Authentication failed. You may not be connected") 646 | return "" 647 | } 648 | } 649 | } 650 | 651 | /** 652 | Send subscription event for subscribing to a public channel 653 | 654 | - parameter channel: The PusherChannel to subscribe to 655 | */ 656 | fileprivate func subscribeToNormalChannel(_ channel: PusherChannel) { 657 | self.sendEvent( 658 | event: "pusher:subscribe", 659 | data: [ 660 | "channel": channel.name 661 | ] 662 | ) 663 | } 664 | 665 | /** 666 | Creates an authentication request for the given authEndpoint 667 | 668 | - parameter endpoint: The authEndpoint to which the request will be made 669 | - parameter socketId: The socketId of the connection's websocket 670 | - parameter channel: The PusherChannel to authenticate subsciption for 671 | 672 | - returns: URLRequest object to be used by the function making the auth request 673 | */ 674 | fileprivate func requestForAuthValue(from endpoint: String, socketId: String, channelName: String) -> URLRequest { 675 | let allowedCharacterSet = CharacterSet(charactersIn: "!*'();:@&=+$,/?%#[] ").inverted 676 | let encodedChannelName = channelName.addingPercentEncoding(withAllowedCharacters: allowedCharacterSet) ?? channelName 677 | 678 | var request = URLRequest(url: URL(string: endpoint)!) 679 | request.httpMethod = "POST" 680 | request.httpBody = "socket_id=\(socketId)&channel_name=\(encodedChannelName)".data(using: String.Encoding.utf8) 681 | 682 | return request 683 | } 684 | 685 | /** 686 | Send authentication request to the authEndpoint specified 687 | 688 | - parameter request: The request to send 689 | - parameter channel: The PusherChannel to authenticate subsciption for 690 | */ 691 | fileprivate func sendAuthorisationRequest(request: URLRequest, channel: PusherChannel) { 692 | let task = URLSession.dataTask(with: request, completionHandler: { data, response, sessionError in 693 | if let error = sessionError { 694 | print("Error authorizing channel [\(channel.name)]: \(error)") 695 | self.handleAuthorizationError(forChannel: channel.name, response: response, data: nil, error: error as NSError?) 696 | return 697 | } 698 | 699 | guard let data = data else { 700 | print("Error authorizing channel [\(channel.name)]") 701 | self.handleAuthorizationError(forChannel: channel.name, response: response, data: nil, error: nil) 702 | return 703 | } 704 | 705 | guard let httpResponse = response as? HTTPURLResponse, (httpResponse.statusCode == 200 || httpResponse.statusCode == 201) else { 706 | let dataString = String(data: data, encoding: String.Encoding.utf8) 707 | print ("Error authorizing channel [\(channel.name)]: \(String(describing: dataString))") 708 | self.handleAuthorizationError(forChannel: channel.name, response: response, data: dataString, error: nil) 709 | return 710 | } 711 | 712 | guard let jsonObject = try? JSONSerialization.jsonObject(with: data, options: []), let json = jsonObject as? [String: AnyObject] else { 713 | print("Error authorizing channel [\(channel.name)]") 714 | self.handleAuthorizationError(forChannel: channel.name, response: httpResponse, data: nil, error: nil) 715 | return 716 | } 717 | 718 | self.handleAuthResponse(json: json, channel: channel) 719 | }) 720 | 721 | task.resume() 722 | } 723 | 724 | /** 725 | Handle authentication request response and call appropriate handle function 726 | 727 | - parameter json: The auth response as a dictionary 728 | - parameter channel: The PusherChannel to authenticate subsciption for 729 | */ 730 | fileprivate func handleAuthResponse( 731 | json: [String : AnyObject], 732 | channel: PusherChannel) { 733 | if let auth = json["auth"] as? String { 734 | if let channelData = json["channel_data"] as? String { 735 | handlePresenceChannelAuth(authValue: auth, channel: channel, channelData: channelData) 736 | } else { 737 | handlePrivateChannelAuth(authValue: auth, channel: channel) 738 | } 739 | } 740 | } 741 | 742 | /** 743 | Handle presence channel auth response and send subscribe message to Pusher API 744 | 745 | - parameter auth: The auth string 746 | - parameter channel: The PusherChannel to authenticate subsciption for 747 | - parameter channelData: The channelData to send along with the auth request 748 | */ 749 | fileprivate func handlePresenceChannelAuth( 750 | authValue: String, 751 | channel: PusherChannel, 752 | channelData: String) { 753 | (channel as? PusherPresenceChannel)?.setMyUserId(channelData: channelData) 754 | 755 | self.sendEvent( 756 | event: "pusher:subscribe", 757 | data: [ 758 | "channel": channel.name, 759 | "auth": authValue, 760 | "channel_data": channelData 761 | ] 762 | ) 763 | } 764 | 765 | /** 766 | Handle private channel auth response and send subscribe message to Pusher API 767 | 768 | - parameter auth: The auth string 769 | - parameter channel: The PusherChannel to authenticate subsciption for 770 | */ 771 | fileprivate func handlePrivateChannelAuth(authValue auth: String, channel: PusherChannel) { 772 | self.sendEvent( 773 | event: "pusher:subscribe", 774 | data: [ 775 | "channel": channel.name, 776 | "auth": auth 777 | ] 778 | ) 779 | } 780 | } 781 | 782 | @objc public class PusherAuth: NSObject { 783 | public let auth: String 784 | public let channelData: String? 785 | 786 | public init(auth: String, channelData: String? = nil) { 787 | self.auth = auth 788 | self.channelData = channelData 789 | } 790 | } 791 | 792 | @objc public enum ConnectionState: Int { 793 | case connecting 794 | case connected 795 | case disconnecting 796 | case disconnected 797 | case reconnecting 798 | case reconnectingWhenNetworkBecomesReachable 799 | 800 | static let connectionStates = [ 801 | connecting: "connecting", 802 | connected: "connected", 803 | disconnecting: "disconnecting", 804 | disconnected: "disconnected", 805 | reconnecting: "reconnecting", 806 | reconnectingWhenNetworkBecomesReachable: "reconnreconnectingWhenNetworkBecomesReachable", 807 | ] 808 | 809 | public func stringValue() -> String { 810 | return ConnectionState.connectionStates[self]! 811 | } 812 | } 813 | -------------------------------------------------------------------------------- /Pods/PusherSwift/Source/PusherDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PusherDelegate.swift 3 | // PusherSwift 4 | // 5 | // Created by Hamilton Chapman on 19/09/2016. 6 | // 7 | // 8 | 9 | @objc public protocol PusherDelegate: class { 10 | @objc optional func debugLog(message: String) 11 | 12 | @objc optional func registeredForPushNotifications(clientId: String) 13 | @objc optional func failedToRegisterForPushNotifications(response: URLResponse, responseBody: String?) 14 | @objc optional func subscribedToInterest(name: String) 15 | @objc optional func unsubscribedFromInterest(name: String) 16 | 17 | @objc optional func changedConnectionState(from old: ConnectionState, to new: ConnectionState) 18 | @objc optional func subscribedToChannel(name: String) 19 | @objc optional func failedToSubscribeToChannel(name: String, response: URLResponse?, data: String?, error: NSError?) 20 | } 21 | -------------------------------------------------------------------------------- /Pods/PusherSwift/Source/PusherGlobalChannel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PusherGlobalChannel.swift 3 | // PusherSwift 4 | // 5 | // Created by Hamilton Chapman on 01/04/2016. 6 | // 7 | // 8 | 9 | open class GlobalChannel: PusherChannel { 10 | open var globalCallbacks: [String : (Any?) -> Void] = [:] 11 | 12 | /** 13 | Initializes a new GlobalChannel instance 14 | 15 | - parameter connection: The connection associated with the global channel 16 | 17 | - returns: A new GlobalChannel instance 18 | */ 19 | init(connection: PusherConnection) { 20 | super.init(name: "pusher_global_internal_channel", connection: connection) 21 | } 22 | 23 | /** 24 | Calls the appropriate callbacks for the given event name in the scope of the global channel 25 | 26 | - parameter name: The name of the received event 27 | - parameter data: The data associated with the received message 28 | - parameter channelName: The name of the channel that the received message was triggered 29 | to, if relevant 30 | */ 31 | internal func handleEvent(name: String, data: String, channelName: String?) { 32 | for (_, callback) in self.globalCallbacks { 33 | if let channelName = channelName { 34 | callback(["channel": channelName, "event": name, "data": data] as [String: Any]) 35 | } else { 36 | callback(["event": name, "data": data] as [String: Any]) 37 | } 38 | } 39 | } 40 | 41 | /** 42 | Calls the appropriate callbacks for the given event name in the scope of the global channel 43 | 44 | - parameter name: The name of the received event 45 | - parameter data: The data associated with the received message 46 | */ 47 | internal func handleErrorEvent(name: String, data: [String: AnyObject]) { 48 | for (_, callback) in self.globalCallbacks { 49 | callback(["event": name, "data": data]) 50 | } 51 | } 52 | 53 | /** 54 | Binds a callback to the global channel 55 | 56 | - parameter callback: The function to call when a message is received 57 | 58 | - returns: A unique callbackId that can be used to unbind the callback at a later time 59 | */ 60 | internal func bind(_ callback: @escaping (Any?) -> Void) -> String { 61 | let randomId = UUID().uuidString 62 | self.globalCallbacks[randomId] = callback 63 | return randomId 64 | } 65 | 66 | /** 67 | Unbinds the callback with the given callbackId from the global channel 68 | 69 | - parameter callbackId: The unique callbackId string used to identify which callback to unbind 70 | */ 71 | internal func unbind(callbackId: String) { 72 | globalCallbacks.removeValue(forKey: callbackId) 73 | } 74 | 75 | /** 76 | Unbinds all callbacks from the channel 77 | */ 78 | override open func unbindAll() { 79 | globalCallbacks = [:] 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /Pods/PusherSwift/Source/PusherPresenceChannel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PusherPresenceChannel.swift 3 | // PusherSwift 4 | // 5 | // Created by Hamilton Chapman on 01/04/2016. 6 | // 7 | // 8 | 9 | public typealias PusherUserInfoObject = [String : AnyObject] 10 | 11 | open class PusherPresenceChannel: PusherChannel { 12 | open var members: [PusherPresenceChannelMember] 13 | open var onMemberAdded: ((PusherPresenceChannelMember) -> ())? 14 | open var onMemberRemoved: ((PusherPresenceChannelMember) -> ())? 15 | open var myId: String? = nil 16 | 17 | /** 18 | Initializes a new PusherPresenceChannel with a given name, conenction, and optional 19 | member added and member removed handler functions 20 | 21 | - parameter name: The name of the channel 22 | - parameter connection: The connection that this channel is relevant to 23 | - parameter auth: A PusherAuth value if subscription is being made to an 24 | authenticated channel without using the default auth methods 25 | - parameter onMemberAdded: A function that will be called with information about the 26 | member who has just joined the presence channel 27 | - parameter onMemberRemoved: A function that will be called with information about the 28 | member who has just left the presence channel 29 | 30 | - returns: A new PusherPresenceChannel instance 31 | */ 32 | init( 33 | name: String, 34 | connection: PusherConnection, 35 | auth: PusherAuth? = nil, 36 | onMemberAdded: ((PusherPresenceChannelMember) -> ())? = nil, 37 | onMemberRemoved: ((PusherPresenceChannelMember) -> ())? = nil) { 38 | self.members = [] 39 | self.onMemberAdded = onMemberAdded 40 | self.onMemberRemoved = onMemberRemoved 41 | super.init(name: name, connection: connection, auth: auth) 42 | } 43 | 44 | /** 45 | Add information about the member that has just joined to the members object 46 | for the presence channel and call onMemberAdded function, if provided 47 | 48 | - parameter memberJSON: A dictionary representing the member that has joined 49 | the presence channel 50 | */ 51 | internal func addMember(memberJSON: [String : AnyObject]) { 52 | let member: PusherPresenceChannelMember 53 | 54 | if let userId = memberJSON["user_id"] as? String { 55 | if let userInfo = memberJSON["user_info"] as? PusherUserInfoObject { 56 | member = PusherPresenceChannelMember(userId: userId, userInfo: userInfo as AnyObject?) 57 | 58 | } else { 59 | member = PusherPresenceChannelMember(userId: userId) 60 | } 61 | } else { 62 | if let userInfo = memberJSON["user_info"] as? PusherUserInfoObject { 63 | member = PusherPresenceChannelMember(userId: String.init(describing: memberJSON["user_id"]!), userInfo: userInfo as AnyObject?) 64 | } else { 65 | member = PusherPresenceChannelMember(userId: String.init(describing: memberJSON["user_id"]!)) 66 | } 67 | } 68 | members.append(member) 69 | self.onMemberAdded?(member) 70 | } 71 | 72 | /** 73 | Add information about the members that are already subscribed to the presence channel to 74 | the members object of the presence channel 75 | 76 | - parameter memberHash: A dictionary representing the members that were already 77 | subscribed to the presence channel 78 | */ 79 | internal func addExistingMembers(memberHash: [String : AnyObject]) { 80 | for (userId, userInfo) in memberHash { 81 | let member: PusherPresenceChannelMember 82 | if let userInfo = userInfo as? PusherUserInfoObject { 83 | member = PusherPresenceChannelMember(userId: userId, userInfo: userInfo as AnyObject?) 84 | } else { 85 | member = PusherPresenceChannelMember(userId: userId) 86 | } 87 | self.members.append(member) 88 | } 89 | } 90 | 91 | /** 92 | Remove information about the member that has just left from the members object 93 | for the presence channel and call onMemberRemoved function, if provided 94 | 95 | - parameter memberJSON: A dictionary representing the member that has left the 96 | presence channel 97 | */ 98 | internal func removeMember(memberJSON: [String : AnyObject]) { 99 | let id: String 100 | 101 | if let userId = memberJSON["user_id"] as? String { 102 | id = userId 103 | } else { 104 | id = String.init(describing: memberJSON["user_id"]!) 105 | } 106 | 107 | if let index = self.members.index(where: { $0.userId == id }) { 108 | let member = self.members[index] 109 | self.members.remove(at: index) 110 | self.onMemberRemoved?(member) 111 | } 112 | } 113 | 114 | /** 115 | Set the value of myId to the value of the user_id returned as part of the authorization 116 | of the subscription to the channel 117 | 118 | - parameter channelData: The channel data obtained from authorization of the subscription 119 | to the channel 120 | */ 121 | internal func setMyUserId(channelData: String) { 122 | if let channelDataObject = parse(channelData: channelData), let userId = channelDataObject["user_id"] { 123 | self.myId = String.init(describing: userId) 124 | } 125 | } 126 | 127 | /** 128 | Parse a string to extract the channel data object from it 129 | 130 | - parameter channelData: The channel data string received as part of authorization 131 | 132 | - returns: A dictionary of channel data 133 | */ 134 | fileprivate func parse(channelData: String) -> [String: AnyObject]? { 135 | let data = (channelData as NSString).data(using: String.Encoding.utf8.rawValue, allowLossyConversion: false) 136 | 137 | do { 138 | if let jsonData = data, let jsonObject = try JSONSerialization.jsonObject(with: jsonData, options: []) as? [String: AnyObject] { 139 | return jsonObject 140 | } else { 141 | print("Unable to parse string: \(channelData)") 142 | } 143 | } catch let error as NSError { 144 | print(error.localizedDescription) 145 | } 146 | return nil 147 | } 148 | 149 | 150 | /** 151 | Returns the PusherPresenceChannelMember object for the given user id 152 | 153 | - parameter userId: The user id of the PusherPresenceChannelMember for whom you want 154 | the PusherPresenceChannelMember object 155 | 156 | - returns: The PusherPresenceChannelMember object for the given user id 157 | */ 158 | open func findMember(userId: String) -> PusherPresenceChannelMember? { 159 | return self.members.filter({ $0.userId == userId }).first 160 | } 161 | 162 | /** 163 | Returns the connected user's PusherPresenceChannelMember object 164 | 165 | - returns: The connected user's PusherPresenceChannelMember object 166 | */ 167 | open func me() -> PusherPresenceChannelMember? { 168 | if let id = self.myId { 169 | return findMember(userId: id) 170 | } else { 171 | return nil 172 | } 173 | } 174 | } 175 | 176 | public class PusherPresenceChannelMember: NSObject { 177 | public let userId: String 178 | public let userInfo: Any? 179 | 180 | public init(userId: String, userInfo: Any? = nil) { 181 | self.userId = userId 182 | self.userInfo = userInfo 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /Pods/PusherSwift/Source/PusherSwift.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PusherSwift.swift 3 | // 4 | // Created by Hamilton Chapman on 19/02/2015. 5 | // 6 | // 7 | 8 | import Foundation 9 | 10 | let PROTOCOL = 7 11 | let VERSION = "4.1.0" 12 | let CLIENT_NAME = "pusher-websocket-swift" 13 | 14 | @objc open class Pusher: NSObject { 15 | open let connection: PusherConnection 16 | open weak var delegate: PusherDelegate? = nil { 17 | willSet { 18 | self.connection.delegate = newValue 19 | #if os(iOS) || os(OSX) 20 | self.nativePusher.delegate = newValue 21 | #endif 22 | } 23 | } 24 | private let key: String 25 | 26 | #if os(iOS) || os(OSX) 27 | public let nativePusher: NativePusher 28 | 29 | /** 30 | Initializes the Pusher client with an app key and any appropriate options. 31 | 32 | - parameter key: The Pusher app key 33 | - parameter options: An optional collection of options 34 | - parameter nativePusher: A NativePusher instance for the app that the provided 35 | key belongs to 36 | 37 | - returns: A new Pusher client instance 38 | */ 39 | public init(key: String, options: PusherClientOptions = PusherClientOptions(), nativePusher: NativePusher = NativePusher()) { 40 | self.key = key 41 | let urlString = constructUrl(key: key, options: options) 42 | let ws = WebSocket(url: URL(string: urlString)!) 43 | connection = PusherConnection(key: key, socket: ws, url: urlString, options: options) 44 | connection.createGlobalChannel() 45 | self.nativePusher = nativePusher 46 | nativePusher.setPusherAppKey(pusherAppKey: key) 47 | } 48 | #endif 49 | 50 | #if os(tvOS) 51 | /** 52 | Initializes the Pusher client with an app key and any appropriate options. 53 | 54 | - parameter key: The Pusher app key 55 | - parameter options: An optional collection of options 56 | 57 | - returns: A new Pusher client instance 58 | */ 59 | public init(key: String, options: PusherClientOptions = PusherClientOptions()) { 60 | self.key = key 61 | let urlString = constructUrl(key: key, options: options) 62 | let ws = WebSocket(url: URL(string: urlString)!) 63 | connection = PusherConnection(key: key, socket: ws, url: urlString, options: options) 64 | connection.createGlobalChannel() 65 | } 66 | #endif 67 | 68 | 69 | /** 70 | Subscribes the client to a new channel 71 | 72 | - parameter channelName: The name of the channel to subscribe to 73 | - parameter auth: A PusherAuth value if subscription is being made to an 74 | authenticated channel without using the default auth methods 75 | - parameter onMemberAdded: A function that will be called with information about the 76 | member who has just joined the presence channel 77 | - parameter onMemberRemoved: A function that will be called with information about the 78 | member who has just left the presence channel 79 | 80 | - returns: A new PusherChannel instance 81 | */ 82 | open func subscribe( 83 | _ channelName: String, 84 | auth: PusherAuth? = nil, 85 | onMemberAdded: ((PusherPresenceChannelMember) -> ())? = nil, 86 | onMemberRemoved: ((PusherPresenceChannelMember) -> ())? = nil) -> PusherChannel { 87 | return self.connection.subscribe( 88 | channelName: channelName, 89 | auth: auth, 90 | onMemberAdded: onMemberAdded, 91 | onMemberRemoved: onMemberRemoved 92 | ) 93 | } 94 | 95 | /** 96 | Subscribes the client to a new presence channel. Use this instead of the subscribe 97 | function when you want a presence channel object to be returned instead of just a 98 | generic channel object (which you can then cast) 99 | 100 | - parameter channelName: The name of the channel to subscribe to 101 | - parameter auth: A PusherAuth value if subscription is being made to an 102 | authenticated channel without using the default auth methods 103 | - parameter onMemberAdded: A function that will be called with information about the 104 | member who has just joined the presence channel 105 | - parameter onMemberRemoved: A function that will be called with information about the 106 | member who has just left the presence channel 107 | 108 | - returns: A new PusherPresenceChannel instance 109 | */ 110 | open func subscribeToPresenceChannel( 111 | channelName: String, 112 | auth: PusherAuth? = nil, 113 | onMemberAdded: ((PusherPresenceChannelMember) -> ())? = nil, 114 | onMemberRemoved: ((PusherPresenceChannelMember) -> ())? = nil) -> PusherPresenceChannel { 115 | return self.connection.subscribeToPresenceChannel( 116 | channelName: channelName, 117 | auth: auth, 118 | onMemberAdded: onMemberAdded, 119 | onMemberRemoved: onMemberRemoved 120 | ) 121 | } 122 | 123 | /** 124 | Unsubscribes the client from a given channel 125 | 126 | - parameter channelName: The name of the channel to unsubscribe from 127 | */ 128 | open func unsubscribe(_ channelName: String) { 129 | self.connection.unsubscribe(channelName: channelName) 130 | } 131 | 132 | /** 133 | Binds the client's global channel to all events 134 | 135 | - parameter callback: The function to call when a new event is received 136 | 137 | - returns: A unique string that can be used to unbind the callback from the client 138 | */ 139 | @discardableResult open func bind(_ callback: @escaping (Any?) -> Void) -> String { 140 | return self.connection.addCallbackToGlobalChannel(callback) 141 | } 142 | 143 | /** 144 | Unbinds the client from its global channel 145 | 146 | - parameter callbackId: The unique callbackId string used to identify which callback to unbind 147 | */ 148 | open func unbind(callbackId: String) { 149 | self.connection.removeCallbackFromGlobalChannel(callbackId: callbackId) 150 | } 151 | 152 | /** 153 | Unbinds the client from all global callbacks 154 | */ 155 | open func unbindAll() { 156 | self.connection.removeAllCallbacksFromGlobalChannel() 157 | } 158 | 159 | /** 160 | Disconnects the client's connection 161 | */ 162 | open func disconnect() { 163 | self.connection.disconnect() 164 | } 165 | 166 | /** 167 | Initiates a connection attempt using the client's existing connection details 168 | */ 169 | open func connect() { 170 | self.connection.connect() 171 | } 172 | } 173 | 174 | /** 175 | Creates a valid URL that can be used in a connection attempt 176 | 177 | - parameter key: The app key to be inserted into the URL 178 | - parameter options: The collection of options needed to correctly construct the URL 179 | 180 | - returns: The constructed URL ready to use in a connection attempt 181 | */ 182 | func constructUrl(key: String, options: PusherClientOptions) -> String { 183 | var url = "" 184 | 185 | if options.encrypted { 186 | url = "wss://\(options.host):\(options.port)/app/\(key)" 187 | } else { 188 | url = "ws://\(options.host):\(options.port)/app/\(key)" 189 | } 190 | return "\(url)?client=\(CLIENT_NAME)&version=\(VERSION)&protocol=\(PROTOCOL)" 191 | } 192 | -------------------------------------------------------------------------------- /Pods/PusherSwift/Source/PusherWebsocketDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PusherWebsocketDelegate.swift 3 | // PusherSwift 4 | // 5 | // Created by Hamilton Chapman on 01/04/2016. 6 | // 7 | // 8 | 9 | extension PusherConnection: WebSocketDelegate { 10 | 11 | /** 12 | Delegate method called when a message is received over a websocket 13 | 14 | - parameter ws: The websocket that has received the message 15 | - parameter text: The message received over the websocket 16 | */ 17 | public func websocketDidReceiveMessage(socket ws: WebSocket, text: String) { 18 | self.delegate?.debugLog?(message: "[PUSHER DEBUG] websocketDidReceiveMessage \(text)") 19 | if let pusherPayloadObject = getPusherEventJSON(from: text), let eventName = pusherPayloadObject["event"] as? String { 20 | self.handleEvent(eventName: eventName, jsonObject: pusherPayloadObject) 21 | } else { 22 | print("Unable to handle incoming Websocket message \(text)") 23 | } 24 | } 25 | 26 | /** 27 | Delegate method called when a websocket disconnected 28 | 29 | - parameter ws: The websocket that disconnected 30 | - parameter error: The error, if one exists, when disconnected 31 | */ 32 | public func websocketDidDisconnect(socket ws: WebSocket, error: NSError?) { 33 | // Handles setting channel subscriptions to unsubscribed wheter disconnection 34 | // is intentional or not 35 | if connectionState == .disconnecting || connectionState == .connected { 36 | for (_, channel) in self.channels.channels { 37 | channel.subscribed = false 38 | } 39 | } 40 | 41 | self.connectionEstablishedMessageReceived = false 42 | self.socketConnected = false 43 | 44 | // Handle error (if any) 45 | guard let error = error, error.code != Int(WebSocket.CloseCode.normal.rawValue) else { 46 | self.delegate?.debugLog?(message: "[PUSHER DEBUG] Deliberate disconnection - skipping reconnect attempts") 47 | return updateConnectionState(to: .disconnected) 48 | } 49 | 50 | print("Websocket is disconnected. Error: \(error.localizedDescription)") 51 | // Attempt reconnect if possible 52 | 53 | guard self.options.autoReconnect else { 54 | return updateConnectionState(to: .disconnected) 55 | } 56 | 57 | guard reconnectAttemptsMax == nil || reconnectAttempts < reconnectAttemptsMax! else { 58 | self.delegate?.debugLog?(message: "[PUSHER DEBUG] Max reconnect attempts reached") 59 | return updateConnectionState(to: .disconnected) 60 | } 61 | 62 | guard let reachability = self.reachability, reachability.isReachable else { 63 | self.delegate?.debugLog?(message: "[PUSHER DEBUG] Network unreachable so waiting to attempt reconnect") 64 | return updateConnectionState(to: .reconnectingWhenNetworkBecomesReachable) 65 | } 66 | 67 | if connectionState != .reconnecting { 68 | updateConnectionState(to: .reconnecting) 69 | } 70 | self.delegate?.debugLog?(message: "[PUSHER DEBUG] Network reachable so will setup reconnect attempt") 71 | 72 | attemptReconnect() 73 | } 74 | 75 | /** 76 | Attempt to reconnect triggered by a disconnection 77 | */ 78 | internal func attemptReconnect() { 79 | guard connectionState != .connected else { 80 | return 81 | } 82 | 83 | guard reconnectAttemptsMax == nil || reconnectAttempts < reconnectAttemptsMax! else { 84 | return 85 | } 86 | 87 | let reconnectInterval = Double(reconnectAttempts * reconnectAttempts) 88 | 89 | let timeInterval = maxReconnectGapInSeconds != nil ? min(reconnectInterval, maxReconnectGapInSeconds!) 90 | : reconnectInterval 91 | 92 | if reconnectAttemptsMax != nil { 93 | self.delegate?.debugLog?(message: "[PUSHER DEBUG] Waiting \(timeInterval) seconds before attempting to reconnect (attempt \(reconnectAttempts + 1) of \(reconnectAttemptsMax!))") 94 | } else { 95 | self.delegate?.debugLog?(message: "[PUSHER DEBUG] Waiting \(timeInterval) seconds before attempting to reconnect (attempt \(reconnectAttempts + 1))") 96 | } 97 | 98 | reconnectTimer = Timer.scheduledTimer( 99 | timeInterval: timeInterval, 100 | target: self, 101 | selector: #selector(connect), 102 | userInfo: nil, 103 | repeats: false 104 | ) 105 | reconnectAttempts += 1 106 | } 107 | 108 | /** 109 | Delegate method called when a websocket connected 110 | 111 | - parameter ws: The websocket that connected 112 | */ 113 | public func websocketDidConnect(socket ws: WebSocket) { 114 | self.socketConnected = true 115 | } 116 | 117 | public func websocketDidReceiveData(socket ws: WebSocket, data: Data) {} 118 | } 119 | -------------------------------------------------------------------------------- /Pods/PusherSwift/Source/Reachability.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Reachability.swift 3 | // PusherSwift 4 | // 5 | // Created by Hamilton Chapman on 06/04/2016. 6 | // 7 | // 8 | 9 | /* 10 | Copyright (c) 2014, Ashley Mills 11 | All rights reserved. 12 | 13 | Redistribution and use in source and binary forms, with or without 14 | modification, are permitted provided that the following conditions are met: 15 | 16 | 1. Redistributions of source code must retain the above copyright notice, this 17 | list of conditions and the following disclaimer. 18 | 19 | 2. Redistributions in binary form must reproduce the above copyright notice, 20 | this list of conditions and the following disclaimer in the documentation 21 | and/or other materials provided with the distribution. 22 | 23 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 24 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 27 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 28 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 29 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 30 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 31 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 32 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33 | POSSIBILITY OF SUCH DAMAGE. 34 | */ 35 | 36 | // Reachability.swift version 2.2beta2 37 | 38 | import SystemConfiguration 39 | import Foundation 40 | 41 | public enum ReachabilityError: Error { 42 | case failedToCreateWithAddress(sockaddr_in) 43 | case failedToCreateWithHostname(String) 44 | case unableToSetCallback 45 | case unableToSetDispatchQueue 46 | } 47 | 48 | public let ReachabilityChangedNotification = NSNotification.Name("ReachabilityChangedNotification") 49 | 50 | func callback(reachability:SCNetworkReachability, flags: SCNetworkReachabilityFlags, info: UnsafeMutableRawPointer?) { 51 | 52 | guard let info = info else { return } 53 | 54 | let reachability = Unmanaged.fromOpaque(info).takeUnretainedValue() 55 | 56 | DispatchQueue.main.async { 57 | reachability.reachabilityChanged() 58 | } 59 | } 60 | 61 | public class Reachability { 62 | 63 | public typealias NetworkReachable = (Reachability) -> () 64 | public typealias NetworkUnreachable = (Reachability) -> () 65 | 66 | public enum NetworkStatus: CustomStringConvertible { 67 | 68 | case notReachable, reachableViaWiFi, reachableViaWWAN 69 | 70 | public var description: String { 71 | switch self { 72 | case .reachableViaWWAN: return "Cellular" 73 | case .reachableViaWiFi: return "WiFi" 74 | case .notReachable: return "No Connection" 75 | } 76 | } 77 | } 78 | 79 | public var whenReachable: NetworkReachable? 80 | public var whenUnreachable: NetworkUnreachable? 81 | public var reachableOnWWAN: Bool 82 | 83 | public var currentReachabilityString: String { 84 | return "\(currentReachabilityStatus)" 85 | } 86 | 87 | public var currentReachabilityStatus: NetworkStatus { 88 | guard isReachable else { return .notReachable } 89 | 90 | if isReachableViaWiFi { 91 | return .reachableViaWiFi 92 | } 93 | if isRunningOnDevice { 94 | return .reachableViaWWAN 95 | } 96 | 97 | return .notReachable 98 | } 99 | 100 | fileprivate var previousFlags: SCNetworkReachabilityFlags? 101 | 102 | fileprivate var isRunningOnDevice: Bool = { 103 | #if (arch(i386) || arch(x86_64)) && os(iOS) 104 | return false 105 | #else 106 | return true 107 | #endif 108 | }() 109 | 110 | fileprivate var notifierRunning = false 111 | fileprivate var reachabilityRef: SCNetworkReachability? 112 | 113 | fileprivate let reachabilitySerialQueue = DispatchQueue(label: "uk.co.ashleymills.reachability") 114 | 115 | required public init(reachabilityRef: SCNetworkReachability) { 116 | reachableOnWWAN = true 117 | self.reachabilityRef = reachabilityRef 118 | } 119 | 120 | public convenience init?(hostname: String) { 121 | 122 | guard let ref = SCNetworkReachabilityCreateWithName(nil, hostname) else { return nil } 123 | 124 | self.init(reachabilityRef: ref) 125 | } 126 | 127 | public convenience init?() { 128 | 129 | var zeroAddress = sockaddr() 130 | zeroAddress.sa_len = UInt8(MemoryLayout.size) 131 | zeroAddress.sa_family = sa_family_t(AF_INET) 132 | 133 | guard let ref: SCNetworkReachability = withUnsafePointer(to: &zeroAddress, { 134 | SCNetworkReachabilityCreateWithAddress(nil, UnsafePointer($0)) 135 | }) else { return nil } 136 | 137 | self.init(reachabilityRef: ref) 138 | } 139 | 140 | deinit { 141 | stopNotifier() 142 | 143 | reachabilityRef = nil 144 | whenReachable = nil 145 | whenUnreachable = nil 146 | } 147 | } 148 | 149 | public extension Reachability { 150 | 151 | // MARK: - *** Notifier methods *** 152 | func startNotifier() throws { 153 | 154 | guard let reachabilityRef = reachabilityRef, !notifierRunning else { return } 155 | 156 | var context = SCNetworkReachabilityContext(version: 0, info: nil, retain: nil, release: nil, copyDescription: nil) 157 | context.info = Unmanaged.passUnretained(self).toOpaque() 158 | 159 | if !SCNetworkReachabilitySetCallback(reachabilityRef, callback, &context) { 160 | stopNotifier() 161 | throw ReachabilityError.unableToSetCallback 162 | } 163 | 164 | if !SCNetworkReachabilitySetDispatchQueue(reachabilityRef, reachabilitySerialQueue) { 165 | stopNotifier() 166 | throw ReachabilityError.unableToSetDispatchQueue 167 | } 168 | 169 | // Perform an intial check 170 | reachabilitySerialQueue.async { 171 | self.reachabilityChanged() 172 | } 173 | 174 | notifierRunning = true 175 | } 176 | 177 | func stopNotifier() { 178 | defer { notifierRunning = false } 179 | guard let reachabilityRef = reachabilityRef else { return } 180 | 181 | SCNetworkReachabilitySetCallback(reachabilityRef, nil, nil) 182 | SCNetworkReachabilitySetDispatchQueue(reachabilityRef, nil) 183 | } 184 | 185 | // MARK: - *** Connection test methods *** 186 | var isReachable: Bool { 187 | 188 | guard isReachableFlagSet else { return false } 189 | 190 | if isConnectionRequiredAndTransientFlagSet { 191 | return false 192 | } 193 | 194 | if isRunningOnDevice { 195 | if isOnWWANFlagSet && !reachableOnWWAN { 196 | // We don't want to connect when on 3G. 197 | return false 198 | } 199 | } 200 | 201 | return true 202 | } 203 | 204 | var isReachableViaWWAN: Bool { 205 | // Check we're not on the simulator, we're REACHABLE and check we're on WWAN 206 | return isRunningOnDevice && isReachableFlagSet && isOnWWANFlagSet 207 | } 208 | 209 | var isReachableViaWiFi: Bool { 210 | 211 | // Check we're reachable 212 | guard isReachableFlagSet else { return false } 213 | 214 | // If reachable we're reachable, but not on an iOS device (i.e. simulator), we must be on WiFi 215 | guard isRunningOnDevice else { return true } 216 | 217 | // Check we're NOT on WWAN 218 | return !isOnWWANFlagSet 219 | } 220 | 221 | var description: String { 222 | 223 | let W = isRunningOnDevice ? (isOnWWANFlagSet ? "W" : "-") : "X" 224 | let R = isReachableFlagSet ? "R" : "-" 225 | let c = isConnectionRequiredFlagSet ? "c" : "-" 226 | let t = isTransientConnectionFlagSet ? "t" : "-" 227 | let i = isInterventionRequiredFlagSet ? "i" : "-" 228 | let C = isConnectionOnTrafficFlagSet ? "C" : "-" 229 | let D = isConnectionOnDemandFlagSet ? "D" : "-" 230 | let l = isLocalAddressFlagSet ? "l" : "-" 231 | let d = isDirectFlagSet ? "d" : "-" 232 | 233 | return "\(W)\(R) \(c)\(t)\(i)\(C)\(D)\(l)\(d)" 234 | } 235 | } 236 | 237 | fileprivate extension Reachability { 238 | 239 | func reachabilityChanged() { 240 | 241 | let flags = reachabilityFlags 242 | 243 | guard previousFlags != flags else { return } 244 | 245 | let block = isReachable ? whenReachable : whenUnreachable 246 | block?(self) 247 | 248 | NotificationCenter.default.post(name: ReachabilityChangedNotification, object:self) 249 | 250 | previousFlags = flags 251 | } 252 | 253 | var isOnWWANFlagSet: Bool { 254 | #if os(iOS) 255 | return reachabilityFlags.contains(.isWWAN) 256 | #else 257 | return false 258 | #endif 259 | } 260 | var isReachableFlagSet: Bool { 261 | return reachabilityFlags.contains(.reachable) 262 | } 263 | var isConnectionRequiredFlagSet: Bool { 264 | return reachabilityFlags.contains(.connectionRequired) 265 | } 266 | var isInterventionRequiredFlagSet: Bool { 267 | return reachabilityFlags.contains(.interventionRequired) 268 | } 269 | var isConnectionOnTrafficFlagSet: Bool { 270 | return reachabilityFlags.contains(.connectionOnTraffic) 271 | } 272 | var isConnectionOnDemandFlagSet: Bool { 273 | return reachabilityFlags.contains(.connectionOnDemand) 274 | } 275 | var isConnectionOnTrafficOrDemandFlagSet: Bool { 276 | return !reachabilityFlags.intersection([.connectionOnTraffic, .connectionOnDemand]).isEmpty 277 | } 278 | var isTransientConnectionFlagSet: Bool { 279 | return reachabilityFlags.contains(.transientConnection) 280 | } 281 | var isLocalAddressFlagSet: Bool { 282 | return reachabilityFlags.contains(.isLocalAddress) 283 | } 284 | var isDirectFlagSet: Bool { 285 | return reachabilityFlags.contains(.isDirect) 286 | } 287 | var isConnectionRequiredAndTransientFlagSet: Bool { 288 | return reachabilityFlags.intersection([.connectionRequired, .transientConnection]) == [.connectionRequired, .transientConnection] 289 | } 290 | 291 | var reachabilityFlags: SCNetworkReachabilityFlags { 292 | 293 | guard let reachabilityRef = reachabilityRef else { return SCNetworkReachabilityFlags() } 294 | 295 | var flags = SCNetworkReachabilityFlags() 296 | let gotFlags = withUnsafeMutablePointer(to: &flags) { 297 | SCNetworkReachabilityGetFlags(reachabilityRef, UnsafeMutablePointer($0)) 298 | } 299 | 300 | if gotFlags { 301 | return flags 302 | } else { 303 | return SCNetworkReachabilityFlags() 304 | } 305 | } 306 | } 307 | -------------------------------------------------------------------------------- /Pods/PusherSwift/Source/TaskQueue.swift: -------------------------------------------------------------------------------- 1 | /** 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2014 Marin Todorov 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | // 26 | // TaskQueue.swift 27 | // PusherSwift 28 | // 29 | // Created by Hamilton Chapman on 19/09/2016. 30 | // 31 | // The content is based on the TaskQueue library created by Marin Todorov, with a few 32 | // alterations made to better cater for the PusherSwift use case 33 | // 34 | 35 | internal class TaskQueue: CustomStringConvertible { 36 | public typealias ClosureNoResultNext = () -> Void 37 | public typealias ClosureWithResultNext = (Any?, @escaping (Any?) -> Void) -> Void 38 | 39 | internal var tasks = [ClosureWithResultNext]() 40 | internal lazy var completions = [ClosureNoResultNext]() 41 | 42 | fileprivate(set) var numberOfActiveTasks = 0 43 | internal var maximumNumberOfActiveTasks = 1 { 44 | willSet { 45 | assert(maximumNumberOfActiveTasks > 0, "Setting less than 1 task at a time is not allowed") 46 | } 47 | } 48 | 49 | fileprivate var currentTask: ClosureWithResultNext? = nil 50 | fileprivate(set) var lastResult: Any! = nil 51 | 52 | fileprivate(set) var running = false 53 | 54 | internal var paused: Bool = false { 55 | didSet { 56 | running = !paused 57 | } 58 | } 59 | 60 | fileprivate var cancelled = false 61 | internal func cancel() { 62 | cancelled = true 63 | } 64 | 65 | fileprivate var hasCompletions = false 66 | 67 | internal init() {} 68 | 69 | internal func run(_ completion: ClosureNoResultNext? = nil) { 70 | if completion != nil { 71 | hasCompletions = true 72 | completions += [completion!] 73 | } 74 | 75 | if paused { 76 | paused = false 77 | _runNextTask() 78 | return 79 | } 80 | 81 | if running { 82 | return 83 | } 84 | 85 | running = true 86 | _runNextTask() 87 | } 88 | 89 | fileprivate func _runNextTask(_ result: Any? = nil) { 90 | if (cancelled) { 91 | tasks.removeAll(keepingCapacity: false) 92 | completions.removeAll(keepingCapacity: false) 93 | } 94 | 95 | if (numberOfActiveTasks >= maximumNumberOfActiveTasks) { 96 | return 97 | } 98 | 99 | lastResult = result 100 | 101 | if paused { 102 | return 103 | } 104 | 105 | var task: ClosureWithResultNext? = nil 106 | 107 | //fetch one task synchronized 108 | objc_sync_enter(self) 109 | if tasks.count > 0 { 110 | task = tasks.remove(at: 0) 111 | numberOfActiveTasks += 1 112 | } 113 | objc_sync_exit(self) 114 | 115 | if task == nil { 116 | if numberOfActiveTasks == 0 { 117 | _complete() 118 | } 119 | return 120 | } 121 | 122 | currentTask = task 123 | 124 | let executeTask = { 125 | task!(self.maximumNumberOfActiveTasks > 1 ? nil: result) {nextResult in 126 | self.numberOfActiveTasks -= 1 127 | self._runNextTask(nextResult) 128 | } 129 | } 130 | 131 | if maximumNumberOfActiveTasks > 1 { 132 | //parallel queue 133 | _delay(seconds: 0.001) { 134 | self._runNextTask(nil) 135 | } 136 | _delay(seconds: 0, completion: executeTask) 137 | } else { 138 | //serial queue 139 | executeTask() 140 | } 141 | } 142 | 143 | fileprivate func _complete() { 144 | paused = false 145 | running = false 146 | 147 | if hasCompletions { 148 | //synchronized remove completions 149 | objc_sync_enter(self) 150 | while completions.count > 0 { 151 | completions.remove(at: 0)() 152 | } 153 | objc_sync_exit(self) 154 | } 155 | } 156 | 157 | internal func skip() { 158 | if tasks.count>0 { 159 | _ = tasks.remove(at: 0) 160 | } 161 | } 162 | 163 | internal func removeAll() { 164 | tasks.removeAll(keepingCapacity: false) 165 | } 166 | 167 | internal var count: Int { 168 | return tasks.count 169 | } 170 | 171 | internal func pauseAndResetCurrentTask() { 172 | paused = true 173 | 174 | tasks.insert(currentTask!, at: 0) 175 | currentTask = nil 176 | self.numberOfActiveTasks -= 1 177 | } 178 | 179 | internal func retry(_ delay: Double = 0) { 180 | assert(maximumNumberOfActiveTasks == 1, "You can only call retry() only on serial queues") 181 | 182 | tasks.insert(currentTask!, at: 0) 183 | currentTask = nil 184 | 185 | _delay(seconds: delay) { 186 | self.numberOfActiveTasks -= 1 187 | self._runNextTask(self.lastResult) 188 | } 189 | } 190 | 191 | internal var description: String { 192 | let state = running ? "runing " : (paused ? "paused ": "stopped") 193 | let type = maximumNumberOfActiveTasks == 1 ? "serial": "parallel" 194 | 195 | return "[TaskQueue] type=\(type) state=\(state) \(tasks.count) tasks" 196 | } 197 | 198 | deinit {} 199 | 200 | fileprivate func _delay(seconds: Double, completion: @escaping () -> ()) { 201 | let popTime = DispatchTime.now() + Double(Int64( Double(NSEC_PER_SEC) * seconds )) / Double(NSEC_PER_SEC) 202 | 203 | DispatchQueue.global(qos: .background).asyncAfter(deadline: popTime) { 204 | completion() 205 | } 206 | } 207 | 208 | } 209 | 210 | // 211 | // Add a task closure with result and next params 212 | // 213 | internal func += (tasks: inout [TaskQueue.ClosureWithResultNext], task: @escaping TaskQueue.ClosureWithResultNext) { 214 | tasks += [task] 215 | } 216 | 217 | // 218 | // Add a task closure that doesn't take result/next params 219 | // 220 | internal func += (tasks: inout [TaskQueue.ClosureWithResultNext], task: @escaping TaskQueue.ClosureNoResultNext) { 221 | tasks += [{ _, next in 222 | task() 223 | next(nil) 224 | }] 225 | } 226 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-Deeplinks/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-Deeplinks/Pods-Deeplinks-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | 4 | ## PusherSwift 5 | 6 | Copyright (c) 2015 Pusher Ltd. 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in 16 | all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | THE SOFTWARE. 25 | Generated by CocoaPods - https://cocoapods.org 26 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-Deeplinks/Pods-Deeplinks-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | Copyright (c) 2015 Pusher Ltd. 18 | 19 | Permission is hereby granted, free of charge, to any person obtaining a copy 20 | of this software and associated documentation files (the "Software"), to deal 21 | in the Software without restriction, including without limitation the rights 22 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 23 | copies of the Software, and to permit persons to whom the Software is 24 | furnished to do so, subject to the following conditions: 25 | 26 | The above copyright notice and this permission notice shall be included in 27 | all copies or substantial portions of the Software. 28 | 29 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 30 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 31 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 32 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 33 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 34 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 35 | THE SOFTWARE. 36 | License 37 | MIT 38 | Title 39 | PusherSwift 40 | Type 41 | PSGroupSpecifier 42 | 43 | 44 | FooterText 45 | Generated by CocoaPods - https://cocoapods.org 46 | Title 47 | 48 | Type 49 | PSGroupSpecifier 50 | 51 | 52 | StringsTable 53 | Acknowledgements 54 | Title 55 | Acknowledgements 56 | 57 | 58 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-Deeplinks/Pods-Deeplinks-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_Deeplinks : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_Deeplinks 5 | @end 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-Deeplinks/Pods-Deeplinks-frameworks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 5 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 6 | 7 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" 8 | 9 | install_framework() 10 | { 11 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then 12 | local source="${BUILT_PRODUCTS_DIR}/$1" 13 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then 14 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" 15 | elif [ -r "$1" ]; then 16 | local source="$1" 17 | fi 18 | 19 | local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 20 | 21 | if [ -L "${source}" ]; then 22 | echo "Symlinked..." 23 | source="$(readlink "${source}")" 24 | fi 25 | 26 | # use filter instead of exclude so missing patterns dont' throw errors 27 | echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" 28 | rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" 29 | 30 | local basename 31 | basename="$(basename -s .framework "$1")" 32 | binary="${destination}/${basename}.framework/${basename}" 33 | if ! [ -r "$binary" ]; then 34 | binary="${destination}/${basename}" 35 | fi 36 | 37 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 38 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then 39 | strip_invalid_archs "$binary" 40 | fi 41 | 42 | # Resign the code if required by the build settings to avoid unstable apps 43 | code_sign_if_enabled "${destination}/$(basename "$1")" 44 | 45 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. 46 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then 47 | local swift_runtime_libs 48 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) 49 | for lib in $swift_runtime_libs; do 50 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" 51 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" 52 | code_sign_if_enabled "${destination}/${lib}" 53 | done 54 | fi 55 | } 56 | 57 | # Signs a framework with the provided identity 58 | code_sign_if_enabled() { 59 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then 60 | # Use the current code_sign_identitiy 61 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" 62 | local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements '$1'" 63 | 64 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 65 | code_sign_cmd="$code_sign_cmd &" 66 | fi 67 | echo "$code_sign_cmd" 68 | eval "$code_sign_cmd" 69 | fi 70 | } 71 | 72 | # Strip invalid architectures 73 | strip_invalid_archs() { 74 | binary="$1" 75 | # Get architectures for current file 76 | archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)" 77 | stripped="" 78 | for arch in $archs; do 79 | if ! [[ "${VALID_ARCHS}" == *"$arch"* ]]; then 80 | # Strip non-valid architectures in-place 81 | lipo -remove "$arch" -output "$binary" "$binary" || exit 1 82 | stripped="$stripped $arch" 83 | fi 84 | done 85 | if [[ "$stripped" ]]; then 86 | echo "Stripped $binary of architectures:$stripped" 87 | fi 88 | } 89 | 90 | 91 | if [[ "$CONFIGURATION" == "Debug" ]]; then 92 | install_framework "$BUILT_PRODUCTS_DIR/PusherSwift/PusherSwift.framework" 93 | fi 94 | if [[ "$CONFIGURATION" == "Release" ]]; then 95 | install_framework "$BUILT_PRODUCTS_DIR/PusherSwift/PusherSwift.framework" 96 | fi 97 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 98 | wait 99 | fi 100 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-Deeplinks/Pods-Deeplinks-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 5 | 6 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt 7 | > "$RESOURCES_TO_COPY" 8 | 9 | XCASSET_FILES=() 10 | 11 | case "${TARGETED_DEVICE_FAMILY}" in 12 | 1,2) 13 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" 14 | ;; 15 | 1) 16 | TARGET_DEVICE_ARGS="--target-device iphone" 17 | ;; 18 | 2) 19 | TARGET_DEVICE_ARGS="--target-device ipad" 20 | ;; 21 | 3) 22 | TARGET_DEVICE_ARGS="--target-device tv" 23 | ;; 24 | *) 25 | TARGET_DEVICE_ARGS="--target-device mac" 26 | ;; 27 | esac 28 | 29 | install_resource() 30 | { 31 | if [[ "$1" = /* ]] ; then 32 | RESOURCE_PATH="$1" 33 | else 34 | RESOURCE_PATH="${PODS_ROOT}/$1" 35 | fi 36 | if [[ ! -e "$RESOURCE_PATH" ]] ; then 37 | cat << EOM 38 | error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. 39 | EOM 40 | exit 1 41 | fi 42 | case $RESOURCE_PATH in 43 | *.storyboard) 44 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" 45 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 46 | ;; 47 | *.xib) 48 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" 49 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 50 | ;; 51 | *.framework) 52 | echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 53 | mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 54 | echo "rsync -av $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 55 | rsync -av "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 56 | ;; 57 | *.xcdatamodel) 58 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" 59 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" 60 | ;; 61 | *.xcdatamodeld) 62 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" 63 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" 64 | ;; 65 | *.xcmappingmodel) 66 | echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" 67 | xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" 68 | ;; 69 | *.xcassets) 70 | ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH" 71 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") 72 | ;; 73 | *) 74 | echo "$RESOURCE_PATH" 75 | echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" 76 | ;; 77 | esac 78 | } 79 | 80 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 81 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 82 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then 83 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 84 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 85 | fi 86 | rm -f "$RESOURCES_TO_COPY" 87 | 88 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ] 89 | then 90 | # Find all other xcassets (this unfortunately includes those of path pods and other targets). 91 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) 92 | while read line; do 93 | if [[ $line != "${PODS_ROOT}*" ]]; then 94 | XCASSET_FILES+=("$line") 95 | fi 96 | done <<<"$OTHER_XCASSETS" 97 | 98 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 99 | fi 100 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-Deeplinks/Pods-Deeplinks-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double Pods_DeeplinksVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char Pods_DeeplinksVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-Deeplinks/Pods-Deeplinks.debug.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/PusherSwift" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 5 | OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/PusherSwift/PusherSwift.framework/Headers" 6 | OTHER_LDFLAGS = $(inherited) -framework "PusherSwift" 7 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 8 | PODS_BUILD_DIR = $BUILD_DIR 9 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_ROOT = ${SRCROOT}/Pods 11 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-Deeplinks/Pods-Deeplinks.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_Deeplinks { 2 | umbrella header "Pods-Deeplinks-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-Deeplinks/Pods-Deeplinks.release.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/PusherSwift" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 5 | OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/PusherSwift/PusherSwift.framework/Headers" 6 | OTHER_LDFLAGS = $(inherited) -framework "PusherSwift" 7 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 8 | PODS_BUILD_DIR = $BUILD_DIR 9 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_ROOT = ${SRCROOT}/Pods 11 | -------------------------------------------------------------------------------- /Pods/Target Support Files/PusherSwift/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 4.1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Pods/Target Support Files/PusherSwift/PusherSwift-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_PusherSwift : NSObject 3 | @end 4 | @implementation PodsDummy_PusherSwift 5 | @end 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/PusherSwift/PusherSwift-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /Pods/Target Support Files/PusherSwift/PusherSwift-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double PusherSwiftVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char PusherSwiftVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Pods/Target Support Files/PusherSwift/PusherSwift.modulemap: -------------------------------------------------------------------------------- 1 | framework module PusherSwift { 2 | umbrella header "PusherSwift-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Pods/Target Support Files/PusherSwift/PusherSwift.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/PusherSwift 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public" 4 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 5 | PODS_BUILD_DIR = $BUILD_DIR 6 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PODS_ROOT = ${SRCROOT} 8 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/PusherSwift 9 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 10 | SKIP_INSTALL = YES 11 | --------------------------------------------------------------------------------