diff --git a/.travis.yml b/.travis.yml index 2531497..d9ed958 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,12 +7,12 @@ branches: - master - development before_install: - - brew update + # - brew update # - brew outdated xctool || brew upgrade xctool - - brew outdated carthage || brew upgrade carthage + # - brew outdated carthage || brew upgrade carthage - carthage update --platform macosx script: - - xcodebuild -project Socket.IO-Client-Swift.xcodeproj -scheme SocketIO-Mac build test -quiet -# - xcodebuild -project Socket.IO-Client-Swift.xcodeproj -scheme SocketIO-Mac build-for-testing -quiet -# - xctool -project Socket.IO-Client-Swift.xcodeproj -scheme SocketIO-Mac run-tests --parallelize + - xcodebuild -project Socket.IO-Client-Swift.xcodeproj -scheme SocketIO build test -quiet +# - xcodebuild -project Socket.IO-Client-Swift.xcodeproj -scheme SocketIO build-for-testing -quiet +# - xctool -project Socket.IO-Client-Swift.xcodeproj -scheme SocketIO run-tests --parallelize - swift test diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..9cec509 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,20 @@ +# v13.0.0 + +Checkout out the migration guide in Usage Docs for a more detailed guide on how to migrate to this version. + +What's new: +--- + +- Adds a new `SocketManager` class that multiplexes multiple namespaces through a single engine. +- Adds `.sentPing` and `.gotPong` client events for tracking ping/pongs. +- watchOS support. + +Important API changes +--- + +- Many properties that were previously on `SocketIOClient` have been moved to the `SocketManager`. +- `SocketIOClientOption.nsp` has been removed. Use `SocketManager.socket(forNamespace:)` to create/get a socket attached to a specific namespace. +- Adds `.sentPing` and `.gotPong` client events for tracking ping/pongs. +- Makes the framework a single target. +- Updates Starscream to 3.0 + diff --git a/Cartfile b/Cartfile index 2ef3a0d..1013fa1 100644 --- a/Cartfile +++ b/Cartfile @@ -1 +1 @@ -github "daltoniam/Starscream" ~> 2.0 \ No newline at end of file +github "daltoniam/Starscream" ~> 3.0 diff --git a/Cartfile.resolved b/Cartfile.resolved index be023fb..8dff7a8 100644 --- a/Cartfile.resolved +++ b/Cartfile.resolved @@ -1 +1,3 @@ -github "daltoniam/Starscream" "2.1.1" +github "daltoniam/common-crypto-spm" "1.1.0" +github "daltoniam/zlib-spm" "1.1.0" +github "daltoniam/Starscream" "3.0.2" diff --git a/Package.resolved b/Package.resolved index e2fb1ed..2893ff4 100644 --- a/Package.resolved +++ b/Package.resolved @@ -24,8 +24,8 @@ "repositoryURL": "https://github.com/daltoniam/Starscream", "state": { "branch": null, - "revision": "21678c9426dde2a77152a0d5982cdb952baf0455", - "version": "2.1.1" + "revision": "44ce58956fae7db22fb0106cb4ce3dbef3d06d00", + "version": "3.0.2" } } ] diff --git a/Package.swift b/Package.swift index 7022dfa..3315dd4 100644 --- a/Package.swift +++ b/Package.swift @@ -8,7 +8,7 @@ let package = Package( .library(name: "SocketIO", targets: ["SocketIO"]) ], dependencies: [ - .package(url: "https://github.com/daltoniam/Starscream", .upToNextMajor(from: "2.1.1")), + .package(url: "https://github.com/daltoniam/Starscream", .upToNextMinor(from: "3.0.0")), ], targets: [ .target(name: "SocketIO", dependencies: ["Starscream"]), diff --git a/README.md b/README.md index be9e4bb..e7c7c70 100644 --- a/README.md +++ b/README.md @@ -7,20 +7,21 @@ Socket.IO-client for iOS/OS X. ```swift import SocketIO -let socket = SocketIOClient(socketURL: URL(string: "http://localhost:8080")!, config: [.log(true), .compress]) +let manager = SocketManager(socketURL: URL(string: "http://localhost:8080")!, config: [.log(true), .compress]) +let socket = manager.defaultSocket socket.on(clientEvent: .connect) {data, ack in print("socket connected") } socket.on("currentAmount") {data, ack in - if let cur = data[0] as? Double { - socket.emitWithAck("canUpdate", cur).timingOut(after: 0) {data in - socket.emit("update", ["amount": cur + 2.50]) - } - - ack.with("Got your currentAmount", "dude") + guard let cur = data[0] as? Double else { return } + + socket.emitWithAck("canUpdate", cur).timingOut(after: 0) {data in + socket.emit("update", ["amount": cur + 2.50]) } + + ack.with("Got your currentAmount", "dude") } socket.connect() @@ -29,8 +30,10 @@ socket.connect() ## Objective-C Example ```objective-c @import SocketIO; + NSURL* url = [[NSURL alloc] initWithString:@"http://localhost:8080"]; -SocketIOClient* socket = [[SocketIOClient alloc] initWithSocketURL:url config:@{@"log": @YES, @"compress": @YES}]; +SocketManager* manager = [[SocketManager alloc] initWithSocketURL:url config:@{@"log": @YES, @"compress": @YES}]; +SocketIOClient* socket = manager.defaultSocket; [socket on:@"connect" callback:^(NSArray* data, SocketAckEmitter* ack) { NSLog(@"socket connected"); @@ -60,6 +63,9 @@ SocketIOClient* socket = [[SocketIOClient alloc] initWithSocketURL:url config:@{ ## FAQS Checkout the [FAQs](https://nuclearace.github.io/Socket.IO-Client-Swift/faq.html) for commonly asked questions. +Checkout the [12to13](https://nuclearace.github.io/Socket.IO-Client-Swift/12to13.html) guide for migrating to v13. + + ## Installation Requires Swift 4/Xcode 9.x @@ -80,7 +86,7 @@ let package = Package( .executable(name: "socket.io-test", targets: ["YourTargetName"]) ], dependencies: [ - .package(url: "https://github.com/socketio/socket.io-client-swift", .upToNextMajor(from: "12.1.0")) + .package(url: "https://github.com/socketio/socket.io-client-swift", .upToNextMinor(from: "13.0.0")) ], targets: [ .target(name: "YourTargetName", dependencies: ["SocketIO"], path: "./Path/To/Your/Sources") @@ -93,7 +99,7 @@ Then import `import SocketIO`. ### Carthage Add this line to your `Cartfile`: ``` -github "socketio/socket.io-client-swift" ~> 12.1.3 # Or latest version +github "socketio/socket.io-client-swift" ~> 13.0.0 # Or latest version ``` Run `carthage update --platform ios,macosx`. @@ -107,7 +113,7 @@ Create `Podfile` and add `pod 'Socket.IO-Client-Swift'`: use_frameworks! target 'YourApp' do - pod 'Socket.IO-Client-Swift', '~> 12.1.3' # Or latest version + pod 'Socket.IO-Client-Swift', '~> 13.0.0' # Or latest version end ``` @@ -134,6 +140,7 @@ Objective-C: # [Docs](https://nuclearace.github.io/Socket.IO-Client-Swift/index.html) - [Client](https://nuclearace.github.io/Socket.IO-Client-Swift/Classes/SocketIOClient.html) +- [Manager](https://nuclearace.github.io/Socket.IO-Client-Swift/Classes/SocketManager.html) - [Engine](https://nuclearace.github.io/Socket.IO-Client-Swift/Classes/SocketEngine.html) - [Options](https://nuclearace.github.io/Socket.IO-Client-Swift/Enums/SocketIOClientOption.html) diff --git a/Socket.IO-Client-Swift.podspec b/Socket.IO-Client-Swift.podspec index 5df5bf7..158931a 100644 --- a/Socket.IO-Client-Swift.podspec +++ b/Socket.IO-Client-Swift.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = "Socket.IO-Client-Swift" s.module_name = "SocketIO" - s.version = "12.1.3" + s.version = "13.0.0" s.summary = "Socket.IO-client for iOS and OS X" s.description = <<-DESC Socket.IO-client for iOS and OS X. @@ -14,15 +14,16 @@ Pod::Spec.new do |s| s.ios.deployment_target = '8.0' s.osx.deployment_target = '10.10' s.tvos.deployment_target = '9.0' + s.watchos.deployment_target = '2.0' s.requires_arc = true s.source = { :git => "https://github.com/socketio/socket.io-client-swift.git", - :tag => 'v12.1.3', + :tag => 'v13.0.0', :submodules => true } s.pod_target_xcconfig = { 'SWIFT_VERSION' => '4.0' } s.source_files = "Source/SocketIO/**/*.swift", "Source/SocketIO/*.swift" - s.dependency "Starscream", "~> 2.1.1" + s.dependency "Starscream", "~> 3.0.2" end diff --git a/Socket.IO-Client-Swift.xcodeproj/project.pbxproj b/Socket.IO-Client-Swift.xcodeproj/project.pbxproj index d088ecf..32ecb6c 100644 --- a/Socket.IO-Client-Swift.xcodeproj/project.pbxproj +++ b/Socket.IO-Client-Swift.xcodeproj/project.pbxproj @@ -7,13 +7,8 @@ objects = { /* Begin PBXBuildFile section */ - 1C686BDA1F869AF9007D8627 /* SocketIOClientConfigurationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C686BD21F869AF1007D8627 /* SocketIOClientConfigurationTest.swift */; }; - 1C686BDB1F869AF9007D8627 /* SocketEngineTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C686BD31F869AF1007D8627 /* SocketEngineTest.swift */; }; - 1C686BDC1F869AF9007D8627 /* SocketSideEffectTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C686BD41F869AF1007D8627 /* SocketSideEffectTest.swift */; }; - 1C686BDD1F869AF9007D8627 /* SocketBasicPacketTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C686BD51F869AF1007D8627 /* SocketBasicPacketTest.swift */; }; - 1C686BDE1F869AF9007D8627 /* SocketAckManagerTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C686BD61F869AF1007D8627 /* SocketAckManagerTest.swift */; }; - 1C686BDF1F869AF9007D8627 /* SocketParserTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C686BD71F869AF1007D8627 /* SocketParserTest.swift */; }; - 1C686BE01F869AF9007D8627 /* SocketNamespacePacketTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C686BD81F869AF1007D8627 /* SocketNamespacePacketTest.swift */; }; + 1C6572803D7E252A77A86E5F /* SocketManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C65763817782DFAC67BE05C /* SocketManager.swift */; }; + 1C657FBB3F670261780FD72E /* SocketManagerSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C6574AF9687A213814753E4 /* SocketManagerSpec.swift */; }; 1C686BE21F869AFD007D8627 /* SocketIOClientConfigurationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C686BD21F869AF1007D8627 /* SocketIOClientConfigurationTest.swift */; }; 1C686BE31F869AFD007D8627 /* SocketEngineTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C686BD31F869AF1007D8627 /* SocketEngineTest.swift */; }; 1C686BE41F869AFD007D8627 /* SocketSideEffectTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C686BD41F869AF1007D8627 /* SocketSideEffectTest.swift */; }; @@ -21,111 +16,40 @@ 1C686BE61F869AFD007D8627 /* SocketAckManagerTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C686BD61F869AF1007D8627 /* SocketAckManagerTest.swift */; }; 1C686BE71F869AFD007D8627 /* SocketParserTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C686BD71F869AF1007D8627 /* SocketParserTest.swift */; }; 1C686BE81F869AFD007D8627 /* SocketNamespacePacketTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C686BD81F869AF1007D8627 /* SocketNamespacePacketTest.swift */; }; - 1C686BEA1F869B02007D8627 /* SocketIOClientConfigurationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C686BD21F869AF1007D8627 /* SocketIOClientConfigurationTest.swift */; }; - 1C686BEB1F869B02007D8627 /* SocketEngineTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C686BD31F869AF1007D8627 /* SocketEngineTest.swift */; }; - 1C686BEC1F869B02007D8627 /* SocketSideEffectTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C686BD41F869AF1007D8627 /* SocketSideEffectTest.swift */; }; - 1C686BED1F869B02007D8627 /* SocketBasicPacketTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C686BD51F869AF1007D8627 /* SocketBasicPacketTest.swift */; }; - 1C686BEE1F869B02007D8627 /* SocketAckManagerTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C686BD61F869AF1007D8627 /* SocketAckManagerTest.swift */; }; - 1C686BEF1F869B02007D8627 /* SocketParserTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C686BD71F869AF1007D8627 /* SocketParserTest.swift */; }; - 1C686BF01F869B02007D8627 /* SocketNamespacePacketTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C686BD81F869AF1007D8627 /* SocketNamespacePacketTest.swift */; }; - 1C686BFF1F869EA9007D8627 /* SocketObjectiveCTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1C686BFE1F869E9D007D8627 /* SocketObjectiveCTest.m */; }; 1C686C001F869EAE007D8627 /* SocketObjectiveCTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1C686BFE1F869E9D007D8627 /* SocketObjectiveCTest.m */; }; - 1C686C011F869EB6007D8627 /* SocketObjectiveCTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1C686BFE1F869E9D007D8627 /* SocketObjectiveCTest.m */; }; - 572EF21F1B51F16C00EEBB58 /* SocketIO.h in Headers */ = {isa = PBXBuildFile; fileRef = 572EF21E1B51F16C00EEBB58 /* SocketIO.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 572EF2251B51F16C00EEBB58 /* SocketIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 572EF2191B51F16C00EEBB58 /* SocketIO.framework */; }; - 572EF23D1B51F18A00EEBB58 /* SocketIO-Mac.h in Headers */ = {isa = PBXBuildFile; fileRef = 572EF23C1B51F18A00EEBB58 /* SocketIO-Mac.h */; settings = {ATTRIBUTES = (Public, ); }; }; 572EF2431B51F18A00EEBB58 /* SocketIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 572EF2381B51F18A00EEBB58 /* SocketIO.framework */; }; - 57634A111BD9B46A00E19CD7 /* SocketIO.h in Headers */ = {isa = PBXBuildFile; fileRef = 572EF21E1B51F16C00EEBB58 /* SocketIO.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 57634A3F1BD9B4BF00E19CD7 /* SocketIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 57634A161BD9B46A00E19CD7 /* SocketIO.framework */; }; - 6CA08A961D615C040061FD2A /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6CA08A951D615C040061FD2A /* Security.framework */; }; 6CA08A981D615C0B0061FD2A /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6CA08A971D615C0B0061FD2A /* Security.framework */; }; - 6CA08A9A1D615C140061FD2A /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6CA08A991D615C140061FD2A /* Security.framework */; }; - 749FA1A61F81152B002FBB30 /* Starscream.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 9432E00B1F77F883006AF628 /* Starscream.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 74D0F58E1F804FED0037C4DC /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 74D0F58D1F804FED0037C4DC /* libz.tbd */; }; + 74BF53581F894326004972D8 /* SocketIO.h in Headers */ = {isa = PBXBuildFile; fileRef = 572EF23C1B51F18A00EEBB58 /* SocketIO.h */; settings = {ATTRIBUTES = (Public, ); }; }; 74D0F5961F8053950037C4DC /* Starscream.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9432E00B1F77F883006AF628 /* Starscream.framework */; }; 74DA21741F09440F009C19EE /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 74DA21731F09440F009C19EE /* libz.tbd */; }; 74DA217C1F09457B009C19EE /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 74DA21731F09440F009C19EE /* libz.tbd */; }; - 9432E0071F77F7CA006AF628 /* SSLSecurity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9432E0061F77F7CA006AF628 /* SSLSecurity.swift */; }; - 9432E00A1F77F87D006AF628 /* Starscream.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9432E0091F77F87D006AF628 /* Starscream.framework */; }; - 9432E00E1F77F889006AF628 /* Starscream.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9432E00D1F77F889006AF628 /* Starscream.framework */; }; 9432E00F1F77F8C4006AF628 /* SSLSecurity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9432E0061F77F7CA006AF628 /* SSLSecurity.swift */; }; - 9432E0101F77F8C4006AF628 /* SSLSecurity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9432E0061F77F7CA006AF628 /* SSLSecurity.swift */; }; DD52B048C71D724ABBD18C71 /* SocketTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52BDC9E66AADA2CC5E8246 /* SocketTypes.swift */; }; - DD52B06F898CD9164AC8F80E /* SocketAnyEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52B5A9DE10C7A8AD35617F /* SocketAnyEvent.swift */; }; - DD52B099A5166C5FF975FAB5 /* SocketClientManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52B282975446C9A9C56D7B /* SocketClientManager.swift */; }; - DD52B0A84B1EBF50C84481D1 /* SocketAckManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52B09F7984E730513AB7E5 /* SocketAckManager.swift */; }; - DD52B0C7C017460057CEF1A5 /* SocketTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52BDC9E66AADA2CC5E8246 /* SocketTypes.swift */; }; - DD52B1081FF25DF079E0B5D2 /* SocketEngineSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52B645273A873667BC2D43 /* SocketEngineSpec.swift */; }; DD52B11AF936352BAE30B2C8 /* SocketStringReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52BA240D139F72633D4159 /* SocketStringReader.swift */; }; - DD52B16128003D74FC23A01F /* SocketIOClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52BA1F41F2E4B3DC20260E /* SocketIOClient.swift */; }; - DD52B1653EB81FAA48E15A22 /* SocketExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52B471D780013E18DF9335 /* SocketExtensions.swift */; }; - DD52B1B2424B764C1F5B0CDF /* SocketEngineWebsocket.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52BE9AD8B2BD7F841CD1D4 /* SocketEngineWebsocket.swift */; }; DD52B1F8BA0455EBE7C1B93E /* SocketAckEmitter.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52BFF2E3216CDC364BB8AF /* SocketAckEmitter.swift */; }; DD52B1FDEB06B853FF932AC7 /* SocketEnginePacketType.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52B4EA17D8C3F35C8E2CB4 /* SocketEnginePacketType.swift */; }; - DD52B1FEE4C81226884B1E67 /* SocketIOClientOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52B078DB0A3C3D1BB507CD /* SocketIOClientOption.swift */; }; - DD52B2023B7D10D7D733513D /* SocketAckEmitter.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52BFF2E3216CDC364BB8AF /* SocketAckEmitter.swift */; }; - DD52B203B4F32D84A6CFDFE7 /* SocketEngine.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52B7A9779A2E08075E5AAC /* SocketEngine.swift */; }; - DD52B2386039DD776E9A5270 /* SocketEngineWebsocket.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52BE9AD8B2BD7F841CD1D4 /* SocketEngineWebsocket.swift */; }; - DD52B25B365B0EDB9F6E88EA /* SocketIOClientConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52B57FFEE8560CFFD793B3 /* SocketIOClientConfiguration.swift */; }; - DD52B26DA9E4D566276B7E49 /* SocketIOClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52BA1F41F2E4B3DC20260E /* SocketIOClient.swift */; }; - DD52B27DABA4C475B850A326 /* SocketEventHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52B6DCCBBAC6BE9C22568D /* SocketEventHandler.swift */; }; - DD52B28103E47A9BE15494A5 /* SocketLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52BED81BF312B0E90E92AC /* SocketLogger.swift */; }; DD52B2AFE7D46039C7AE4D19 /* SocketIOClientOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52B078DB0A3C3D1BB507CD /* SocketIOClientOption.swift */; }; - DD52B3105268735BDB1F6612 /* SocketTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52BDC9E66AADA2CC5E8246 /* SocketTypes.swift */; }; - DD52B319CF9D6FAE75119A58 /* SocketAckEmitter.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52BFF2E3216CDC364BB8AF /* SocketAckEmitter.swift */; }; - DD52B396621157BBA175DE7E /* SocketEnginePacketType.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52B4EA17D8C3F35C8E2CB4 /* SocketEnginePacketType.swift */; }; DD52B3A6C1E082841C35C85D /* SocketEngineClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52BE5FDCE1D684132E897C /* SocketEngineClient.swift */; }; - DD52B3C95BFA9E9D9FA30D6D /* SocketLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52BED81BF312B0E90E92AC /* SocketLogger.swift */; }; - DD52B3D941DB2A0C678F8251 /* SocketIOClientStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52B1D9BC4AE46D38D827DE /* SocketIOClientStatus.swift */; }; - DD52B4223DCCB75630441370 /* SocketIOClientSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52BCAF915A546288664346 /* SocketIOClientSpec.swift */; }; DD52B44AE56F2E07F3F3F991 /* SocketAckManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52B09F7984E730513AB7E5 /* SocketAckManager.swift */; }; DD52B4DFA12F2599410205D9 /* SocketEngineWebsocket.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52BE9AD8B2BD7F841CD1D4 /* SocketEngineWebsocket.swift */; }; - DD52B4E953A0B2BFB1626416 /* SocketStringReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52BA240D139F72633D4159 /* SocketStringReader.swift */; }; + DD52B53F2609D91A683DFCDD /* ManagerObjectiveCTest.m in Sources */ = {isa = PBXBuildFile; fileRef = DD52BB5E907D283ACC31E17F /* ManagerObjectiveCTest.m */; }; DD52B56DE03CDB4F40BD1A23 /* SocketExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52B471D780013E18DF9335 /* SocketExtensions.swift */; }; DD52B57E7ABC61B57EE2A4B8 /* SocketPacket.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52B59C11D3D2BC63612E50 /* SocketPacket.swift */; }; - DD52B633A16E194E761813CB /* SocketEngineSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52B645273A873667BC2D43 /* SocketEngineSpec.swift */; }; - DD52B660D63B6A25C3755AA7 /* SocketClientManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52B282975446C9A9C56D7B /* SocketClientManager.swift */; }; - DD52B6BE1D398DBD144C4D14 /* SocketAnyEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52B5A9DE10C7A8AD35617F /* SocketAnyEvent.swift */; }; - DD52B6DF3770172053359F51 /* SocketClientManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52B282975446C9A9C56D7B /* SocketClientManager.swift */; }; - DD52B6E44917CA5DFC3CE6B5 /* SocketIOClientStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52B1D9BC4AE46D38D827DE /* SocketIOClientStatus.swift */; }; - DD52B6FC2F0A6A3106FFCBE3 /* SocketIOClientOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52B078DB0A3C3D1BB507CD /* SocketIOClientOption.swift */; }; - DD52B780FF3E646583BDC192 /* SocketEnginePollable.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52B2D110F55723F82B108E /* SocketEnginePollable.swift */; }; - DD52B86B8430A179B3D1039D /* SocketEngineClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52BE5FDCE1D684132E897C /* SocketEngineClient.swift */; }; DD52B883F942CD5A9D29892B /* SocketEnginePollable.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52B2D110F55723F82B108E /* SocketEnginePollable.swift */; }; DD52B9412F660F828B683422 /* SocketParsable.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52B31D0E6815F5F10CEFB6 /* SocketParsable.swift */; }; - DD52BA7825D2D32C3311BE76 /* SocketStringReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52BA240D139F72633D4159 /* SocketStringReader.swift */; }; - DD52BA7DB1DAD7BB1A965CD2 /* SocketEngine.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52B7A9779A2E08075E5AAC /* SocketEngine.swift */; }; - DD52BAF5C3F7FEF04D5D0932 /* SocketPacket.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52B59C11D3D2BC63612E50 /* SocketPacket.swift */; }; DD52BB69B6D260035B652CA4 /* SocketAnyEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52B5A9DE10C7A8AD35617F /* SocketAnyEvent.swift */; }; - DD52BB6BD8F50D339AD53844 /* SocketIOClientConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52B57FFEE8560CFFD793B3 /* SocketIOClientConfiguration.swift */; }; DD52BB82239886CF6ADD642C /* SocketEngine.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52B7A9779A2E08075E5AAC /* SocketEngine.swift */; }; - DD52BB88BD4C5641CFD2E8D4 /* SocketIOClientSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52BCAF915A546288664346 /* SocketIOClientSpec.swift */; }; DD52BB9A3E42FF2DD6BE7C2F /* SocketIOClientSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52BCAF915A546288664346 /* SocketIOClientSpec.swift */; }; - DD52BC0F60703CB9C3A6F594 /* SocketParsable.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52B31D0E6815F5F10CEFB6 /* SocketParsable.swift */; }; - DD52BC28EC86700F814CCFAA /* SocketPacket.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52B59C11D3D2BC63612E50 /* SocketPacket.swift */; }; DD52BC3F1F880820E8FDFD0C /* SocketLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52BED81BF312B0E90E92AC /* SocketLogger.swift */; }; + DD52BCCD25EFA76E0F9B313C /* SocketMangerTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52BBAC5FAA7730D32CD5BF /* SocketMangerTest.swift */; }; DD52BD065B74AC5B77BAEFAA /* SocketIOClientConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52B57FFEE8560CFFD793B3 /* SocketIOClientConfiguration.swift */; }; - DD52BD275A22ADEF73506EB4 /* SocketEngineClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52BE5FDCE1D684132E897C /* SocketEngineClient.swift */; }; - DD52BD9CCA7063C77045A7E7 /* SocketEnginePollable.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52B2D110F55723F82B108E /* SocketEnginePollable.swift */; }; - DD52BDB51FE41BAB49073BEF /* SocketEventHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52B6DCCBBAC6BE9C22568D /* SocketEventHandler.swift */; }; - DD52BE14D2DD9C9C9768C2D8 /* SocketParsable.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52B31D0E6815F5F10CEFB6 /* SocketParsable.swift */; }; - DD52BE29B55736873B00ECC4 /* SocketAckManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52B09F7984E730513AB7E5 /* SocketAckManager.swift */; }; - DD52BE4D1E6BB752CD9614A6 /* SocketIOClientStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52B1D9BC4AE46D38D827DE /* SocketIOClientStatus.swift */; }; + DD52BE4D1E6BB752CD9614A6 /* SocketIOStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52B1D9BC4AE46D38D827DE /* SocketIOStatus.swift */; }; DD52BF924BEF05E1235CFD29 /* SocketIOClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52BA1F41F2E4B3DC20260E /* SocketIOClient.swift */; }; DD52BFBC9E7CC32D3515AC80 /* SocketEngineSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52B645273A873667BC2D43 /* SocketEngineSpec.swift */; }; DD52BFEB4DBD3BF8D93DAEFF /* SocketEventHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52B6DCCBBAC6BE9C22568D /* SocketEventHandler.swift */; }; - DD52BFF4CC89C83012182B42 /* SocketExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52B471D780013E18DF9335 /* SocketExtensions.swift */; }; - DD52BFFA8473060CB00F5092 /* SocketEnginePacketType.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD52B4EA17D8C3F35C8E2CB4 /* SocketEnginePacketType.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - 572EF2261B51F16C00EEBB58 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 572EF20E1B51F12F00EEBB58 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 572EF2181B51F16C00EEBB58; - remoteInfo = "SocketIO-iOS"; - }; 572EF2441B51F18A00EEBB58 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 572EF20E1B51F12F00EEBB58 /* Project object */; @@ -133,29 +57,11 @@ remoteGlobalIDString = 572EF2371B51F18A00EEBB58; remoteInfo = "SocketIO-Mac"; }; - 57634A3D1BD9B4B800E19CD7 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 572EF20E1B51F12F00EEBB58 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 576349FA1BD9B46A00E19CD7; - remoteInfo = "SocketIO-tvOS"; - }; /* End PBXContainerItemProxy section */ -/* Begin PBXCopyFilesBuildPhase section */ - 749FA1A51F811521002FBB30 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 10; - files = ( - 749FA1A61F81152B002FBB30 /* Starscream.framework in CopyFiles */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXCopyFilesBuildPhase section */ - /* Begin PBXFileReference section */ + 1C6574AF9687A213814753E4 /* SocketManagerSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketManagerSpec.swift; sourceTree = ""; }; + 1C65763817782DFAC67BE05C /* SocketManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketManager.swift; sourceTree = ""; }; 1C686BD21F869AF1007D8627 /* SocketIOClientConfigurationTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SocketIOClientConfigurationTest.swift; sourceTree = ""; }; 1C686BD31F869AF1007D8627 /* SocketEngineTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SocketEngineTest.swift; sourceTree = ""; }; 1C686BD41F869AF1007D8627 /* SocketSideEffectTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SocketSideEffectTest.swift; sourceTree = ""; }; @@ -164,16 +70,10 @@ 1C686BD71F869AF1007D8627 /* SocketParserTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SocketParserTest.swift; sourceTree = ""; }; 1C686BD81F869AF1007D8627 /* SocketNamespacePacketTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SocketNamespacePacketTest.swift; sourceTree = ""; }; 1C686BFE1F869E9D007D8627 /* SocketObjectiveCTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SocketObjectiveCTest.m; sourceTree = ""; }; - 572EF2191B51F16C00EEBB58 /* SocketIO.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SocketIO.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 572EF21D1B51F16C00EEBB58 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 572EF21E1B51F16C00EEBB58 /* SocketIO.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SocketIO.h; sourceTree = ""; }; - 572EF2241B51F16C00EEBB58 /* SocketIO-iOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SocketIO-iOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; 572EF2381B51F18A00EEBB58 /* SocketIO.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SocketIO.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 572EF23B1B51F18A00EEBB58 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 572EF23C1B51F18A00EEBB58 /* SocketIO-Mac.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SocketIO-Mac.h"; sourceTree = ""; }; - 572EF2421B51F18A00EEBB58 /* SocketIO-MacTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SocketIO-MacTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; - 57634A161BD9B46A00E19CD7 /* SocketIO.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SocketIO.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 57634A3B1BD9B46D00E19CD7 /* SocketIO-tvOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SocketIO-tvOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + 572EF23C1B51F18A00EEBB58 /* SocketIO.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SocketIO.h; sourceTree = ""; }; + 572EF2421B51F18A00EEBB58 /* SocketIO-Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SocketIO-Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; 6CA08A951D615C040061FD2A /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.3.sdk/System/Library/Frameworks/Security.framework; sourceTree = DEVELOPER_DIR; }; 6CA08A971D615C0B0061FD2A /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; 6CA08A991D615C140061FD2A /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS9.2.sdk/System/Library/Frameworks/Security.framework; sourceTree = DEVELOPER_DIR; }; @@ -188,8 +88,8 @@ 9432E00D1F77F889006AF628 /* Starscream.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Starscream.framework; path = Carthage/Build/tvOS/Starscream.framework; sourceTree = ""; }; DD52B078DB0A3C3D1BB507CD /* SocketIOClientOption.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketIOClientOption.swift; sourceTree = ""; }; DD52B09F7984E730513AB7E5 /* SocketAckManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketAckManager.swift; sourceTree = ""; }; - DD52B1D9BC4AE46D38D827DE /* SocketIOClientStatus.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketIOClientStatus.swift; sourceTree = ""; }; - DD52B282975446C9A9C56D7B /* SocketClientManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketClientManager.swift; sourceTree = ""; }; + DD52B1D9BC4AE46D38D827DE /* SocketIOStatus.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketIOStatus.swift; sourceTree = ""; }; + DD52B2C54A6ADF3371C13DCB /* SocketObjectiveCTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SocketObjectiveCTest.h; sourceTree = ""; }; DD52B2D110F55723F82B108E /* SocketEnginePollable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketEnginePollable.swift; sourceTree = ""; }; DD52B31D0E6815F5F10CEFB6 /* SocketParsable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketParsable.swift; sourceTree = ""; }; DD52B471D780013E18DF9335 /* SocketExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketExtensions.swift; sourceTree = ""; }; @@ -200,8 +100,11 @@ DD52B645273A873667BC2D43 /* SocketEngineSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketEngineSpec.swift; sourceTree = ""; }; DD52B6DCCBBAC6BE9C22568D /* SocketEventHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketEventHandler.swift; sourceTree = ""; }; DD52B7A9779A2E08075E5AAC /* SocketEngine.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketEngine.swift; sourceTree = ""; }; + DD52B8396C7DEE7BFD6A985A /* ManagerObjectiveCTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ManagerObjectiveCTest.h; sourceTree = ""; }; DD52BA1F41F2E4B3DC20260E /* SocketIOClient.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketIOClient.swift; sourceTree = ""; }; DD52BA240D139F72633D4159 /* SocketStringReader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketStringReader.swift; sourceTree = ""; }; + DD52BB5E907D283ACC31E17F /* ManagerObjectiveCTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ManagerObjectiveCTest.m; sourceTree = ""; }; + DD52BBAC5FAA7730D32CD5BF /* SocketMangerTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketMangerTest.swift; sourceTree = ""; }; DD52BCAF915A546288664346 /* SocketIOClientSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketIOClientSpec.swift; sourceTree = ""; }; DD52BDC9E66AADA2CC5E8246 /* SocketTypes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketTypes.swift; sourceTree = ""; }; DD52BE5FDCE1D684132E897C /* SocketEngineClient.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketEngineClient.swift; sourceTree = ""; }; @@ -211,24 +114,6 @@ /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - 572EF2151B51F16C00EEBB58 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 74D0F58E1F804FED0037C4DC /* libz.tbd in Frameworks */, - 6CA08A961D615C040061FD2A /* Security.framework in Frameworks */, - 9432E00A1F77F87D006AF628 /* Starscream.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 572EF2211B51F16C00EEBB58 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 572EF2251B51F16C00EEBB58 /* SocketIO.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; 572EF2341B51F18A00EEBB58 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -248,26 +133,19 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 57634A0F1BD9B46A00E19CD7 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 6CA08A9A1D615C140061FD2A /* Security.framework in Frameworks */, - 9432E00E1F77F889006AF628 /* Starscream.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 57634A351BD9B46D00E19CD7 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 57634A3F1BD9B4BF00E19CD7 /* SocketIO.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 1C657951DEA2E0293D0FD1B6 /* Manager */ = { + isa = PBXGroup; + children = ( + 1C65763817782DFAC67BE05C /* SocketManager.swift */, + 1C6574AF9687A213814753E4 /* SocketManagerSpec.swift */, + ); + name = Manager; + path = Source/SocketIO/Manager; + sourceTree = ""; + }; 1C686BD11F869AF1007D8627 /* TestSocketIO */ = { isa = PBXGroup; children = ( @@ -278,6 +156,7 @@ 1C686BD61F869AF1007D8627 /* SocketAckManagerTest.swift */, 1C686BD71F869AF1007D8627 /* SocketParserTest.swift */, 1C686BD81F869AF1007D8627 /* SocketNamespacePacketTest.swift */, + DD52BBAC5FAA7730D32CD5BF /* SocketMangerTest.swift */, ); name = TestSocketIO; path = Tests/TestSocketIO; @@ -287,6 +166,9 @@ isa = PBXGroup; children = ( 1C686BFE1F869E9D007D8627 /* SocketObjectiveCTest.m */, + DD52BB5E907D283ACC31E17F /* ManagerObjectiveCTest.m */, + DD52B8396C7DEE7BFD6A985A /* ManagerObjectiveCTest.h */, + DD52B2C54A6ADF3371C13DCB /* SocketObjectiveCTest.h */, ); name = TestSocketIOObjc; path = Tests/TestSocketIOObjc; @@ -299,8 +181,7 @@ 1C686BFD1F869E9D007D8627 /* TestSocketIOObjc */, 6CA08A9B1D615C190061FD2A /* Frameworks */, 572EF21A1B51F16C00EEBB58 /* Products */, - 572EF21B1B51F16C00EEBB58 /* SocketIO-iOS */, - 572EF2391B51F18A00EEBB58 /* SocketIO-Mac */, + 572EF2391B51F18A00EEBB58 /* SocketIO */, 5764DF7B1B51F24A004FF46E /* Source */, ); sourceTree = ""; @@ -308,40 +189,19 @@ 572EF21A1B51F16C00EEBB58 /* Products */ = { isa = PBXGroup; children = ( - 572EF2191B51F16C00EEBB58 /* SocketIO.framework */, - 572EF2241B51F16C00EEBB58 /* SocketIO-iOSTests.xctest */, 572EF2381B51F18A00EEBB58 /* SocketIO.framework */, - 572EF2421B51F18A00EEBB58 /* SocketIO-MacTests.xctest */, - 57634A161BD9B46A00E19CD7 /* SocketIO.framework */, - 57634A3B1BD9B46D00E19CD7 /* SocketIO-tvOSTests.xctest */, + 572EF2421B51F18A00EEBB58 /* SocketIO-Tests.xctest */, ); name = Products; sourceTree = ""; }; - 572EF21B1B51F16C00EEBB58 /* SocketIO-iOS */ = { + 572EF2391B51F18A00EEBB58 /* SocketIO */ = { isa = PBXGroup; children = ( - 572EF21E1B51F16C00EEBB58 /* SocketIO.h */, - 572EF21C1B51F16C00EEBB58 /* Supporting Files */, - ); - path = "SocketIO-iOS"; - sourceTree = ""; - }; - 572EF21C1B51F16C00EEBB58 /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 572EF21D1B51F16C00EEBB58 /* Info.plist */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 572EF2391B51F18A00EEBB58 /* SocketIO-Mac */ = { - isa = PBXGroup; - children = ( - 572EF23C1B51F18A00EEBB58 /* SocketIO-Mac.h */, + 572EF23C1B51F18A00EEBB58 /* SocketIO.h */, 572EF23A1B51F18A00EEBB58 /* Supporting Files */, ); - path = "SocketIO-Mac"; + path = SocketIO; sourceTree = ""; }; 572EF23A1B51F18A00EEBB58 /* Supporting Files */ = { @@ -360,6 +220,7 @@ DD52B6A0966AF71393777311 /* Client */, DD52B1D10D761CEF3944A6BC /* Util */, DD52B647ED881F3FF6EEC617 /* Parse */, + 1C657951DEA2E0293D0FD1B6 /* Manager */, ); name = Source; sourceTree = ""; @@ -413,7 +274,6 @@ DD52BED81BF312B0E90E92AC /* SocketLogger.swift */, DD52B471D780013E18DF9335 /* SocketExtensions.swift */, DD52BA240D139F72633D4159 /* SocketStringReader.swift */, - DD52B282975446C9A9C56D7B /* SocketClientManager.swift */, 9432E0061F77F7CA006AF628 /* SSLSecurity.swift */, ); name = Util; @@ -438,7 +298,7 @@ DD52B6DCCBBAC6BE9C22568D /* SocketEventHandler.swift */, DD52BCAF915A546288664346 /* SocketIOClientSpec.swift */, DD52B078DB0A3C3D1BB507CD /* SocketIOClientOption.swift */, - DD52B1D9BC4AE46D38D827DE /* SocketIOClientStatus.swift */, + DD52B1D9BC4AE46D38D827DE /* SocketIOStatus.swift */, DD52B57FFEE8560CFFD793B3 /* SocketIOClientConfiguration.swift */, ); name = Client; @@ -472,73 +332,20 @@ /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ - 572EF2161B51F16C00EEBB58 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 572EF21F1B51F16C00EEBB58 /* SocketIO.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; 572EF2351B51F18A00EEBB58 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 572EF23D1B51F18A00EEBB58 /* SocketIO-Mac.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 57634A101BD9B46A00E19CD7 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 57634A111BD9B46A00E19CD7 /* SocketIO.h in Headers */, + 74BF53581F894326004972D8 /* SocketIO.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ - 572EF2181B51F16C00EEBB58 /* SocketIO-iOS */ = { + 572EF2371B51F18A00EEBB58 /* SocketIO */ = { isa = PBXNativeTarget; - buildConfigurationList = 572EF22D1B51F16C00EEBB58 /* Build configuration list for PBXNativeTarget "SocketIO-iOS" */; - buildPhases = ( - 572EF2141B51F16C00EEBB58 /* Sources */, - 572EF2151B51F16C00EEBB58 /* Frameworks */, - 572EF2161B51F16C00EEBB58 /* Headers */, - 572EF2171B51F16C00EEBB58 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "SocketIO-iOS"; - productName = "SocketIO-iOS"; - productReference = 572EF2191B51F16C00EEBB58 /* SocketIO.framework */; - productType = "com.apple.product-type.framework"; - }; - 572EF2231B51F16C00EEBB58 /* SocketIO-iOSTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 572EF2301B51F16C00EEBB58 /* Build configuration list for PBXNativeTarget "SocketIO-iOSTests" */; - buildPhases = ( - 572EF2201B51F16C00EEBB58 /* Sources */, - 572EF2211B51F16C00EEBB58 /* Frameworks */, - 572EF2221B51F16C00EEBB58 /* Resources */, - 749FA19A1F8111A6002FBB30 /* ShellScript */, - ); - buildRules = ( - ); - dependencies = ( - 572EF2271B51F16C00EEBB58 /* PBXTargetDependency */, - ); - name = "SocketIO-iOSTests"; - productName = "SocketIO-iOSTests"; - productReference = 572EF2241B51F16C00EEBB58 /* SocketIO-iOSTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; - 572EF2371B51F18A00EEBB58 /* SocketIO-Mac */ = { - isa = PBXNativeTarget; - buildConfigurationList = 572EF24B1B51F18A00EEBB58 /* Build configuration list for PBXNativeTarget "SocketIO-Mac" */; + buildConfigurationList = 572EF24B1B51F18A00EEBB58 /* Build configuration list for PBXNativeTarget "SocketIO" */; buildPhases = ( 572EF2331B51F18A00EEBB58 /* Sources */, 572EF2341B51F18A00EEBB58 /* Frameworks */, @@ -549,64 +356,28 @@ ); dependencies = ( ); - name = "SocketIO-Mac"; + name = SocketIO; productName = "SocketIO-Mac"; productReference = 572EF2381B51F18A00EEBB58 /* SocketIO.framework */; productType = "com.apple.product-type.framework"; }; - 572EF2411B51F18A00EEBB58 /* SocketIO-MacTests */ = { + 572EF2411B51F18A00EEBB58 /* SocketIO-Tests */ = { isa = PBXNativeTarget; - buildConfigurationList = 572EF24E1B51F18A00EEBB58 /* Build configuration list for PBXNativeTarget "SocketIO-MacTests" */; + buildConfigurationList = 572EF24E1B51F18A00EEBB58 /* Build configuration list for PBXNativeTarget "SocketIO-Tests" */; buildPhases = ( 572EF23E1B51F18A00EEBB58 /* Sources */, 572EF23F1B51F18A00EEBB58 /* Frameworks */, 572EF2401B51F18A00EEBB58 /* Resources */, - 749FA1A51F811521002FBB30 /* CopyFiles */, + 74BF53571F8930D3004972D8 /* ShellScript */, ); buildRules = ( ); dependencies = ( 572EF2451B51F18A00EEBB58 /* PBXTargetDependency */, ); - name = "SocketIO-MacTests"; + name = "SocketIO-Tests"; productName = "SocketIO-MacTests"; - productReference = 572EF2421B51F18A00EEBB58 /* SocketIO-MacTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; - 576349FA1BD9B46A00E19CD7 /* SocketIO-tvOS */ = { - isa = PBXNativeTarget; - buildConfigurationList = 57634A131BD9B46A00E19CD7 /* Build configuration list for PBXNativeTarget "SocketIO-tvOS" */; - buildPhases = ( - 576349FB1BD9B46A00E19CD7 /* Sources */, - 57634A0F1BD9B46A00E19CD7 /* Frameworks */, - 57634A101BD9B46A00E19CD7 /* Headers */, - 57634A121BD9B46A00E19CD7 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "SocketIO-tvOS"; - productName = "SocketIO-iOS"; - productReference = 57634A161BD9B46A00E19CD7 /* SocketIO.framework */; - productType = "com.apple.product-type.framework"; - }; - 57634A181BD9B46D00E19CD7 /* SocketIO-tvOSTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 57634A381BD9B46D00E19CD7 /* Build configuration list for PBXNativeTarget "SocketIO-tvOSTests" */; - buildPhases = ( - 57634A1B1BD9B46D00E19CD7 /* Sources */, - 57634A351BD9B46D00E19CD7 /* Frameworks */, - 57634A371BD9B46D00E19CD7 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 57634A3E1BD9B4B800E19CD7 /* PBXTargetDependency */, - ); - name = "SocketIO-tvOSTests"; - productName = "SocketIO-iOSTests"; - productReference = 57634A3B1BD9B46D00E19CD7 /* SocketIO-tvOSTests.xctest */; + productReference = 572EF2421B51F18A00EEBB58 /* SocketIO-Tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ @@ -619,13 +390,6 @@ LastSwiftUpdateCheck = 0730; LastUpgradeCheck = 0900; TargetAttributes = { - 572EF2181B51F16C00EEBB58 = { - CreatedOnToolsVersion = 6.4; - }; - 572EF2231B51F16C00EEBB58 = { - CreatedOnToolsVersion = 6.4; - LastSwiftMigration = 0900; - }; 572EF2371B51F18A00EEBB58 = { CreatedOnToolsVersion = 6.4; LastSwiftMigration = 0900; @@ -634,9 +398,6 @@ CreatedOnToolsVersion = 6.4; LastSwiftMigration = 0900; }; - 57634A181BD9B46D00E19CD7 = { - LastSwiftMigration = 0900; - }; }; }; buildConfigurationList = 572EF2111B51F12F00EEBB58 /* Build configuration list for PBXProject "Socket.IO-Client-Swift" */; @@ -651,31 +412,13 @@ projectDirPath = ""; projectRoot = ""; targets = ( - 572EF2181B51F16C00EEBB58 /* SocketIO-iOS */, - 572EF2231B51F16C00EEBB58 /* SocketIO-iOSTests */, - 572EF2371B51F18A00EEBB58 /* SocketIO-Mac */, - 572EF2411B51F18A00EEBB58 /* SocketIO-MacTests */, - 576349FA1BD9B46A00E19CD7 /* SocketIO-tvOS */, - 57634A181BD9B46D00E19CD7 /* SocketIO-tvOSTests */, + 572EF2371B51F18A00EEBB58 /* SocketIO */, + 572EF2411B51F18A00EEBB58 /* SocketIO-Tests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ - 572EF2171B51F16C00EEBB58 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 572EF2221B51F16C00EEBB58 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; 572EF2361B51F18A00EEBB58 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -690,86 +433,25 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 57634A121BD9B46A00E19CD7 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 57634A371BD9B46D00E19CD7 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 749FA19A1F8111A6002FBB30 /* ShellScript */ = { + 74BF53571F8930D3004972D8 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( - "$(SRCROOT)/Carthage/Build/iOS/Starscream.framework", ); outputPaths = ( - "$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/Starscream.framework", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "/usr/local/bin/carthage copy-frameworks"; + shellScript = "for path in $FRAMEWORK_SEARCH_PATHS\ndo\n if [ -d \"${path}/Starscream.framework\" ] && [[ $path == *\"Carthage\"* ]]; then\n export SCRIPT_INPUT_FILE_COUNT=1\n export SCRIPT_INPUT_FILE_0=\"${path}/Starscream.framework\"\n /usr/local/bin/carthage copy-frameworks\n break\n fi\ndone"; }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ - 572EF2141B51F16C00EEBB58 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - DD52B203B4F32D84A6CFDFE7 /* SocketEngine.swift in Sources */, - DD52B633A16E194E761813CB /* SocketEngineSpec.swift in Sources */, - DD52B86B8430A179B3D1039D /* SocketEngineClient.swift in Sources */, - DD52B780FF3E646583BDC192 /* SocketEnginePollable.swift in Sources */, - DD52B1B2424B764C1F5B0CDF /* SocketEngineWebsocket.swift in Sources */, - DD52B396621157BBA175DE7E /* SocketEnginePacketType.swift in Sources */, - DD52B319CF9D6FAE75119A58 /* SocketAckEmitter.swift in Sources */, - DD52BE29B55736873B00ECC4 /* SocketAckManager.swift in Sources */, - DD52B06F898CD9164AC8F80E /* SocketAnyEvent.swift in Sources */, - DD52B16128003D74FC23A01F /* SocketIOClient.swift in Sources */, - DD52BDB51FE41BAB49073BEF /* SocketEventHandler.swift in Sources */, - 9432E0071F77F7CA006AF628 /* SSLSecurity.swift in Sources */, - DD52BB88BD4C5641CFD2E8D4 /* SocketIOClientSpec.swift in Sources */, - DD52B1FEE4C81226884B1E67 /* SocketIOClientOption.swift in Sources */, - DD52B6E44917CA5DFC3CE6B5 /* SocketIOClientStatus.swift in Sources */, - DD52B25B365B0EDB9F6E88EA /* SocketIOClientConfiguration.swift in Sources */, - DD52B3105268735BDB1F6612 /* SocketTypes.swift in Sources */, - DD52B28103E47A9BE15494A5 /* SocketLogger.swift in Sources */, - DD52B1653EB81FAA48E15A22 /* SocketExtensions.swift in Sources */, - DD52B4E953A0B2BFB1626416 /* SocketStringReader.swift in Sources */, - DD52B6DF3770172053359F51 /* SocketClientManager.swift in Sources */, - DD52BAF5C3F7FEF04D5D0932 /* SocketPacket.swift in Sources */, - DD52BE14D2DD9C9C9768C2D8 /* SocketParsable.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 572EF2201B51F16C00EEBB58 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 1C686BFF1F869EA9007D8627 /* SocketObjectiveCTest.m in Sources */, - 1C686BEA1F869B02007D8627 /* SocketIOClientConfigurationTest.swift in Sources */, - 1C686BEB1F869B02007D8627 /* SocketEngineTest.swift in Sources */, - 1C686BEC1F869B02007D8627 /* SocketSideEffectTest.swift in Sources */, - 1C686BED1F869B02007D8627 /* SocketBasicPacketTest.swift in Sources */, - 1C686BEE1F869B02007D8627 /* SocketAckManagerTest.swift in Sources */, - 1C686BEF1F869B02007D8627 /* SocketParserTest.swift in Sources */, - 1C686BF01F869B02007D8627 /* SocketNamespacePacketTest.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; 572EF2331B51F18A00EEBB58 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -788,15 +470,16 @@ 9432E00F1F77F8C4006AF628 /* SSLSecurity.swift in Sources */, DD52BB9A3E42FF2DD6BE7C2F /* SocketIOClientSpec.swift in Sources */, DD52B2AFE7D46039C7AE4D19 /* SocketIOClientOption.swift in Sources */, - DD52BE4D1E6BB752CD9614A6 /* SocketIOClientStatus.swift in Sources */, + DD52BE4D1E6BB752CD9614A6 /* SocketIOStatus.swift in Sources */, DD52BD065B74AC5B77BAEFAA /* SocketIOClientConfiguration.swift in Sources */, DD52B048C71D724ABBD18C71 /* SocketTypes.swift in Sources */, DD52BC3F1F880820E8FDFD0C /* SocketLogger.swift in Sources */, DD52B56DE03CDB4F40BD1A23 /* SocketExtensions.swift in Sources */, DD52B11AF936352BAE30B2C8 /* SocketStringReader.swift in Sources */, - DD52B660D63B6A25C3755AA7 /* SocketClientManager.swift in Sources */, DD52B57E7ABC61B57EE2A4B8 /* SocketPacket.swift in Sources */, DD52B9412F660F828B683422 /* SocketParsable.swift in Sources */, + 1C6572803D7E252A77A86E5F /* SocketManager.swift in Sources */, + 1C657FBB3F670261780FD72E /* SocketManagerSpec.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -812,72 +495,19 @@ 1C686BE61F869AFD007D8627 /* SocketAckManagerTest.swift in Sources */, 1C686BE71F869AFD007D8627 /* SocketParserTest.swift in Sources */, 1C686BE81F869AFD007D8627 /* SocketNamespacePacketTest.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 576349FB1BD9B46A00E19CD7 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - DD52BA7DB1DAD7BB1A965CD2 /* SocketEngine.swift in Sources */, - DD52B1081FF25DF079E0B5D2 /* SocketEngineSpec.swift in Sources */, - DD52BD275A22ADEF73506EB4 /* SocketEngineClient.swift in Sources */, - DD52BD9CCA7063C77045A7E7 /* SocketEnginePollable.swift in Sources */, - DD52B2386039DD776E9A5270 /* SocketEngineWebsocket.swift in Sources */, - DD52BFFA8473060CB00F5092 /* SocketEnginePacketType.swift in Sources */, - DD52B2023B7D10D7D733513D /* SocketAckEmitter.swift in Sources */, - DD52B0A84B1EBF50C84481D1 /* SocketAckManager.swift in Sources */, - DD52B6BE1D398DBD144C4D14 /* SocketAnyEvent.swift in Sources */, - DD52B26DA9E4D566276B7E49 /* SocketIOClient.swift in Sources */, - DD52B27DABA4C475B850A326 /* SocketEventHandler.swift in Sources */, - 9432E0101F77F8C4006AF628 /* SSLSecurity.swift in Sources */, - DD52B4223DCCB75630441370 /* SocketIOClientSpec.swift in Sources */, - DD52B6FC2F0A6A3106FFCBE3 /* SocketIOClientOption.swift in Sources */, - DD52B3D941DB2A0C678F8251 /* SocketIOClientStatus.swift in Sources */, - DD52BB6BD8F50D339AD53844 /* SocketIOClientConfiguration.swift in Sources */, - DD52B0C7C017460057CEF1A5 /* SocketTypes.swift in Sources */, - DD52B3C95BFA9E9D9FA30D6D /* SocketLogger.swift in Sources */, - DD52BFF4CC89C83012182B42 /* SocketExtensions.swift in Sources */, - DD52BA7825D2D32C3311BE76 /* SocketStringReader.swift in Sources */, - DD52B099A5166C5FF975FAB5 /* SocketClientManager.swift in Sources */, - DD52BC28EC86700F814CCFAA /* SocketPacket.swift in Sources */, - DD52BC0F60703CB9C3A6F594 /* SocketParsable.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 57634A1B1BD9B46D00E19CD7 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 1C686C011F869EB6007D8627 /* SocketObjectiveCTest.m in Sources */, - 1C686BDA1F869AF9007D8627 /* SocketIOClientConfigurationTest.swift in Sources */, - 1C686BDB1F869AF9007D8627 /* SocketEngineTest.swift in Sources */, - 1C686BDC1F869AF9007D8627 /* SocketSideEffectTest.swift in Sources */, - 1C686BDD1F869AF9007D8627 /* SocketBasicPacketTest.swift in Sources */, - 1C686BDE1F869AF9007D8627 /* SocketAckManagerTest.swift in Sources */, - 1C686BDF1F869AF9007D8627 /* SocketParserTest.swift in Sources */, - 1C686BE01F869AF9007D8627 /* SocketNamespacePacketTest.swift in Sources */, + DD52BCCD25EFA76E0F9B313C /* SocketMangerTest.swift in Sources */, + DD52B53F2609D91A683DFCDD /* ManagerObjectiveCTest.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - 572EF2271B51F16C00EEBB58 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 572EF2181B51F16C00EEBB58 /* SocketIO-iOS */; - targetProxy = 572EF2261B51F16C00EEBB58 /* PBXContainerItemProxy */; - }; 572EF2451B51F18A00EEBB58 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 572EF2371B51F18A00EEBB58 /* SocketIO-Mac */; + target = 572EF2371B51F18A00EEBB58 /* SocketIO */; targetProxy = 572EF2441B51F18A00EEBB58 /* PBXContainerItemProxy */; }; - 57634A3E1BD9B4B800E19CD7 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 576349FA1BD9B46A00E19CD7 /* SocketIO-tvOS */; - targetProxy = 57634A3D1BD9B4B800E19CD7 /* PBXContainerItemProxy */; - }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ @@ -904,6 +534,34 @@ ENABLE_BITCODE = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; + "FRAMEWORK_SEARCH_PATHS[sdk=appletvos*]" = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/tvOS", + ); + "FRAMEWORK_SEARCH_PATHS[sdk=appletvsimulator*]" = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/tvOS", + ); + "FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*]" = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/iOS", + ); + "FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*]" = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/iOS", + ); + "FRAMEWORK_SEARCH_PATHS[sdk=macosx*]" = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/Mac", + ); + "FRAMEWORK_SEARCH_PATHS[sdk=watchos*]" = ( + "$(PROJECT_DIR)/Carthage/Build/watchOS", + "$(inherited)", + ); + "FRAMEWORK_SEARCH_PATHS[sdk=watchsimulator*]" = ( + "$(PROJECT_DIR)/Carthage/Build/watchOS", + "$(inherited)", + ); GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; @@ -916,9 +574,11 @@ MACOSX_DEPLOYMENT_TARGET = 10.10; ONLY_ACTIVE_ARCH = YES; PRODUCT_NAME = SocketIO; + SUPPORTED_PLATFORMS = "macosx appletvsimulator appletvos iphonesimulator iphoneos watchos watchsimulator"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 3.0; TVOS_DEPLOYMENT_TARGET = 9.0; + VALID_ARCHS = "i386 x86_64 armv7 armv7s arm64 armv7k"; WATCHOS_DEPLOYMENT_TARGET = 2.0; }; name = Debug; @@ -945,6 +605,34 @@ CODE_SIGN_IDENTITY = "Developer ID Application"; ENABLE_BITCODE = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; + "FRAMEWORK_SEARCH_PATHS[sdk=appletvos*]" = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/tvOS", + ); + "FRAMEWORK_SEARCH_PATHS[sdk=appletvsimulator*]" = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/tvOS", + ); + "FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*]" = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/iOS", + ); + "FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*]" = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/iOS", + ); + "FRAMEWORK_SEARCH_PATHS[sdk=macosx*]" = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/Mac", + ); + "FRAMEWORK_SEARCH_PATHS[sdk=watchos*]" = ( + "$(PROJECT_DIR)/Carthage/Build/watchOS", + "$(inherited)", + ); + "FRAMEWORK_SEARCH_PATHS[sdk=watchsimulator*]" = ( + "$(PROJECT_DIR)/Carthage/Build/watchOS", + "$(inherited)", + ); GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; @@ -955,232 +643,15 @@ IPHONEOS_DEPLOYMENT_TARGET = 8.0; MACOSX_DEPLOYMENT_TARGET = 10.10; PRODUCT_NAME = SocketIO; + SUPPORTED_PLATFORMS = "macosx appletvsimulator appletvos iphonesimulator iphoneos watchos watchsimulator"; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; SWIFT_VERSION = 3.0; TVOS_DEPLOYMENT_TARGET = 9.0; + VALID_ARCHS = "i386 x86_64 armv7 armv7s arm64 armv7k"; WATCHOS_DEPLOYMENT_TARGET = 2.0; }; name = Release; }; - 572EF22E1B51F16C00EEBB58 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - APPLICATION_EXTENSION_API_ONLY = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "iPhone Developer"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/iOS", - ); - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = "SocketIO-iOS/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - PRODUCT_BUNDLE_IDENTIFIER = io.socket.SocketIOClientSwift; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_INCLUDE_PATHS = $SRCROOT/zlib; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 4.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; - 572EF22F1B51F16C00EEBB58 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - APPLICATION_EXTENSION_API_ONLY = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "iPhone Distribution"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/iOS", - ); - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = "SocketIO-iOS/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MTL_ENABLE_DEBUG_INFO = NO; - PRODUCT_BUNDLE_IDENTIFIER = io.socket.SocketIOClientSwift; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_INCLUDE_PATHS = $SRCROOT/zlib; - SWIFT_VERSION = 4.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; - 572EF2311B51F16C00EEBB58 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(SDKROOT)/Developer/Library/Frameworks", - "$(inherited)", - ); - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = "SocketIO-iOS/Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 8.4; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - PRODUCT_BUNDLE_IDENTIFIER = "io.socket.$(PRODUCT_NAME:rfc1034identifier)"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = iphoneos; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 4.0; - }; - name = Debug; - }; - 572EF2321B51F16C00EEBB58 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(SDKROOT)/Developer/Library/Frameworks", - "$(inherited)", - ); - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = "SocketIO-iOS/Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 8.4; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MTL_ENABLE_DEBUG_INFO = NO; - PRODUCT_BUNDLE_IDENTIFIER = "io.socket.$(PRODUCT_NAME:rfc1034identifier)"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = iphoneos; - SWIFT_VERSION = 4.0; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; 572EF24C1B51F18A00EEBB58 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -1210,10 +681,7 @@ ENABLE_BITCODE = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/Mac", - ); + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; FRAMEWORK_VERSION = A; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; @@ -1229,22 +697,25 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = "SocketIO-Mac/Info.plist"; + INFOPLIST_FILE = SocketIO/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "$(SDKROOT)/usr/lib/system", - ); + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = "$(inherited)"; + MACOSX_DEPLOYMENT_TARGET = 10.10; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; PRODUCT_BUNDLE_IDENTIFIER = "io.socket.$(PRODUCT_NAME:rfc1034identifier)"; SDKROOT = macosx; SKIP_INSTALL = YES; + SUPPORTED_PLATFORMS = "$(inherited)"; SWIFT_INCLUDE_PATHS = ""; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_SWIFT3_OBJC_INFERENCE = Default; SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = "1,2,3,4"; + TVOS_DEPLOYMENT_TARGET = 10.0; + VALID_ARCHS = "$(inherited)"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; @@ -1280,10 +751,7 @@ ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/Mac", - ); + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; FRAMEWORK_VERSION = A; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; @@ -1293,20 +761,23 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = "SocketIO-Mac/Info.plist"; + INFOPLIST_FILE = SocketIO/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "$(SDKROOT)/usr/lib/system", - ); + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = "$(inherited)"; + MACOSX_DEPLOYMENT_TARGET = 10.10; MTL_ENABLE_DEBUG_INFO = NO; PRODUCT_BUNDLE_IDENTIFIER = "io.socket.$(PRODUCT_NAME:rfc1034identifier)"; SDKROOT = macosx; SKIP_INSTALL = YES; + SUPPORTED_PLATFORMS = "$(inherited)"; SWIFT_INCLUDE_PATHS = ""; SWIFT_SWIFT3_OBJC_INFERENCE = Default; SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = "1,2,3,4"; + TVOS_DEPLOYMENT_TARGET = 10.0; + VALID_ARCHS = "$(inherited)"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; @@ -1340,6 +811,26 @@ "$(inherited)", "$(PROJECT_DIR)/Carthage/Build/Mac", ); + "FRAMEWORK_SEARCH_PATHS[sdk=appletvos*]" = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/tvOS", + ); + "FRAMEWORK_SEARCH_PATHS[sdk=appletvsimulator*]" = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/tvOS", + ); + "FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*]" = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/iOS", + ); + "FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*]" = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/iOS", + ); + "FRAMEWORK_SEARCH_PATHS[sdk=macosx*]" = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/Mac", + ); GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; @@ -1355,21 +846,22 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = "SocketIO-Mac/Info.plist"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "$(SDKROOT)/usr/lib/system", - ); + INFOPLIST_FILE = SocketIO/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks @loader_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = "$(inherited)"; MACOSX_DEPLOYMENT_TARGET = 10.10; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; PRODUCT_BUNDLE_IDENTIFIER = "io.socket.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; + SUPPORTED_PLATFORMS = "$(inherited)"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_SWIFT3_OBJC_INFERENCE = Default; SWIFT_VERSION = 4.0; + TVOS_DEPLOYMENT_TARGET = 10.0; + VALID_ARCHS = "$(inherited)"; }; name = Debug; }; @@ -1402,6 +894,26 @@ "$(inherited)", "$(PROJECT_DIR)/Carthage/Build/Mac", ); + "FRAMEWORK_SEARCH_PATHS[sdk=appletvos*]" = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/tvOS", + ); + "FRAMEWORK_SEARCH_PATHS[sdk=appletvsimulator*]" = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/tvOS", + ); + "FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*]" = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/iOS", + ); + "FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*]" = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/iOS", + ); + "FRAMEWORK_SEARCH_PATHS[sdk=macosx*]" = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/Mac", + ); GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; @@ -1410,242 +922,20 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = "SocketIO-Mac/Info.plist"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "$(SDKROOT)/usr/lib/system", - ); + INFOPLIST_FILE = SocketIO/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks @loader_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = "$(inherited)"; MACOSX_DEPLOYMENT_TARGET = 10.10; MTL_ENABLE_DEBUG_INFO = NO; PRODUCT_BUNDLE_IDENTIFIER = "io.socket.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; + SUPPORTED_PLATFORMS = "$(inherited)"; SWIFT_SWIFT3_OBJC_INFERENCE = Default; SWIFT_VERSION = 4.0; - }; - name = Release; - }; - 57634A141BD9B46A00E19CD7 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "iPhone Developer"; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/tvOS", - ); - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = "SocketIO-iOS/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - PRODUCT_BUNDLE_IDENTIFIER = "io.socket.$(PRODUCT_NAME:rfc1034identifier)"; - PRODUCT_NAME = SocketIO; - SDKROOT = appletvos; - SKIP_INSTALL = YES; - SWIFT_INCLUDE_PATHS = $SRCROOT/zlib; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 4.0; - TARGETED_DEVICE_FAMILY = 3; - TVOS_DEPLOYMENT_TARGET = 9.0; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; - 57634A151BD9B46A00E19CD7 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "iPhone Distribution"; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; - COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/tvOS", - ); - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = "SocketIO-iOS/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MTL_ENABLE_DEBUG_INFO = NO; - PRODUCT_BUNDLE_IDENTIFIER = "io.socket.$(PRODUCT_NAME:rfc1034identifier)"; - PRODUCT_NAME = SocketIO; - SDKROOT = appletvos; - SKIP_INSTALL = YES; - SWIFT_INCLUDE_PATHS = $SRCROOT/zlib; - SWIFT_VERSION = 4.0; - TARGETED_DEVICE_FAMILY = 3; - TVOS_DEPLOYMENT_TARGET = 9.0; - VALIDATE_PRODUCT = YES; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; - 57634A391BD9B46D00E19CD7 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(SDKROOT)/Developer/Library/Frameworks", - "$(inherited)", - ); - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = "SocketIO-iOS/Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 8.4; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - PRODUCT_BUNDLE_IDENTIFIER = "io.socket.$(PRODUCT_NAME:rfc1034identifier)"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = appletvos; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 4.0; - }; - name = Debug; - }; - 57634A3A1BD9B46D00E19CD7 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(SDKROOT)/Developer/Library/Frameworks", - "$(inherited)", - ); - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = "SocketIO-iOS/Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 8.4; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MTL_ENABLE_DEBUG_INFO = NO; - PRODUCT_BUNDLE_IDENTIFIER = "io.socket.$(PRODUCT_NAME:rfc1034identifier)"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = appletvos; - SWIFT_VERSION = 4.0; - VALIDATE_PRODUCT = YES; + TVOS_DEPLOYMENT_TARGET = 10.0; + VALID_ARCHS = "$(inherited)"; }; name = Release; }; @@ -1661,25 +951,7 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 572EF22D1B51F16C00EEBB58 /* Build configuration list for PBXNativeTarget "SocketIO-iOS" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 572EF22E1B51F16C00EEBB58 /* Debug */, - 572EF22F1B51F16C00EEBB58 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 572EF2301B51F16C00EEBB58 /* Build configuration list for PBXNativeTarget "SocketIO-iOSTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 572EF2311B51F16C00EEBB58 /* Debug */, - 572EF2321B51F16C00EEBB58 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 572EF24B1B51F18A00EEBB58 /* Build configuration list for PBXNativeTarget "SocketIO-Mac" */ = { + 572EF24B1B51F18A00EEBB58 /* Build configuration list for PBXNativeTarget "SocketIO" */ = { isa = XCConfigurationList; buildConfigurations = ( 572EF24C1B51F18A00EEBB58 /* Debug */, @@ -1688,7 +960,7 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 572EF24E1B51F18A00EEBB58 /* Build configuration list for PBXNativeTarget "SocketIO-MacTests" */ = { + 572EF24E1B51F18A00EEBB58 /* Build configuration list for PBXNativeTarget "SocketIO-Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 572EF24F1B51F18A00EEBB58 /* Debug */, @@ -1697,24 +969,6 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 57634A131BD9B46A00E19CD7 /* Build configuration list for PBXNativeTarget "SocketIO-tvOS" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 57634A141BD9B46A00E19CD7 /* Debug */, - 57634A151BD9B46A00E19CD7 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 57634A381BD9B46D00E19CD7 /* Build configuration list for PBXNativeTarget "SocketIO-tvOSTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 57634A391BD9B46D00E19CD7 /* Debug */, - 57634A3A1BD9B46D00E19CD7 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; /* End XCConfigurationList section */ }; rootObject = 572EF20E1B51F12F00EEBB58 /* Project object */; diff --git a/Socket.IO-Client-Swift.xcodeproj/xcshareddata/xcschemes/SocketIO-iOS.xcscheme b/Socket.IO-Client-Swift.xcodeproj/xcshareddata/xcschemes/SocketIO-iOS.xcscheme deleted file mode 100644 index 34314fe..0000000 --- a/Socket.IO-Client-Swift.xcodeproj/xcshareddata/xcschemes/SocketIO-iOS.xcscheme +++ /dev/null @@ -1,115 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Socket.IO-Client-Swift.xcodeproj/xcshareddata/xcschemes/SocketIO-tvOS.xcscheme b/Socket.IO-Client-Swift.xcodeproj/xcshareddata/xcschemes/SocketIO-tvOS.xcscheme deleted file mode 100644 index 61cbb43..0000000 --- a/Socket.IO-Client-Swift.xcodeproj/xcshareddata/xcschemes/SocketIO-tvOS.xcscheme +++ /dev/null @@ -1,115 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Socket.IO-Client-Swift.xcodeproj/xcshareddata/xcschemes/SocketIO-Mac.xcscheme b/Socket.IO-Client-Swift.xcodeproj/xcshareddata/xcschemes/SocketIO.xcscheme similarity index 91% rename from Socket.IO-Client-Swift.xcodeproj/xcshareddata/xcschemes/SocketIO-Mac.xcscheme rename to Socket.IO-Client-Swift.xcodeproj/xcshareddata/xcschemes/SocketIO.xcscheme index d533f78..74dc491 100644 --- a/Socket.IO-Client-Swift.xcodeproj/xcshareddata/xcschemes/SocketIO-Mac.xcscheme +++ b/Socket.IO-Client-Swift.xcodeproj/xcshareddata/xcschemes/SocketIO.xcscheme @@ -16,7 +16,7 @@ BuildableIdentifier = "primary" BlueprintIdentifier = "572EF2371B51F18A00EEBB58" BuildableName = "SocketIO.framework" - BlueprintName = "SocketIO-Mac" + BlueprintName = "SocketIO" ReferencedContainer = "container:Socket.IO-Client-Swift.xcodeproj"> @@ -29,8 +29,8 @@ @@ -48,8 +48,8 @@ @@ -59,7 +59,7 @@ BuildableIdentifier = "primary" BlueprintIdentifier = "572EF2371B51F18A00EEBB58" BuildableName = "SocketIO.framework" - BlueprintName = "SocketIO-Mac" + BlueprintName = "SocketIO" ReferencedContainer = "container:Socket.IO-Client-Swift.xcodeproj"> @@ -82,7 +82,7 @@ BuildableIdentifier = "primary" BlueprintIdentifier = "572EF2371B51F18A00EEBB58" BuildableName = "SocketIO.framework" - BlueprintName = "SocketIO-Mac" + BlueprintName = "SocketIO" ReferencedContainer = "container:Socket.IO-Client-Swift.xcodeproj"> @@ -100,7 +100,7 @@ BuildableIdentifier = "primary" BlueprintIdentifier = "572EF2371B51F18A00EEBB58" BuildableName = "SocketIO.framework" - BlueprintName = "SocketIO-Mac" + BlueprintName = "SocketIO" ReferencedContainer = "container:Socket.IO-Client-Swift.xcodeproj"> diff --git a/SocketIO-iOS/Info.plist b/SocketIO-iOS/Info.plist deleted file mode 100644 index d3de8ee..0000000 --- a/SocketIO-iOS/Info.plist +++ /dev/null @@ -1,26 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - FMWK - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - $(CURRENT_PROJECT_VERSION) - NSPrincipalClass - - - diff --git a/SocketIO-iOS/SocketIO.h b/SocketIO-iOS/SocketIO.h deleted file mode 100644 index 34db681..0000000 --- a/SocketIO-iOS/SocketIO.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// SocketIO-iOS.h -// SocketIO-iOS -// -// Created by Nacho Soto on 7/11/15. -// -// - -#import - -//! Project version number for SocketIO-iOS. -FOUNDATION_EXPORT double SocketIO_iOSVersionNumber; - -//! Project version string for SocketIO-iOS. -FOUNDATION_EXPORT const unsigned char SocketIO_iOSVersionString[]; - -// In this header, you should import all the public headers of your framework using statements like #import - - diff --git a/SocketIO-Mac/Info.plist b/SocketIO/Info.plist similarity index 100% rename from SocketIO-Mac/Info.plist rename to SocketIO/Info.plist diff --git a/SocketIO-Mac/SocketIO-Mac.h b/SocketIO/SocketIO.h similarity index 92% rename from SocketIO-Mac/SocketIO-Mac.h rename to SocketIO/SocketIO.h index 40afd3d..a189866 100644 --- a/SocketIO-Mac/SocketIO-Mac.h +++ b/SocketIO/SocketIO.h @@ -6,7 +6,7 @@ // // -#import +#import //! Project version number for SocketIO-Mac. FOUNDATION_EXPORT double SocketIO_MacVersionNumber; diff --git a/Source/SocketIO/Ack/SocketAckEmitter.swift b/Source/SocketIO/Ack/SocketAckEmitter.swift index 5776289..db8cecf 100644 --- a/Source/SocketIO/Ack/SocketAckEmitter.swift +++ b/Source/SocketIO/Ack/SocketAckEmitter.swift @@ -120,8 +120,10 @@ public final class OnAckCallback : NSObject { guard seconds != 0 else { return } - socket.handleQueue.asyncAfter(deadline: DispatchTime.now() + seconds) { - socket.ackHandlers.timeoutAck(self.ackNumber, onQueue: socket.handleQueue) + socket.manager?.handleQueue.asyncAfter(deadline: DispatchTime.now() + seconds) {[weak socket] in + guard let socket = socket, let manager = socket.manager else { return } + + socket.ackHandlers.timeoutAck(self.ackNumber, onQueue: manager.handleQueue) } } diff --git a/Source/SocketIO/Client/SocketIOClient.swift b/Source/SocketIO/Client/SocketIOClient.swift index 6acb536..acc8ad0 100644 --- a/Source/SocketIO/Client/SocketIOClient.swift +++ b/Source/SocketIO/Client/SocketIOClient.swift @@ -25,108 +25,52 @@ import Dispatch import Foundation -/// The main class for SocketIOClientSwift. +/// Represents a socket.io-client. /// -/// **NOTE**: The client is not thread/queue safe, all interaction with the socket should be done on the `handleQueue` +/// Clients are created through a `SocketManager`, which owns the `SocketEngineSpec` that controls the connection to the server. /// -/// Represents a socket.io-client. Most interaction with socket.io will be through this class. -open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, SocketParsable { +/// For example: +/// +/// ```swift +/// // Create a socket for the /swift namespace +/// let socket = manager.socket(forNamespace: "/swift") +/// +/// // Add some handlers and connect +/// ``` +/// +/// **NOTE**: The client is not thread/queue safe, all interaction with the socket should be done on the `manager.handleQueue` +/// +open class SocketIOClient : NSObject, SocketIOClientSpec { // MARK: Properties - private static let logType = "SocketIOClient" - - /// If `true` then every time `connect` is called, a new engine will be created. - @objc - public var forceNew = false - - /// The queue that all interaction with the client should occur on. This is the queue that event handlers are - /// called on. - @objc - public var handleQueue = DispatchQueue.main - /// The namespace that this socket is currently connected to. /// /// **Must** start with a `/`. @objc - public var nsp = "/" - - /// The configuration for this client. - /// - /// **This cannot be set after calling one of the connect methods**. - public var config: SocketIOClientConfiguration { - get { - return _config - } - - set { - guard status == .notConnected else { - DefaultSocketLogger.Logger.error("Tried setting config after calling connect", - type: SocketIOClient.logType) - return - } - - _config = newValue - - if socketURL.absoluteString.hasPrefix("https://") { - _config.insert(.secure(true)) - } - - _config.insert(.path("/socket.io/"), replacing: false) - setConfigs() - } - } - - /// If `true`, this client will try and reconnect on any disconnects. - @objc - public var reconnects = true - - /// The number of seconds to wait before attempting to reconnect. - @objc - public var reconnectWait = 10 + public let nsp: String /// The session id of this client. @objc - public var sid: String? { - return engine?.sid + public var sid: String { + guard let engine = manager?.engine else { return "" } + + return nsp == "/" ? engine.sid : "\(nsp)#\(engine.sid)" } - /// The URL of the socket.io server. - /// - /// If changed after calling `init`, `forceNew` must be set to `true`, or it will only connect to the url set in the - /// init. - @objc - public var socketURL: URL - - /// A list of packets that are waiting for binary data. - /// - /// The way that socket.io works all data should be sent directly after each packet. - /// So this should ideally be an array of one packet waiting for data. - /// - /// **This should not be modified directly.** - public var waitingPackets = [SocketPacket]() - /// A handler that will be called on any event. public private(set) var anyHandler: ((SocketAnyEvent) -> ())? - /// The engine for this client. - @objc - public internal(set) var engine: SocketEngineSpec? - /// The array of handlers for this socket. public private(set) var handlers = [SocketEventHandler]() + /// The manager for this socket. + @objc + public private(set) weak var manager: SocketManagerSpec? + /// The status of this client. @objc - public private(set) var status = SocketIOClientStatus.notConnected { + public private(set) var status = SocketIOStatus.notConnected { didSet { - switch status { - case .connected: - reconnecting = false - currentReconnectAttempt = 0 - default: - break - } - handleClientEvent(.statusChange, data: [status]) } } @@ -134,60 +78,29 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So var ackHandlers = SocketAckManager() private(set) var currentAck = -1 - private(set) var reconnectAttempts = -1 - private var _config: SocketIOClientConfiguration - private var currentReconnectAttempt = 0 - private var reconnecting = false + private lazy var logType = "SocketIOClient{\(nsp)}" // MARK: Initializers /// Type safe way to create a new SocketIOClient. `opts` can be omitted. /// + /// - parameter manager: The manager for this socket. /// - parameter socketURL: The url of the socket.io server. - /// - parameter config: The config for this socket. - public init(socketURL: URL, config: SocketIOClientConfiguration = []) { - self._config = config - self.socketURL = socketURL - - if socketURL.absoluteString.hasPrefix("https://") { - self._config.insert(.secure(true)) - } - - self._config.insert(.path("/socket.io/"), replacing: false) + @objc + public init(manager: SocketManagerSpec, nsp: String) { + self.manager = manager + self.nsp = nsp super.init() - - setConfigs() - } - - /// Not so type safe way to create a SocketIOClient, meant for Objective-C compatiblity. - /// If using Swift it's recommended to use `init(socketURL: NSURL, options: Set)` - /// - /// - parameter socketURL: The url of the socket.io server. - /// - parameter config: The config for this socket. - @objc - public convenience init(socketURL: NSURL, config: NSDictionary?) { - self.init(socketURL: socketURL as URL, config: config?.toSocketConfiguration() ?? []) } deinit { - DefaultSocketLogger.Logger.log("Client is being released", type: SocketIOClient.logType) - engine?.disconnect(reason: "Client Deinit") + DefaultSocketLogger.Logger.log("Client is being released", type: logType) } // MARK: Methods - private func addEngine() { - DefaultSocketLogger.Logger.log("Adding engine", type: SocketIOClient.logType) - - engine?.engineQueue.sync { - self.engine?.client = nil - } - - engine = SocketEngine(client: self, url: socketURL, config: config) - } - /// Connect to the server. The same as calling `connect(timeoutAfter:withHandler:)` with a timeout of 0. /// /// Only call after adding your event listeners, unless you know what you're doing. @@ -207,27 +120,22 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So open func connect(timeoutAfter: Double, withHandler handler: (() -> ())?) { assert(timeoutAfter >= 0, "Invalid timeout: \(timeoutAfter)") - guard status != .connected else { - DefaultSocketLogger.Logger.log("Tried connecting on an already connected socket", - type: SocketIOClient.logType) + guard let manager = self.manager, status != .connected else { + DefaultSocketLogger.Logger.log("Tried connecting on an already connected socket", type: logType) return } status = .connecting - if engine == nil || forceNew { - addEngine() - } - - engine?.connect() + manager.connectSocket(self) guard timeoutAfter != 0 else { return } - handleQueue.asyncAfter(deadline: DispatchTime.now() + timeoutAfter) {[weak self] in + manager.handleQueue.asyncAfter(deadline: DispatchTime.now() + timeoutAfter) {[weak self] in guard let this = self, this.status == .connecting || this.status == .notConnected else { return } this.status = .disconnected - this.engine?.disconnect(reason: "Connect timeout") + this.leaveNamespace() handler?() } @@ -246,7 +154,7 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So open func didConnect(toNamespace namespace: String) { guard status != .connected else { return } - DefaultSocketLogger.Logger.log("Socket connected", type: SocketIOClient.logType) + DefaultSocketLogger.Logger.log("Socket connected", type: logType) status = .connected @@ -259,21 +167,22 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So open func didDisconnect(reason: String) { guard status != .disconnected else { return } - DefaultSocketLogger.Logger.log("Disconnected: \(reason)", type: SocketIOClient.logType) + DefaultSocketLogger.Logger.log("Disconnected: \(reason)", type: logType) - reconnecting = false status = .disconnected - // Make sure the engine is actually dead. - engine?.disconnect(reason: reason) handleClientEvent(.disconnect, data: [reason]) } /// Disconnects the socket. + /// + /// This will cause the socket to leave the namespace it is associated to, as well as remove itself from the + /// `manager`. @objc open func disconnect() { - DefaultSocketLogger.Logger.log("Closing socket", type: SocketIOClient.logType) + DefaultSocketLogger.Logger.log("Closing socket", type: logType) + leaveNamespace() didDisconnect(reason: "Disconnect") } @@ -289,7 +198,7 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So try emit(event, with: items.map({ try $0.socketRepresentation() })) } catch let err { DefaultSocketLogger.Logger.error("Error creating socketRepresentation for emit: \(event), \(items)", - type: SocketIOClient.logType) + type: logType) handleClientEvent(.error, data: [event, items, err]) } @@ -333,7 +242,7 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So return emitWithAck(event, with: try items.map({ try $0.socketRepresentation() })) } catch let err { DefaultSocketLogger.Logger.error("Error creating socketRepresentation for emit: \(event), \(items)", - type: SocketIOClient.logType) + type: logType) handleClientEvent(.error, data: [event, items, err]) @@ -371,9 +280,9 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So let packet = SocketPacket.packetFromEmit(data, id: ack ?? -1, nsp: nsp, ack: false) let str = packet.packetString - DefaultSocketLogger.Logger.log("Emitting: \(str)", type: SocketIOClient.logType) + DefaultSocketLogger.Logger.log("Emitting: \(str)", type: logType) - engine?.send(str, withData: packet.binary) + manager?.engine?.send(str, withData: packet.binary) } /// Call when you wish to tell the server that you've received the event for `ack`. @@ -388,69 +297,9 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So let packet = SocketPacket.packetFromEmit(items, id: ack, nsp: nsp, ack: true) let str = packet.packetString - DefaultSocketLogger.Logger.log("Emitting Ack: \(str)", type: SocketIOClient.logType) + DefaultSocketLogger.Logger.log("Emitting Ack: \(str)", type: logType) - engine?.send(str, withData: packet.binary) - } - - /// Called when the engine closes. - /// - /// - parameter reason: The reason that the engine closed. - open func engineDidClose(reason: String) { - handleQueue.async { - self._engineDidClose(reason: reason) - } - } - - private func _engineDidClose(reason: String) { - waitingPackets.removeAll() - - if status != .disconnected { - status = .notConnected - } - - if status == .disconnected || !reconnects { - didDisconnect(reason: reason) - } else if !reconnecting { - reconnecting = true - tryReconnect(reason: reason) - } - } - - /// Called when the engine errors. - /// - /// - parameter reason: The reason the engine errored. - open func engineDidError(reason: String) { - handleQueue.async { - self._engineDidError(reason: reason) - } - } - - private func _engineDidError(reason: String) { - DefaultSocketLogger.Logger.error("\(reason)", type: SocketIOClient.logType) - - handleClientEvent(.error, data: [reason]) - } - - /// Called when the engine opens. - /// - /// - parameter reason: The reason the engine opened. - open func engineDidOpen(reason: String) { - handleQueue.async { - self._engineDidOpen(reason: reason) - } - } - - private func _engineDidOpen(reason: String) { - DefaultSocketLogger.Logger.log("Engine opened \(reason)", type: SocketIOClient.logType) - - guard nsp != "/" else { - didConnect(toNamespace: "/") - - return - } - - joinNamespace(nsp) + manager?.engine?.send(str, withData: packet.binary) } /// Called when socket.io has acked one of our emits. Causes the corresponding ack callback to be called. @@ -459,11 +308,19 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So /// - parameter data: The data sent back with this ack. @objc open func handleAck(_ ack: Int, data: [Any]) { - guard status == .connected else { return } + guard status == .connected, let manager = self.manager else { return } - DefaultSocketLogger.Logger.log("Handling ack: \(ack) with data: \(data)", type: SocketIOClient.logType) + DefaultSocketLogger.Logger.log("Handling ack: \(ack) with data: \(data)", type: logType) - ackHandlers.executeAck(ack, with: data, onQueue: handleQueue) + ackHandlers.executeAck(ack, with: data, onQueue: manager.handleQueue) + } + + /// Called on socket.io specific events. + /// + /// - parameter event: The `SocketClientEvent`. + /// - parameter data: The data for this event. + open func handleClientEvent(_ event: SocketClientEvent, data: [Any]) { + handleEvent(event.rawValue, data: data, isInternalMessage: true) } /// Called when we get an event from socket.io. @@ -476,7 +333,7 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So open func handleEvent(_ event: String, data: [Any], isInternalMessage: Bool, withAck ack: Int = -1) { guard status == .connected || isInternalMessage else { return } - DefaultSocketLogger.Logger.log("Handling event: \(event) with data: \(data)", type: SocketIOClient.logType) + DefaultSocketLogger.Logger.log("Handling event: \(event) with data: \(data)", type: logType) anyHandler?(SocketAnyEvent(event: event, items: data)) @@ -485,36 +342,45 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So } } - /// Called on socket.io specific events. + /// Causes a client to handle a socket.io packet. The namespace for the packet must match the namespace of the + /// socket. /// - /// - parameter event: The `SocketClientEvent`. - /// - parameter data: The data for this event. - open func handleClientEvent(_ event: SocketClientEvent, data: [Any]) { - handleEvent(event.rawValue, data: data, isInternalMessage: true) + /// - parameter packet: The packet to handle. + open func handlePacket(_ packet: SocketPacket) { + guard packet.nsp == nsp else { return } + + switch packet.type { + case .event, .binaryEvent: + handleEvent(packet.event, data: packet.args, isInternalMessage: false, withAck: packet.id) + case .ack, .binaryAck: + handleAck(packet.id, data: packet.data) + case .connect: + didConnect(toNamespace: nsp) + case .disconnect: + didDisconnect(reason: "Got Disconnect") + case .error: + handleEvent("error", data: packet.data, isInternalMessage: true, withAck: packet.id) + } } - /// Call when you wish to leave a namespace and return to the default namespace. + /// Call when you wish to leave a namespace and disconnect this socket. @objc open func leaveNamespace() { guard nsp != "/" else { return } - engine?.send("1\(nsp)", withData: []) - nsp = "/" + status = .disconnected + + manager?.disconnectSocket(self) } - /// Joins `namespace`. - /// - /// **Do not use this to join the default namespace.** Instead call `leaveNamespace`. - /// - /// - parameter namespace: The namespace to join. + /// Joins `nsp`. @objc - open func joinNamespace(_ namespace: String) { - guard namespace != "/" else { return } + open func joinNamespace() { + guard nsp != "/" else { return } - DefaultSocketLogger.Logger.log("Joining namespace \(namespace)", type: SocketIOClient.logType) + DefaultSocketLogger.Logger.log("Joining namespace \(nsp)", type: logType) - nsp = namespace - engine?.send("0\(nsp)", withData: []) + manager?.engine?.send("0\(nsp)", withData: []) } /// Removes handler(s) for a client event. @@ -533,7 +399,7 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So /// - parameter event: The event to remove handlers for. @objc open func off(_ event: String) { - DefaultSocketLogger.Logger.log("Removing handler for event: \(event)", type: SocketIOClient.logType) + DefaultSocketLogger.Logger.log("Removing handler for event: \(event)", type: logType) handlers = handlers.filter({ $0.event != event }) } @@ -545,7 +411,7 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So /// - parameter id: The UUID of the handler you wish to remove. @objc open func off(id: UUID) { - DefaultSocketLogger.Logger.log("Removing handler with id: \(id)", type: SocketIOClient.logType) + DefaultSocketLogger.Logger.log("Removing handler with id: \(id)", type: logType) handlers = handlers.filter({ $0.id != id }) } @@ -558,7 +424,7 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So @objc @discardableResult open func on(_ event: String, callback: @escaping NormalCallback) -> UUID { - DefaultSocketLogger.Logger.log("Adding handler for event: \(event)", type: SocketIOClient.logType) + DefaultSocketLogger.Logger.log("Adding handler for event: \(event)", type: logType) let handler = SocketEventHandler(event: event, id: UUID(), callback: callback) handlers.append(handler) @@ -581,12 +447,7 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So /// - returns: A unique id for the handler that can be used to remove it. @discardableResult open func on(clientEvent event: SocketClientEvent, callback: @escaping NormalCallback) -> UUID { - DefaultSocketLogger.Logger.log("Adding handler for event: \(event)", type: SocketIOClient.logType) - - let handler = SocketEventHandler(event: event.rawValue, id: UUID(), callback: callback) - handlers.append(handler) - - return handler.id + return on(event.rawValue, callback: callback) } /// Adds a single-use handler for a client event. @@ -607,7 +468,7 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So @objc @discardableResult open func once(_ event: String, callback: @escaping NormalCallback) -> UUID { - DefaultSocketLogger.Logger.log("Adding once handler for event: \(event)", type: SocketIOClient.logType) + DefaultSocketLogger.Logger.log("Adding once handler for event: \(event)", type: logType) let id = UUID() @@ -630,31 +491,10 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So anyHandler = handler } - /// Called when the engine has a message that must be parsed. - /// - /// - parameter msg: The message that needs parsing. - public func parseEngineMessage(_ msg: String) { - DefaultSocketLogger.Logger.log("Should parse message: \(msg)", type: SocketIOClient.logType) - - handleQueue.async { self.parseSocketMessage(msg) } - } - - /// Called when the engine receives binary data. - /// - /// - parameter data: The data the engine received. - public func parseEngineBinaryData(_ data: Data) { - handleQueue.async { self.parseBinaryData(data) } - } - /// Tries to reconnect to the server. - /// - /// This will cause a `disconnect` event to be emitted, as well as an `reconnectAttempt` event. @objc - open func reconnect() { - guard !reconnecting else { return } - - engine?.disconnect(reason: "manual reconnect") - } + @available(*, unavailable, message: "Call the manager's reconnect method") + open func reconnect() { } /// Removes all handlers. /// @@ -664,54 +504,15 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So handlers.removeAll(keepingCapacity: false) } - private func tryReconnect(reason: String) { - guard reconnecting else { return } + /// Puts the socket back into the connecting state. + /// Called when the manager detects a broken connection, or when a manual reconnect is triggered. + /// + /// - parameter reason: The reason this socket is reconnecting. + @objc + open func setReconnecting(reason: String) { + status = .connecting - DefaultSocketLogger.Logger.log("Starting reconnect", type: SocketIOClient.logType) handleClientEvent(.reconnect, data: [reason]) - - _tryReconnect() - } - - private func _tryReconnect() { - guard reconnects && reconnecting && status != .disconnected else { return } - - if reconnectAttempts != -1 && currentReconnectAttempt + 1 > reconnectAttempts { - return didDisconnect(reason: "Reconnect Failed") - } - - DefaultSocketLogger.Logger.log("Trying to reconnect", type: SocketIOClient.logType) - handleClientEvent(.reconnectAttempt, data: [(reconnectAttempts - currentReconnectAttempt)]) - - currentReconnectAttempt += 1 - connect() - - handleQueue.asyncAfter(deadline: DispatchTime.now() + Double(reconnectWait), execute: _tryReconnect) - } - - private func setConfigs() { - for option in config { - switch option { - case let .reconnects(reconnects): - self.reconnects = reconnects - case let .reconnectAttempts(attempts): - reconnectAttempts = attempts - case let .reconnectWait(wait): - reconnectWait = abs(wait) - case let .nsp(nsp): - self.nsp = nsp - case let .log(log): - DefaultSocketLogger.Logger.log = log - case let .logger(logger): - DefaultSocketLogger.Logger = logger - case let .handleQueue(queue): - handleQueue = queue - case let .forceNew(force): - forceNew = force - default: - continue - } - } } // Test properties @@ -724,14 +525,10 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So status = .connected } - func setTestStatus(_ status: SocketIOClientStatus) { + func setTestStatus(_ status: SocketIOStatus) { self.status = status } - func setTestEngine(_ engine: SocketEngineSpec?) { - self.engine = engine - } - func emitTest(event: String, _ data: Any...) { emit([event] + data) } diff --git a/Source/SocketIO/Client/SocketIOClientConfiguration.swift b/Source/SocketIO/Client/SocketIOClientConfiguration.swift index 290dd5b..97f6d91 100644 --- a/Source/SocketIO/Client/SocketIOClientConfiguration.swift +++ b/Source/SocketIO/Client/SocketIOClientConfiguration.swift @@ -125,5 +125,12 @@ public struct SocketIOClientConfiguration : ExpressibleByArrayLiteral, Collectio backingArray.append(element) } - +} + +/// Declares that a type can set configs from a `SocketIOClientConfiguration`. +public protocol ConfigSettable { + /// Called when an `ConfigSettable` should set/update its configs from a given configuration. + /// + /// - parameter config: The `SocketIOClientConfiguration` that should be used to set/update configs. + mutating func setConfigs(_ config: SocketIOClientConfiguration) } diff --git a/Source/SocketIO/Client/SocketIOClientOption.swift b/Source/SocketIO/Client/SocketIOClientOption.swift index 10b521e..3e9114f 100644 --- a/Source/SocketIO/Client/SocketIOClientOption.swift +++ b/Source/SocketIO/Client/SocketIOClientOption.swift @@ -40,10 +40,6 @@ public enum SocketIOClientOption : ClientOption { /// An array of cookies that will be sent during the initial connection. case cookies([HTTPCookie]) - /// Deprecated - @available(*, deprecated, message: "No longer needed in socket.io 2.0+") - case doubleEncodeUTF8(Bool) - /// Any extra HTTP headers that should be sent during the initial connection. case extraHeaders([String: String]) @@ -67,10 +63,6 @@ public enum SocketIOClientOption : ClientOption { /// Used to pass in a custom logger. case logger(SocketLogger) - /// The namespace that this client should connect to. Can be changed during use using the `joinNamespace` - /// and `leaveNamespace` methods on `SocketIOClient`. - case nsp(String) - /// A custom path to socket.io. Only use this if the socket.io server is configured to look for this path. case path(String) @@ -96,11 +88,6 @@ public enum SocketIOClientOption : ClientOption { /// Sets an NSURLSessionDelegate for the underlying engine. Useful if you need to handle self-signed certs. case sessionDelegate(URLSessionDelegate) - /// If passed `true`, the WebSocket transport will try and use voip logic to keep network connections open in - /// the background. **This option is experimental as socket.io shouldn't be used for background communication.** - @available(*, deprecated, message: "No longer has any effect, and will be removed in v11.0") - case voipEnabled(Bool) - // MARK: Properties /// The description of this option. @@ -114,8 +101,6 @@ public enum SocketIOClientOption : ClientOption { description = "connectParams" case .cookies: description = "cookies" - case .doubleEncodeUTF8: - description = "doubleEncodeUTF8" case .extraHeaders: description = "extraHeaders" case .forceNew: @@ -130,8 +115,6 @@ public enum SocketIOClientOption : ClientOption { description = "log" case .logger: description = "logger" - case .nsp: - description = "nsp" case .path: description = "path" case .reconnects: @@ -148,8 +131,6 @@ public enum SocketIOClientOption : ClientOption { description = "security" case .sessionDelegate: description = "sessionDelegate" - case .voipEnabled: - description = "voipEnabled" } return description @@ -165,8 +146,6 @@ public enum SocketIOClientOption : ClientOption { value = params case let .cookies(cookies): value = cookies - case let .doubleEncodeUTF8(encode): - value = encode case let .extraHeaders(headers): value = headers case let .forceNew(force): @@ -181,8 +160,6 @@ public enum SocketIOClientOption : ClientOption { value = log case let .logger(logger): value = logger - case let .nsp(nsp): - value = nsp case let .path(path): value = path case let .reconnects(reconnects): @@ -199,8 +176,6 @@ public enum SocketIOClientOption : ClientOption { value = signed case let .sessionDelegate(delegate): value = delegate - case let .voipEnabled(enabled): - value = enabled } return value diff --git a/Source/SocketIO/Client/SocketIOClientSpec.swift b/Source/SocketIO/Client/SocketIOClientSpec.swift index 0616a6e..26e8e60 100644 --- a/Source/SocketIO/Client/SocketIOClientSpec.swift +++ b/Source/SocketIO/Client/SocketIOClientSpec.swift @@ -32,22 +32,19 @@ public protocol SocketIOClientSpec : class { /// A handler that will be called on any event. var anyHandler: ((SocketAnyEvent) -> ())? { get } - /// The configuration for this client. - var config: SocketIOClientConfiguration { get set } - - /// The queue that all interaction with the client must be on. - var handleQueue: DispatchQueue { get set } - /// The array of handlers for this socket. var handlers: [SocketEventHandler] { get } + /// The manager for this socket. + var manager: SocketManagerSpec? { get } + /// The namespace that this socket is currently connected to. /// /// **Must** start with a `/`. - var nsp: String { get set } + var nsp: String { get } /// The status of this client. - var status: SocketIOClientStatus { get } + var status: SocketIOStatus { get } // MARK: Methods @@ -126,6 +123,12 @@ public protocol SocketIOClientSpec : class { /// - parameter data: The data sent back with this ack. func handleAck(_ ack: Int, data: [Any]) + /// Called on socket.io specific events. + /// + /// - parameter event: The `SocketClientEvent`. + /// - parameter data: The data for this event. + func handleClientEvent(_ event: SocketClientEvent, data: [Any]) + /// Called when we get an event from socket.io. /// /// - parameter event: The name of the event. @@ -134,21 +137,17 @@ public protocol SocketIOClientSpec : class { /// - parameter withAck: If > 0 then this event expects to get an ack back from the client. func handleEvent(_ event: String, data: [Any], isInternalMessage: Bool, withAck ack: Int) - /// Called on socket.io specific events. + /// Causes a client to handle a socket.io packet. The namespace for the packet must match the namespace of the + /// socket. /// - /// - parameter event: The `SocketClientEvent`. - /// - parameter data: The data for this event. - func handleClientEvent(_ event: SocketClientEvent, data: [Any]) + /// - parameter packet: The packet to handle. + func handlePacket(_ packet: SocketPacket) - /// Call when you wish to leave a namespace and return to the default namespace. + /// Call when you wish to leave a namespace and disconnect this socket. func leaveNamespace() - /// Joins `namespace`. - /// - /// **Do not use this to join the default namespace.** Instead call `leaveNamespace`. - /// - /// - parameter namespace: The namespace to join. - func joinNamespace(_ namespace: String) + /// Joins `nsp`. + func joinNamespace() /// Removes handler(s) for a client event. /// @@ -212,13 +211,16 @@ public protocol SocketIOClientSpec : class { /// - parameter handler: The callback that will execute whenever an event is received. func onAny(_ handler: @escaping (SocketAnyEvent) -> ()) - /// Tries to reconnect to the server. - func reconnect() - /// Removes all handlers. /// /// Can be used after disconnecting to break any potential remaining retain cycles. func removeAllHandlers() + + /// Puts the socket back into the connecting state. + /// Called when the manager detects a broken connection, or when a manual reconnect is triggered. + /// + /// parameter reason: The reason this socket is going reconnecting. + func setReconnecting(reason: String) } public extension SocketIOClientSpec { @@ -245,18 +247,80 @@ public enum SocketClientEvent : String { /// ``` case connect - /// Called when the socket has disconnected and will not attempt to try to reconnect. + /// Emitted when the socket has disconnected and will not attempt to try to reconnect. + /// + /// Usage: + /// + /// ```swift + /// socket.on(clientEvent: .disconnect) {data, ack in + /// // Some cleanup logic + /// } + /// ``` case disconnect - /// Called when an error occurs. + /// Emitted when an error occurs. + /// + /// Usage: + /// + /// ```swift + /// socket.on(clientEvent: .error) {data, ack in + /// // Some logging + /// } + /// ``` case error - /// Called when the client begins the reconnection process. + /// Emitted whenever the engine sends a ping. + /// + /// Usage: + /// + /// ```swift + /// socket.on(clientEvent: .ping) {_, _ in + /// // Maybe keep track of latency? + /// } + /// ``` + case ping + + /// Emitted whenever the engine gets a pong. + /// + /// Usage: + /// + /// ```swift + /// socket.on(clientEvent: .pong) {_, _ in + /// // Maybe keep track of latency? + /// } + /// ``` + case pong + + /// Emitted when the client begins the reconnection process. + /// + /// Usage: + /// + /// ```swift + /// socket.on(clientEvent: .reconnect) {data, ack in + /// // Some reconnect event logic + /// } + /// ``` case reconnect - /// Called each time the client tries to reconnect to the server. + /// Emitted each time the client tries to reconnect to the server. + /// + /// Usage: + /// + /// ```swift + /// socket.on(clientEvent: .reconnectAttempt) {data, ack in + /// // Some reconnect attempt logging + /// } + /// ``` case reconnectAttempt - /// Called every time there is a change in the client's status. + /// Emitted every time there is a change in the client's status. + /// + /// Usage: + /// + /// ```swift + /// socket.on(clientEvent: .statusChange) {data, ack in + /// // Some status changing logging + /// } + /// ``` case statusChange } diff --git a/Source/SocketIO/Client/SocketIOClientStatus.swift b/Source/SocketIO/Client/SocketIOStatus.swift similarity index 58% rename from Source/SocketIO/Client/SocketIOClientStatus.swift rename to Source/SocketIO/Client/SocketIOStatus.swift index 8caacbc..4f298a2 100644 --- a/Source/SocketIO/Client/SocketIOClientStatus.swift +++ b/Source/SocketIO/Client/SocketIOStatus.swift @@ -1,5 +1,5 @@ // -// SocketIOClientStatus.swift +// SocketIOStatus.swift // Socket.IO-Client-Swift // // Created by Erik Little on 8/14/15. @@ -24,17 +24,36 @@ import Foundation -/// Represents the state of the client. -@objc public enum SocketIOClientStatus : Int { - /// The client has never been connected. Or the client has been reset. +/// Represents state of a manager or client. +@objc +public enum SocketIOStatus : Int, CustomStringConvertible { + // MARK: Cases + + /// The client/manager has never been connected. Or the client has been reset. case notConnected - /// The client was once connected, but not anymore. + /// The client/manager was once connected, but not anymore. case disconnected - /// The client is in the process of connecting. + /// The client/manager is in the process of connecting. case connecting - /// The client is currently connected. + /// The client/manager is currently connected. case connected + + // MARK: Properties + + /// - returns: True if this client/manager is connected/connecting to a server. + public var active: Bool { + return self == .connected || self == .connecting + } + + public var description: String { + switch self { + case .connected: return "connected" + case .connecting: return "connecting" + case .disconnected: return "disconnected" + case .notConnected: return "notConnected" + } + } } diff --git a/Source/SocketIO/Engine/SocketEngine.swift b/Source/SocketIO/Engine/SocketEngine.swift index 13f36d6..ead8671 100644 --- a/Source/SocketIO/Engine/SocketEngine.swift +++ b/Source/SocketIO/Engine/SocketEngine.swift @@ -28,7 +28,8 @@ import Starscream /// The class that handles the engine.io protocol and transports. /// See `SocketEnginePollable` and `SocketEngineWebsocket` for transport specific methods. -public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePollable, SocketEngineWebsocket { +public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePollable, SocketEngineWebsocket, + ConfigSettable { // MARK: Properties private static let logType = "SocketEngine" @@ -147,41 +148,11 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll public init(client: SocketEngineClient, url: URL, config: SocketIOClientConfiguration) { self.client = client self.url = url - for option in config { - switch option { - case let .connectParams(params): - connectParams = params - case let .cookies(cookies): - self.cookies = cookies - case let .extraHeaders(headers): - extraHeaders = headers - case let .sessionDelegate(delegate): - sessionDelegate = delegate - case let .forcePolling(force): - forcePolling = force - case let .forceWebsockets(force): - forceWebsockets = force - case let .path(path): - socketPath = path - - if !socketPath.hasSuffix("/") { - socketPath += "/" - } - case let .secure(secure): - self.secure = secure - case let .selfSigned(selfSigned): - self.selfSigned = selfSigned - case let .security(security): - self.security = security - case .compress: - self.compress = true - default: - continue - } - } super.init() + setConfigs(config) + sessionDelegate = sessionDelegate ?? self (urlPolling, urlWebSocket) = createURLs() @@ -192,7 +163,7 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll /// - parameter client: The client for this engine. /// - parameter url: The url for this engine. /// - parameter options: The options for this engine. - public convenience init(client: SocketEngineClient, url: URL, options: NSDictionary?) { + public convenience init(client: SocketEngineClient, url: URL, options: [String: Any]?) { self.init(client: client, url: url, config: options?.toSocketConfiguration() ?? []) } @@ -310,22 +281,22 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll private func createWebSocketAndConnect() { ws?.delegate = nil // TODO this seems a bit defensive, is this really needed? - ws = WebSocket(url: urlWebSocketWithSid) + var req = URLRequest(url: urlWebSocketWithSid) if cookies != nil { let headers = HTTPCookie.requestHeaderFields(with: cookies!) - for (key, value) in headers { - ws?.headers[key] = value + for (headerName, value) in headers { + req.setValue(value, forHTTPHeaderField: headerName) } } if extraHeaders != nil { for (headerName, value) in extraHeaders! { - ws?.headers[headerName] = value + req.setValue(value, forHTTPHeaderField: headerName) } } - + ws = WebSocket(request: req) ws?.callbackQueue = engineQueue ws?.enableCompression = compress ws?.delegate = self @@ -485,6 +456,8 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll if message == "3probe" { upgradeTransport() } + + client?.engineDidReceivePong() } /// Parses raw binary received from engine.io. @@ -569,6 +542,46 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll this.sendPing() } + + client?.engineDidSendPing() + } + + /// Called when the engine should set/update its configs from a given configuration. + /// + /// parameter config: The `SocketIOClientConfiguration` that should be used to set/update configs. + open func setConfigs(_ config: SocketIOClientConfiguration) { + for option in config { + switch option { + case let .connectParams(params): + connectParams = params + case let .cookies(cookies): + self.cookies = cookies + case let .extraHeaders(headers): + extraHeaders = headers + case let .sessionDelegate(delegate): + sessionDelegate = delegate + case let .forcePolling(force): + forcePolling = force + case let .forceWebsockets(force): + forceWebsockets = force + case let .path(path): + socketPath = path + + if !socketPath.hasSuffix("/") { + socketPath += "/" + } + case let .secure(secure): + self.secure = secure + case let .selfSigned(selfSigned): + self.selfSigned = selfSigned + case let .security(security): + self.security = security + case .compress: + self.compress = true + default: + continue + } + } } // Moves from long-polling to websockets @@ -608,7 +621,7 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll // MARK: Starscream delegate conformance /// Delegate method for connection. - public func websocketDidConnect(socket: WebSocket) { + public func websocketDidConnect(socket: WebSocketClient) { if !forceWebsockets { probing = true probeWebSocket() @@ -620,7 +633,7 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll } /// Delegate method for disconnection. - public func websocketDidDisconnect(socket: WebSocket, error: NSError?) { + public func websocketDidDisconnect(socket: WebSocketClient, error: Error?) { probing = false if closed { @@ -644,6 +657,12 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll client?.engineDidClose(reason: "Socket Disconnected") } } + + // Test Properties + + func setConnected(_ value: Bool) { + connected = value + } } extension SocketEngine { diff --git a/Source/SocketIO/Engine/SocketEngineClient.swift b/Source/SocketIO/Engine/SocketEngineClient.swift index dc2692c..eefc2ac 100644 --- a/Source/SocketIO/Engine/SocketEngineClient.swift +++ b/Source/SocketIO/Engine/SocketEngineClient.swift @@ -44,6 +44,12 @@ import Foundation /// - parameter reason: The reason the engine opened. func engineDidOpen(reason: String) + /// Called when the engine receives a pong message. + func engineDidReceivePong() + + /// Called when the engine sends a ping to the server. + func engineDidSendPing() + /// Called when the engine has a message that must be parsed. /// /// - parameter msg: The message that needs parsing. diff --git a/Source/SocketIO/Engine/SocketEngineSpec.swift b/Source/SocketIO/Engine/SocketEngineSpec.swift index 4dba805..76db405 100644 --- a/Source/SocketIO/Engine/SocketEngineSpec.swift +++ b/Source/SocketIO/Engine/SocketEngineSpec.swift @@ -34,6 +34,9 @@ import Starscream /// `true` if this engine is closed. var closed: Bool { get } + /// If `true` the engine will attempt to use WebSocket compression. + var compress: Bool { get } + /// `true` if this engine is connected. Connected means that the initial poll connect has succeeded. var connected: Bool { get } @@ -87,7 +90,7 @@ import Starscream /// - parameter client: The client for this engine. /// - parameter url: The url for this engine. /// - parameter options: The options for this engine. - init(client: SocketEngineClient, url: URL, options: NSDictionary?) + init(client: SocketEngineClient, url: URL, options: [String: Any]?) /// Starts the connection to the server. func connect() diff --git a/Source/SocketIO/Engine/SocketEngineWebsocket.swift b/Source/SocketIO/Engine/SocketEngineWebsocket.swift index 514ea3a..75da709 100644 --- a/Source/SocketIO/Engine/SocketEngineWebsocket.swift +++ b/Source/SocketIO/Engine/SocketEngineWebsocket.swift @@ -68,12 +68,12 @@ extension SocketEngineWebsocket { // MARK: Starscream delegate methods /// Delegate method for when a message is received. - public func websocketDidReceiveMessage(socket: WebSocket, text: String) { + public func websocketDidReceiveMessage(socket: WebSocketClient, text: String) { parseEngineMessage(text) } /// Delegate method for when binary is received. - public func websocketDidReceiveData(socket: WebSocket, data: Data) { + public func websocketDidReceiveData(socket: WebSocketClient, data: Data) { parseEngineData(data) } } diff --git a/Source/SocketIO/Manager/SocketManager.swift b/Source/SocketIO/Manager/SocketManager.swift new file mode 100644 index 0000000..95e56e7 --- /dev/null +++ b/Source/SocketIO/Manager/SocketManager.swift @@ -0,0 +1,519 @@ +// +// Created by Erik Little on 10/14/17. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +import Dispatch +import Foundation + +/// +/// A manager for a socket.io connection. +/// +/// A `SocketManager` is responsible for multiplexing multiple namespaces through a single `SocketEngineSpec`. +/// +/// Example: +/// +/// ```swift +/// let manager = SocketManager(socketURL: URL(string:"http://localhost:8080/")!) +/// let defaultNamespaceSocket = manager.defaultSocket +/// let swiftSocket = manager.socket(forNamespace: "/swift") +/// +/// // defaultNamespaceSocket and swiftSocket both share a single connection to the server +/// ``` +/// +/// Sockets created through the manager are retained by the manager. So at the very least, a single strong reference +/// to the manager must be maintained to keep sockets alive. +/// +/// To disconnect a socket and remove it from the manager, either call `SocketIOClient.disconnect()` on the socket, +/// or call one of the `disconnectSocket` methods on this class. +/// +open class SocketManager : NSObject, SocketManagerSpec, SocketParsable, SocketDataBufferable, ConfigSettable { + private static let logType = "SocketManager" + + // MARK Properties + + /// The socket associated with the default namespace ("/"). + public var defaultSocket: SocketIOClient { + return socket(forNamespace: "/") + } + + /// The URL of the socket.io server. + /// + /// If changed after calling `init`, `forceNew` must be set to `true`, or it will only connect to the url set in the + /// init. + public let socketURL: URL + + /// The configuration for this client. + /// + /// **Some configs will not take affect until after a reconnect if set after calling a connect method**. + public var config: SocketIOClientConfiguration { + get { + return _config + } + + set { + if status.active { + DefaultSocketLogger.Logger.log("Setting configs on active manager. Some configs may not be applied until reconnect", + type: SocketManager.logType) + } + + setConfigs(newValue) + } + } + + /// The engine for this manager. + public var engine: SocketEngineSpec? + + /// If `true` then every time `connect` is called, a new engine will be created. + public var forceNew = false + + /// The queue that all interaction with the client should occur on. This is the queue that event handlers are + /// called on. + /// + /// **This should be a serial queue! Concurrent queues are not supported and might cause crashes and races**. + public var handleQueue = DispatchQueue.main + + /// The sockets in this manager indexed by namespace. + public var nsps = [String: SocketIOClient]() + + /// If `true`, this client will try and reconnect on any disconnects. + public var reconnects = true + + /// The number of seconds to wait before attempting to reconnect. + public var reconnectWait = 10 + + /// The status of this manager. + public private(set) var status: SocketIOStatus = .notConnected { + didSet { + switch status { + case .connected: + reconnecting = false + currentReconnectAttempt = 0 + default: + break + } + } + } + + /// A list of packets that are waiting for binary data. + /// + /// The way that socket.io works all data should be sent directly after each packet. + /// So this should ideally be an array of one packet waiting for data. + /// + /// **This should not be modified directly.** + public var waitingPackets = [SocketPacket]() + + private(set) var reconnectAttempts = -1 + + private var _config: SocketIOClientConfiguration + private var currentReconnectAttempt = 0 + private var reconnecting = false + + /// Type safe way to create a new SocketIOClient. `opts` can be omitted. + /// + /// - parameter socketURL: The url of the socket.io server. + /// - parameter config: The config for this socket. + public init(socketURL: URL, config: SocketIOClientConfiguration = []) { + self._config = config + self.socketURL = socketURL + + if socketURL.absoluteString.hasPrefix("https://") { + self._config.insert(.secure(true)) + } + + self._config.insert(.path("/socket.io/"), replacing: false) + + super.init() + + setConfigs(_config) + } + + /// Not so type safe way to create a SocketIOClient, meant for Objective-C compatiblity. + /// If using Swift it's recommended to use `init(socketURL: NSURL, options: Set)` + /// + /// - parameter socketURL: The url of the socket.io server. + /// - parameter config: The config for this socket. + @objc + public convenience init(socketURL: URL, config: [String: Any]?) { + self.init(socketURL: socketURL, config: config?.toSocketConfiguration() ?? []) + } + + deinit { + DefaultSocketLogger.Logger.log("Manager is being released", type: SocketManager.logType) + + engine?.disconnect(reason: "Manager Deinit") + } + + // MARK: Methods + + private func addEngine() { + DefaultSocketLogger.Logger.log("Adding engine", type: SocketManager.logType) + + engine?.engineQueue.sync { + self.engine?.client = nil + } + + engine = SocketEngine(client: self, url: socketURL, config: config) + } + + /// Connects the underlying transport and the default namespace socket. + /// + /// Override if you wish to attach a custom `SocketEngineSpec`. + open func connect() { + guard !status.active else { + DefaultSocketLogger.Logger.log("Tried connecting an already active socket", type: SocketManager.logType) + + return + } + + if engine == nil || forceNew { + addEngine() + } + + status = .connecting + + engine?.connect() + } + + /// Connects a socket through this manager's engine. + /// + /// - parameter socket: The socket who we should connect through this manager. + open func connectSocket(_ socket: SocketIOClient) { + guard status == .connected else { + DefaultSocketLogger.Logger.log("Tried connecting socket when engine isn't open. Connecting", + type: SocketManager.logType) + + connect() + return + } + + engine?.send("0\(socket.nsp)", withData: []) + } + + /// Called when the manager has disconnected from socket.io. + /// + /// - parameter reason: The reason for the disconnection. + open func didDisconnect(reason: String) { + forAll {socket in + socket.didDisconnect(reason: reason) + } + } + + /// Disconnects the manager and all associated sockets. + open func disconnect() { + DefaultSocketLogger.Logger.log("Manager closing", type: SocketManager.logType) + + status = .disconnected + + engine?.disconnect(reason: "Disconnect") + } + + /// Disconnects the given socket. + /// + /// This will remove the socket for the manager's control, and make the socket instance useless and ready for + /// releasing. + /// + /// - parameter socket: The socket to disconnect. + open func disconnectSocket(_ socket: SocketIOClient) { + // Make sure we remove socket from nsps + nsps.removeValue(forKey: socket.nsp) + + engine?.send("1\(socket.nsp)", withData: []) + socket.didDisconnect(reason: "Namespace leave") + } + + /// Disconnects the socket associated with `forNamespace`. + /// + /// This will remove the socket for the manager's control, and make the socket instance useless and ready for + /// releasing. + /// + /// - parameter forNamespace: The namespace to disconnect from. + open func disconnectSocket(forNamespace nsp: String) { + guard let socket = nsps.removeValue(forKey: nsp) else { + DefaultSocketLogger.Logger.log("Could not find socket for \(nsp) to disconnect", + type: SocketManager.logType) + + return + } + + disconnectSocket(socket) + } + + /// Sends a client event to all sockets in `nsps` + /// + /// - parameter clientEvent: The event to emit. + open func emitAll(clientEvent event: SocketClientEvent, data: [Any]) { + forAll {socket in + socket.handleClientEvent(event, data: data) + } + } + + /// Sends an event to the server on all namespaces in this manager. + /// + /// - parameter event: The event to send. + /// - parameter items: The data to send with this event. + open func emitAll(_ event: String, _ items: SocketData...) { + guard let emitData = try? items.map({ try $0.socketRepresentation() }) else { + DefaultSocketLogger.Logger.error("Error creating socketRepresentation for emit: \(event), \(items)", + type: SocketManager.logType) + + return + } + + emitAll(event, withItems: emitData) + } + + /// Sends an event to the server on all namespaces in this manager. + /// + /// Same as `emitAll(_:_:)`, but meant for Objective-C. + /// + /// - parameter event: The event to send. + /// - parameter withItems: The data to send with this event. + open func emitAll(_ event: String, withItems items: [Any]) { + forAll {socket in + socket.emit(event, with: items) + } + } + + /// Called when the engine closes. + /// + /// - parameter reason: The reason that the engine closed. + open func engineDidClose(reason: String) { + handleQueue.async { + self._engineDidClose(reason: reason) + } + } + + private func _engineDidClose(reason: String) { + waitingPackets.removeAll() + + if status != .disconnected { + status = .notConnected + } + + if status == .disconnected || !reconnects { + didDisconnect(reason: reason) + } else if !reconnecting { + reconnecting = true + tryReconnect(reason: reason) + } + } + + /// Called when the engine errors. + /// + /// - parameter reason: The reason the engine errored. + open func engineDidError(reason: String) { + handleQueue.async { + self._engineDidError(reason: reason) + } + } + + private func _engineDidError(reason: String) { + DefaultSocketLogger.Logger.error("\(reason)", type: SocketManager.logType) + + emitAll(clientEvent: .error, data: [reason]) + } + + /// Called when the engine opens. + /// + /// - parameter reason: The reason the engine opened. + open func engineDidOpen(reason: String) { + handleQueue.async { + self._engineDidOpen(reason: reason) + } + } + + private func _engineDidOpen(reason: String) { + DefaultSocketLogger.Logger.log("Engine opened \(reason)", type: SocketManager.logType) + + status = .connected + nsps["/"]?.didConnect(toNamespace: "/") + + for (nsp, socket) in nsps where nsp != "/" && socket.status == .connecting { + connectSocket(socket) + } + } + + /// Called when the engine receives a pong message. + open func engineDidReceivePong() { + handleQueue.async { + self._engineDidReceivePong() + } + } + + private func _engineDidReceivePong() { + emitAll(clientEvent: .pong, data: []) + } + + /// Called when the sends a ping to the server. + open func engineDidSendPing() { + handleQueue.async { + self._engineDidSendPing() + } + } + + private func _engineDidSendPing() { + emitAll(clientEvent: .ping, data: []) + } + + private func forAll(do: (SocketIOClient) throws -> ()) rethrows { + for (_, socket) in nsps { + try `do`(socket) + } + } + + /// Called when the engine has a message that must be parsed. + /// + /// - parameter msg: The message that needs parsing. + open func parseEngineMessage(_ msg: String) { + handleQueue.async { + self._parseEngineMessage(msg) + } + } + + private func _parseEngineMessage(_ msg: String) { + guard let packet = parseSocketMessage(msg) else { return } + guard packet.type != .binaryAck && packet.type != .binaryEvent else { + waitingPackets.append(packet) + + return + } + + nsps[packet.nsp]?.handlePacket(packet) + } + + /// Called when the engine receives binary data. + /// + /// - parameter data: The data the engine received. + open func parseEngineBinaryData(_ data: Data) { + handleQueue.async { + self._parseEngineBinaryData(data) + } + } + + private func _parseEngineBinaryData(_ data: Data) { + guard let packet = parseBinaryData(data) else { return } + + nsps[packet.nsp]?.handlePacket(packet) + } + + /// Tries to reconnect to the server. + /// + /// This will cause a `disconnect` event to be emitted, as well as an `reconnectAttempt` event. + open func reconnect() { + guard !reconnecting else { return } + + engine?.disconnect(reason: "manual reconnect") + } + + private func tryReconnect(reason: String) { + guard reconnecting else { return } + + DefaultSocketLogger.Logger.log("Starting reconnect", type: SocketManager.logType) + + // Set status to connecting and emit reconnect for all sockets + forAll {socket in + guard socket.status == .connected else { return } + + socket.setReconnecting(reason: reason) + } + + _tryReconnect() + } + + private func _tryReconnect() { + guard reconnects && reconnecting && status != .disconnected else { return } + + if reconnectAttempts != -1 && currentReconnectAttempt + 1 > reconnectAttempts { + return didDisconnect(reason: "Reconnect Failed") + } + + DefaultSocketLogger.Logger.log("Trying to reconnect", type: SocketManager.logType) + emitAll(clientEvent: .reconnectAttempt, data: [(reconnectAttempts - currentReconnectAttempt)]) + + currentReconnectAttempt += 1 + connect() + + handleQueue.asyncAfter(deadline: DispatchTime.now() + Double(reconnectWait), execute: _tryReconnect) + } + + /// Sets manager specific configs. + /// + /// parameter config: The configs that should be set. + open func setConfigs(_ config: SocketIOClientConfiguration) { + for option in config { + switch option { + case let .forceNew(new): + self.forceNew = new + case let .reconnects(reconnects): + self.reconnects = reconnects + case let .reconnectWait(wait): + reconnectWait = abs(wait) + case let .log(log): + DefaultSocketLogger.Logger.log = log + case let .logger(logger): + DefaultSocketLogger.Logger = logger + default: + continue + } + } + + _config = config + _config.insert(.path("/socket.io/"), replacing: false) + + // If `ConfigSettable` & `SocketEngineSpec`, update its configs. + if var settableEngine = engine as? ConfigSettable & SocketEngineSpec { + settableEngine.engineQueue.sync { + settableEngine.setConfigs(self._config) + } + + engine = settableEngine + } + } + + /// Returns a `SocketIOClient` for the given namespace. This socket shares a transport with the manager. + /// + /// Calling multiple times returns the same socket. + /// + /// Sockets created from this method are retained by the manager. + /// Call one of the `disconnectSocket` methods on this class to remove the socket from manager control. + /// Or call `SocketIOClient.disconnect()` on the client. + /// + /// - parameter forNamespace: The namespace for the socket. + /// - returns: A `SocketIOClient` for the given namespace. + open func socket(forNamespace nsp: String) -> SocketIOClient { + assert(nsp.hasPrefix("/"), "forNamespace must have a leading /") + + if let socket = nsps[nsp] { + return socket + } + + let client = SocketIOClient(manager: self, nsp: nsp) + + nsps[nsp] = client + + return client + } + + // Test properties + + func setTestStatus(_ status: SocketIOStatus) { + self.status = status + } +} diff --git a/Source/SocketIO/Manager/SocketManagerSpec.swift b/Source/SocketIO/Manager/SocketManagerSpec.swift new file mode 100644 index 0000000..8973f43 --- /dev/null +++ b/Source/SocketIO/Manager/SocketManagerSpec.swift @@ -0,0 +1,128 @@ +// +// Created by Erik Little on 10/18/17. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +import Dispatch +import Foundation + +// TODO Fix the types so that we aren't using concrete types + +/// +/// A manager for a socket.io connection. +/// +/// A `SocketManagerSpec` is responsible for multiplexing multiple namespaces through a single `SocketEngineSpec`. +/// +/// Example with `SocketManager`: +/// +/// ```swift +/// let manager = SocketManager(socketURL: URL(string:"http://localhost:8080/")!) +/// let defaultNamespaceSocket = manager.defaultSocket +/// let swiftSocket = manager.socket(forNamespace: "/swift") +/// +/// // defaultNamespaceSocket and swiftSocket both share a single connection to the server +/// ``` +/// +/// Sockets created through the manager are retained by the manager. So at the very least, a single strong reference +/// to the manager must be maintained to keep sockets alive. +/// +/// To disconnect a socket and remove it from the manager, either call `SocketIOClient.disconnect()` on the socket, +/// or call one of the `disconnectSocket` methods on this class. +/// +@objc +public protocol SocketManagerSpec : class, SocketEngineClient { + // MARK: Properties + + /// Returns the socket associated with the default namespace ("/"). + var defaultSocket: SocketIOClient { get } + + /// The engine for this manager. + var engine: SocketEngineSpec? { get set } + + /// If `true` then every time `connect` is called, a new engine will be created. + var forceNew: Bool { get set } + + // TODO Per socket queues? + /// The queue that all interaction with the client should occur on. This is the queue that event handlers are + /// called on. + var handleQueue: DispatchQueue { get set } + + /// If `true`, this manager will try and reconnect on any disconnects. + var reconnects: Bool { get set } + + /// The number of seconds to wait before attempting to reconnect. + var reconnectWait: Int { get set } + + /// The URL of the socket.io server. + var socketURL: URL { get } + + /// The status of this manager. + var status: SocketIOStatus { get } + + // MARK: Methods + + /// Connects the underlying transport. + func connect() + + /// Connects a socket through this manager's engine. + /// + /// - parameter socket: The socket who we should connect through this manager. + func connectSocket(_ socket: SocketIOClient) + + /// Called when the manager has disconnected from socket.io. + /// + /// - parameter reason: The reason for the disconnection. + func didDisconnect(reason: String) + + /// Disconnects the manager and all associated sockets. + func disconnect() + + /// Disconnects the given socket. + /// + /// - parameter socket: The socket to disconnect. + func disconnectSocket(_ socket: SocketIOClient) + + /// Disconnects the socket associated with `forNamespace`. + /// + /// - parameter forNamespace: The namespace to disconnect from. + func disconnectSocket(forNamespace nsp: String) + + /// Sends an event to the server on all namespaces in this manager. + /// + /// - parameter event: The event to send. + /// - parameter withItems: The data to send with this event. + func emitAll(_ event: String, withItems items: [Any]) + + /// Tries to reconnect to the server. + /// + /// This will cause a `disconnect` event to be emitted, as well as an `reconnectAttempt` event. + func reconnect() + + /// Returns a `SocketIOClient` for the given namespace. This socket shares a transport with the manager. + /// + /// Calling multiple times returns the same socket. + /// + /// Sockets created from this method are retained by the manager. + /// Call one of the `disconnectSocket` methods on the implementing class to remove the socket from manager control. + /// Or call `SocketIOClient.disconnect()` on the client. + /// + /// - parameter forNamespace: The namespace for the socket. + /// - returns: A `SocketIOClient` for the given namespace. + func socket(forNamespace nsp: String) -> SocketIOClient +} diff --git a/Source/SocketIO/Parse/SocketPacket.swift b/Source/SocketIO/Parse/SocketPacket.swift index 780f524..28fbf35 100644 --- a/Source/SocketIO/Parse/SocketPacket.swift +++ b/Source/SocketIO/Parse/SocketPacket.swift @@ -142,12 +142,8 @@ public struct SocketPacket : CustomStringConvertible { if dict["_placeholder"] as? Bool ?? false { return binary[dict["num"] as! Int] } else { - return dict.reduce(JSON(), {cur, keyValue in - var cur = cur - + return dict.reduce(into: JSON(), {cur, keyValue in cur[keyValue.0] = _fillInPlaceholders(keyValue.1) - - return cur }) } case let arr as [Any]: @@ -225,12 +221,8 @@ private extension SocketPacket { case let arr as [Any]: return arr.map({shred($0, binary: &binary)}) case let dict as JSON: - return dict.reduce(JSON(), {cur, keyValue in - var mutCur = cur - - mutCur[keyValue.0] = shred(keyValue.1, binary: &binary) - - return mutCur + return dict.reduce(into: JSON(), {cur, keyValue in + cur[keyValue.0] = shred(keyValue.1, binary: &binary) }) default: return data diff --git a/Source/SocketIO/Parse/SocketParsable.swift b/Source/SocketIO/Parse/SocketParsable.swift index de1c87a..2349ce3 100644 --- a/Source/SocketIO/Parse/SocketParsable.swift +++ b/Source/SocketIO/Parse/SocketParsable.swift @@ -26,14 +26,6 @@ import Foundation public protocol SocketParsable : class { // MARK: Properties - /// A list of packets that are waiting for binary data. - /// - /// The way that socket.io works all data should be sent directly after each packet. - /// So this should ideally be an array of one packet waiting for data. - /// - /// **This should not be modified directly.** - var waitingPackets: [SocketPacket] { get set } - // MARK: Methods /// Called when the engine has received some binary data that should be attached to a packet. @@ -43,12 +35,13 @@ public protocol SocketParsable : class { /// into the correct placeholder. /// /// - parameter data: The data that should be attached to a packet. - func parseBinaryData(_ data: Data) + func parseBinaryData(_ data: Data) -> SocketPacket? /// Called when the engine has received a string that should be parsed into a socket.io packet. /// /// - parameter message: The string that needs parsing. - func parseSocketMessage(_ message: String) + /// - returns: A completed socket packet if there is no more data left to collect. + func parseSocketMessage(_ message: String) -> SocketPacket? } /// Errors that can be thrown during parsing. @@ -65,38 +58,18 @@ public enum SocketParsableError : Error { case invalidPacketType } -public extension SocketParsable where Self: SocketIOClientSpec { - private func isCorrectNamespace(_ nsp: String) -> Bool { - return nsp == self.nsp - } - - private func handleConnect(_ packetNamespace: String) { - guard packetNamespace == nsp else { return } - - didConnect(toNamespace: packetNamespace) - } - - private func handlePacket(_ pack: SocketPacket) { - switch pack.type { - case .event where isCorrectNamespace(pack.nsp): - handleEvent(pack.event, data: pack.args, isInternalMessage: false, withAck: pack.id) - case .ack where isCorrectNamespace(pack.nsp): - handleAck(pack.id, data: pack.data) - case .binaryEvent where isCorrectNamespace(pack.nsp): - waitingPackets.append(pack) - case .binaryAck where isCorrectNamespace(pack.nsp): - waitingPackets.append(pack) - case .connect: - handleConnect(pack.nsp) - case .disconnect: - didDisconnect(reason: "Got Disconnect") - case .error: - handleEvent("error", data: pack.data, isInternalMessage: true, withAck: pack.id) - default: - DefaultSocketLogger.Logger.log("Got invalid packet: \(pack.description)", type: "SocketParser") - } - } +/// Says that a type will be able to buffer binary data before all data for an event has come in. +public protocol SocketDataBufferable : class { + /// A list of packets that are waiting for binary data. + /// + /// The way that socket.io works all data should be sent directly after each packet. + /// So this should ideally be an array of one packet waiting for data. + /// + /// **This should not be modified directly.** + var waitingPackets: [SocketPacket] { get set } +} +public extension SocketParsable where Self: SocketManagerSpec & SocketDataBufferable { /// Parses a message from the engine, returning a complete SocketPacket or throwing. /// /// - parameter message: The message to parse. @@ -169,8 +142,9 @@ public extension SocketParsable where Self: SocketIOClientSpec { /// Called when the engine has received a string that should be parsed into a socket.io packet. /// /// - parameter message: The string that needs parsing. - public func parseSocketMessage(_ message: String) { - guard !message.isEmpty else { return } + /// - returns: A completed socket packet or nil if the packet is invalid. + public func parseSocketMessage(_ message: String) -> SocketPacket? { + guard !message.isEmpty else { return nil } DefaultSocketLogger.Logger.log("Parsing \(message)", type: "SocketParser") @@ -179,9 +153,11 @@ public extension SocketParsable where Self: SocketIOClientSpec { DefaultSocketLogger.Logger.log("Decoded packet as: \(packet.description)", type: "SocketParser") - handlePacket(packet) + return packet } catch { DefaultSocketLogger.Logger.error("\(error): \(message)", type: "SocketParser") + + return nil } } @@ -192,21 +168,17 @@ public extension SocketParsable where Self: SocketIOClientSpec { /// into the correct placeholder. /// /// - parameter data: The data that should be attached to a packet. - public func parseBinaryData(_ data: Data) { + /// - returns: A completed socket packet if there is no more data left to collect. + public func parseBinaryData(_ data: Data) -> SocketPacket? { guard !waitingPackets.isEmpty else { DefaultSocketLogger.Logger.error("Got data when not remaking packet", type: "SocketParser") - return + + return nil } // Should execute event? - guard waitingPackets[waitingPackets.count - 1].addData(data) else { return } + guard waitingPackets[waitingPackets.count - 1].addData(data) else { return nil } - let packet = waitingPackets.removeLast() - - if packet.type != .binaryAck { - handleEvent(packet.event, data: packet.args, isInternalMessage: false, withAck: packet.id) - } else { - handleAck(packet.id, data: packet.args) - } + return waitingPackets.removeLast() } } diff --git a/Source/SocketIO/Util/SocketClientManager.swift b/Source/SocketIO/Util/SocketClientManager.swift deleted file mode 100644 index 0c99309..0000000 --- a/Source/SocketIO/Util/SocketClientManager.swift +++ /dev/null @@ -1,110 +0,0 @@ -// -// SocketClientManager.swift -// Socket.IO-Client-Swift -// -// Created by Erik Little on 6/11/16. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -import Foundation - -/** - Experimental socket manager. - - API subject to change. - - Can be used to persist sockets across ViewControllers. - - Sockets are strongly stored, so be sure to remove them once they are no - longer needed. - - Example usage: - ``` - let manager = SocketClientManager.sharedManager - manager["room1"] = socket1 - manager["room2"] = socket2 - manager.removeSocket(socket: socket2) - manager["room1"]?.emit("hello") - ``` - */ -open class SocketClientManager : NSObject { - // MARK: Properties. - - /// The shared manager. - @objc - open static let sharedManager = SocketClientManager() - - private var sockets = [String: SocketIOClient]() - - /// Gets a socket by its name. - /// - /// - returns: The socket, if one had the given name. - open subscript(string: String) -> SocketIOClient? { - get { - return sockets[string] - } - - set(socket) { - sockets[string] = socket - } - } - - // MARK: Methods. - - /// Adds a socket. - /// - /// - parameter socket: The socket to add. - /// - parameter labeledAs: The label for this socket. - @objc - open func addSocket(_ socket: SocketIOClient, labeledAs label: String) { - sockets[label] = socket - } - - /// Removes a socket by a given name. - /// - /// - parameter withLabel: The label of the socket to remove. - /// - returns: The socket for the given label, if one was present. - @objc - @discardableResult - open func removeSocket(withLabel label: String) -> SocketIOClient? { - return sockets.removeValue(forKey: label) - } - - /// Removes a socket. - /// - /// - parameter socket: The socket to remove. - /// - returns: The socket if it was in the manager. - @objc - @discardableResult - open func removeSocket(_ socket: SocketIOClient) -> SocketIOClient? { - var returnSocket: SocketIOClient? - - for (label, dictSocket) in sockets where dictSocket === socket { - returnSocket = sockets.removeValue(forKey: label) - } - - return returnSocket - } - - /// Removes all the sockets in the manager. - @objc - open func removeSockets() { - sockets.removeAll() - } -} diff --git a/Source/SocketIO/Util/SocketExtensions.swift b/Source/SocketIO/Util/SocketExtensions.swift index e80cf6e..eaee76b 100644 --- a/Source/SocketIO/Util/SocketExtensions.swift +++ b/Source/SocketIO/Util/SocketExtensions.swift @@ -42,7 +42,7 @@ extension CharacterSet { } } -extension NSDictionary { +extension Dictionary where Key == String, Value == Any { private static func keyValueToSocketIOClientOption(key: String, value: Any) -> SocketIOClientOption? { switch (key, value) { case let ("connectParams", params as [String: Any]): @@ -63,8 +63,6 @@ extension NSDictionary { return .log(log) case let ("logger", logger as SocketLogger): return .logger(logger) - case let ("nsp", nsp as String): - return .nsp(nsp) case let ("path", path as String): return .path(path) case let ("reconnects", reconnects as Bool): @@ -92,7 +90,7 @@ extension NSDictionary { var options = [] as SocketIOClientConfiguration for (rawKey, value) in self { - if let key = rawKey as? String, let opt = NSDictionary.keyValueToSocketIOClientOption(key: key, value: value) { + if let opt = Dictionary.keyValueToSocketIOClientOption(key: rawKey, value: value) { options.insert(opt) } } diff --git a/Tests/TestSocketIO/SocketBasicPacketTest.swift b/Tests/TestSocketIO/SocketBasicPacketTest.swift index fb947a0..b1c36ad 100644 --- a/Tests/TestSocketIO/SocketBasicPacketTest.swift +++ b/Tests/TestSocketIO/SocketBasicPacketTest.swift @@ -150,10 +150,9 @@ class SocketBasicPacketTest: XCTestCase { func testBinaryStringPlaceholderInMessage() { let engineString = "52-[\"test\",\"~~0\",{\"num\":0,\"_placeholder\":true},{\"_placeholder\":true,\"num\":1}]" - let socket = SocketIOClient(socketURL: URL(string: "http://localhost/")!) - socket.setTestable() + let manager = SocketManager(socketURL: URL(string: "http://localhost/")!) - var packet = try! socket.parseString(engineString) + var packet = try! manager.parseString(engineString) XCTAssertEqual(packet.event, "test") _ = packet.addData(data) diff --git a/Tests/TestSocketIO/SocketEngineTest.swift b/Tests/TestSocketIO/SocketEngineTest.swift index c8cc46d..048100d 100644 --- a/Tests/TestSocketIO/SocketEngineTest.swift +++ b/Tests/TestSocketIO/SocketEngineTest.swift @@ -10,20 +10,9 @@ import XCTest @testable import SocketIO class SocketEngineTest: XCTestCase { - var client: SocketIOClient! - var engine: SocketEngine! - - override func setUp() { - super.setUp() - client = SocketIOClient(socketURL: URL(string: "http://localhost")!) - engine = SocketEngine(client: client, url: URL(string: "http://localhost")!, options: nil) - - client.setTestable() - } - func testBasicPollingMessage() { let expect = expectation(description: "Basic polling test") - client.on("blankTest") {data, ack in + socket.on("blankTest") {data, ack in expect.fulfill() } @@ -35,11 +24,11 @@ class SocketEngineTest: XCTestCase { let finalExpectation = expectation(description: "Final packet in poll test") var gotBlank = false - client.on("blankTest") {data, ack in + socket.on("blankTest") {data, ack in gotBlank = true } - client.on("stringTest") {data, ack in + socket.on("stringTest") {data, ack in if let str = data[0] as? String, gotBlank { if str == "hello" { finalExpectation.fulfill() @@ -54,7 +43,7 @@ class SocketEngineTest: XCTestCase { func testEngineDoesErrorOnUnknownTransport() { let finalExpectation = expectation(description: "Unknown Transport") - client.on("error") {data, ack in + socket.on("error") {data, ack in if let error = data[0] as? String, error == "Unknown transport" { finalExpectation.fulfill() } @@ -67,7 +56,7 @@ class SocketEngineTest: XCTestCase { func testEngineDoesErrorOnUnknownMessage() { let finalExpectation = expectation(description: "Engine Errors") - client.on("error") {data, ack in + socket.on("error") {data, ack in finalExpectation.fulfill() } @@ -78,7 +67,7 @@ class SocketEngineTest: XCTestCase { func testEngineDecodesUTF8Properly() { let expect = expectation(description: "Engine Decodes utf8") - client.on("stringTest") {data, ack in + socket.on("stringTest") {data, ack in XCTAssertEqual(data[0] as? String, "lïne one\nlīne \rtwo𦅙𦅛", "Failed string test") expect.fulfill() } @@ -110,7 +99,7 @@ class SocketEngineTest: XCTestCase { let b64String = "b4aGVsbG8NCg==" let packetString = "451-[\"test\",{\"test\":{\"_placeholder\":true,\"num\":0}}]" - client.on("test") {data, ack in + socket.on("test") {data, ack in if let data = data[0] as? Data, let string = String(data: data, encoding: .utf8) { XCTAssertEqual(string, "hello") } @@ -123,4 +112,97 @@ class SocketEngineTest: XCTestCase { waitForExpectations(timeout: 3, handler: nil) } + + func testSettingExtraHeadersBeforeConnectSetsEngineExtraHeaders() { + let newValue = ["hello": "world"] + + manager.engine = engine + manager.setTestStatus(.notConnected) + manager.config = [.extraHeaders(["new": "value"])] + manager.config.insert(.extraHeaders(newValue), replacing: true) + + XCTAssertEqual(2, manager.config.count) + XCTAssertEqual(manager.engine!.extraHeaders!, newValue) + + for config in manager.config { + switch config { + case let .extraHeaders(headers): + XCTAssertTrue(headers.keys.contains("hello"), "It should contain hello header key") + XCTAssertFalse(headers.keys.contains("new"), "It should not contain old data") + case .path: + continue + default: + XCTFail("It should only have two configs") + } + } + } + + func testSettingExtraHeadersAfterConnectDoesNotIgnoreChanges() { + let newValue = ["hello": "world"] + + manager.engine = engine + manager.setTestStatus(.connected) + engine.setConnected(true) + manager.config = [.extraHeaders(["new": "value"])] + manager.config.insert(.extraHeaders(["hello": "world"]), replacing: true) + + XCTAssertEqual(2, manager.config.count) + XCTAssertEqual(manager.engine!.extraHeaders!, newValue) + } + + func testSettingPathAfterConnectDoesNotIgnoreChanges() { + let newValue = "/newpath/" + + manager.engine = engine + manager.setTestStatus(.connected) + engine.setConnected(true) + manager.config.insert(.path(newValue)) + + XCTAssertEqual(1, manager.config.count) + XCTAssertEqual(manager.engine!.socketPath, newValue) + } + + func testSettingCompressAfterConnectDoesNotIgnoreChanges() { + manager.engine = engine + manager.setTestStatus(.connected) + engine.setConnected(true) + manager.config.insert(.compress) + + XCTAssertEqual(2, manager.config.count) + XCTAssertTrue(manager.engine!.compress) + } + + func testSettingForcePollingAfterConnectDoesNotIgnoreChanges() { + manager.engine = engine + manager.setTestStatus(.connected) + engine.setConnected(true) + manager.config.insert(.forcePolling(true)) + + XCTAssertEqual(2, manager.config.count) + XCTAssertTrue(manager.engine!.forcePolling) + } + + func testSettingForceWebSocketsAfterConnectDoesNotIgnoreChanges() { + manager.engine = engine + manager.setTestStatus(.connected) + engine.setConnected(true) + manager.config.insert(.forceWebsockets(true)) + + XCTAssertEqual(2, manager.config.count) + XCTAssertTrue(manager.engine!.forceWebsockets) + } + + var manager: SocketManager! + var socket: SocketIOClient! + var engine: SocketEngine! + + override func setUp() { + super.setUp() + + manager = SocketManager(socketURL: URL(string: "http://localhost")!) + socket = manager.defaultSocket + engine = SocketEngine(client: manager, url: URL(string: "http://localhost")!, options: nil) + + socket.setTestable() + } } diff --git a/Tests/TestSocketIO/SocketIOClientConfigurationTest.swift b/Tests/TestSocketIO/SocketIOClientConfigurationTest.swift index 9b5c50a..1289a11 100644 --- a/Tests/TestSocketIO/SocketIOClientConfigurationTest.swift +++ b/Tests/TestSocketIO/SocketIOClientConfigurationTest.swift @@ -9,20 +9,12 @@ import XCTest import SocketIO -class TestSocketIOClientConfiguration: XCTestCase { - var config = [] as SocketIOClientConfiguration - - override func setUp() { - super.setUp() - - config = [.log(false), .forceNew(true)] - } - +class TestSocketIOClientConfiguration : XCTestCase { func testReplaceSameOption() { config.insert(.log(true)) - + XCTAssertEqual(config.count, 2) - + switch config[0] { case let .log(log): XCTAssertTrue(log) @@ -30,12 +22,12 @@ class TestSocketIOClientConfiguration: XCTestCase { XCTFail() } } - + func testIgnoreIfExisting() { config.insert(.forceNew(false), replacing: false) - + XCTAssertEqual(config.count, 2) - + switch config[1] { case let .forceNew(new): XCTAssertTrue(new) @@ -43,4 +35,12 @@ class TestSocketIOClientConfiguration: XCTestCase { XCTFail() } } + + var config = [] as SocketIOClientConfiguration + + override func setUp() { + config = [.log(false), .forceNew(true)] + + super.setUp() + } } diff --git a/Tests/TestSocketIO/SocketMangerTest.swift b/Tests/TestSocketIO/SocketMangerTest.swift new file mode 100644 index 0000000..1e37f98 --- /dev/null +++ b/Tests/TestSocketIO/SocketMangerTest.swift @@ -0,0 +1,174 @@ +// +// Created by Erik Little on 10/21/17. +// + +import Dispatch +import Foundation +@testable import SocketIO +import XCTest + +class SocketMangerTest : XCTestCase { + func testManagerProperties() { + XCTAssertNotNil(manager.defaultSocket) + XCTAssertNil(manager.engine) + XCTAssertFalse(manager.forceNew) + XCTAssertEqual(manager.handleQueue, DispatchQueue.main) + XCTAssertTrue(manager.reconnects) + XCTAssertEqual(manager.reconnectWait, 10) + XCTAssertEqual(manager.status, .notConnected) + } + + func testManagerCallsConnect() { + setUpSockets() + + socket.expectations[ManagerExpectation.didConnectCalled] = expectation(description: "The manager should call connect on the default socket") + socket2.expectations[ManagerExpectation.didConnectCalled] = expectation(description: "The manager should call connect on the socket") + + socket.connect() + socket2.connect() + + manager.fakeConnecting() + manager.fakeConnecting(toNamespace: "/swift") + + waitForExpectations(timeout: 0.3) + } + + func testManagerCallsDisconnect() { + setUpSockets() + + socket.expectations[ManagerExpectation.didDisconnectCalled] = expectation(description: "The manager should call disconnect on the default socket") + socket2.expectations[ManagerExpectation.didDisconnectCalled] = expectation(description: "The manager should call disconnect on the socket") + + socket2.on(clientEvent: .connect) {data, ack in + self.manager.disconnect() + self.manager.fakeDisconnecting() + } + + socket.connect() + socket2.connect() + + manager.fakeConnecting() + manager.fakeConnecting(toNamespace: "/swift") + + waitForExpectations(timeout: 0.3) + } + + func testManagerEmitAll() { + setUpSockets() + + socket.expectations[ManagerExpectation.emitAllEventCalled] = expectation(description: "The manager should emit an event to the default socket") + socket2.expectations[ManagerExpectation.emitAllEventCalled] = expectation(description: "The manager should emit an event to the socket") + + socket2.on(clientEvent: .connect) {data, ack in + self.manager.emitAll("event", "testing") + } + + socket.connect() + socket2.connect() + + manager.fakeConnecting() + manager.fakeConnecting(toNamespace: "/swift") + + waitForExpectations(timeout: 0.3) + } + + private func setUpSockets() { + socket = manager.testSocket(forNamespace: "/") + socket2 = manager.testSocket(forNamespace: "/swift") + } + + private var manager: TestManager! + private var socket: TestSocket! + private var socket2: TestSocket! + + override func setUp() { + super.setUp() + + manager = TestManager(socketURL: URL(string: "http://localhost/")!, config: [.log(false)]) + socket = nil + socket2 = nil + } +} + +public enum ManagerExpectation : String { + case didConnectCalled + case didDisconnectCalled + case emitAllEventCalled +} + +public class TestManager : SocketManager { + public override func disconnect() { + setTestStatus(.disconnected) + } + + @objc + public func testSocket(forNamespace nsp: String) -> TestSocket { + return socket(forNamespace: nsp) as! TestSocket + } + + @objc + public func fakeConnecting(toNamespace nsp: String) { + DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.1) { + // Fake connecting + self.parseEngineMessage("0\(nsp)") + } + } + + @objc + public func fakeDisconnecting() { + engineDidClose(reason: "") + } + + @objc + public func fakeConnecting() { + engineDidOpen(reason: "") + } + + public override func socket(forNamespace nsp: String) -> SocketIOClient { + // set socket to our test socket, the superclass method will get this from nsps + nsps[nsp] = TestSocket(manager: self, nsp: nsp) + + return super.socket(forNamespace: nsp) + } +} + +public class TestSocket : SocketIOClient { + public var expectations = [ManagerExpectation: XCTestExpectation]() + + @objc + public var expects = NSMutableDictionary() + + public override func didConnect(toNamespace nsp: String) { + expectations[ManagerExpectation.didConnectCalled]?.fulfill() + expectations[ManagerExpectation.didConnectCalled] = nil + + if let expect = expects[ManagerExpectation.didConnectCalled.rawValue] as? XCTestExpectation { + expect.fulfill() + expects[ManagerExpectation.didConnectCalled.rawValue] = nil + } + + super.didConnect(toNamespace: nsp) + } + + public override func didDisconnect(reason: String) { + expectations[ManagerExpectation.didDisconnectCalled]?.fulfill() + expectations[ManagerExpectation.didDisconnectCalled] = nil + + if let expect = expects[ManagerExpectation.didDisconnectCalled.rawValue] as? XCTestExpectation { + expect.fulfill() + expects[ManagerExpectation.didDisconnectCalled.rawValue] = nil + } + + super.didDisconnect(reason: reason) + } + + public override func emit(_ event: String, with items: [Any]) { + expectations[ManagerExpectation.emitAllEventCalled]?.fulfill() + expectations[ManagerExpectation.emitAllEventCalled] = nil + + if let expect = expects[ManagerExpectation.emitAllEventCalled.rawValue] as? XCTestExpectation { + expect.fulfill() + expects[ManagerExpectation.emitAllEventCalled.rawValue] = nil + } + } +} diff --git a/Tests/TestSocketIO/SocketParserTest.swift b/Tests/TestSocketIO/SocketParserTest.swift index e22de7c..2ac1301 100644 --- a/Tests/TestSocketIO/SocketParserTest.swift +++ b/Tests/TestSocketIO/SocketParserTest.swift @@ -10,26 +10,6 @@ import XCTest @testable import SocketIO class SocketParserTest: XCTestCase { - let testSocket = SocketIOClient(socketURL: URL(string: "http://localhost/")!) - - //Format key: message; namespace-data-binary-id - static let packetTypes: [String: (String, [Any], [Data], Int)] = [ - "0": ("/", [], [], -1), "1": ("/", [], [], -1), - "25[\"test\"]": ("/", ["test"], [], 5), - "2[\"test\",\"~~0\"]": ("/", ["test", "~~0"], [], -1), - "2/swift,[\"testArrayEmitReturn\",[\"test3\",\"test4\"]]": ("/swift", ["testArrayEmitReturn", ["test3", "test4"] as NSArray], [], -1), - "51-/swift,[\"testMultipleItemsWithBufferEmitReturn\",[1,2],{\"test\":\"bob\"},25,\"polo\",{\"_placeholder\":true,\"num\":0}]": ("/swift", ["testMultipleItemsWithBufferEmitReturn", [1, 2] as NSArray, ["test": "bob"] as NSDictionary, 25, "polo", ["_placeholder": true, "num": 0] as NSDictionary], [], -1), - "3/swift,0[[\"test3\",\"test4\"]]": ("/swift", [["test3", "test4"] as NSArray], [], 0), - "61-/swift,19[[1,2],{\"test\":\"bob\"},25,\"polo\",{\"_placeholder\":true,\"num\":0}]": - ("/swift", [ [1, 2] as NSArray, ["test": "bob"] as NSDictionary, 25, "polo", ["_placeholder": true, "num": 0] as NSDictionary], [], 19), - "4/swift,": ("/swift", [], [], -1), - "0/swift": ("/swift", [], [], -1), - "1/swift": ("/swift", [], [], -1), - "4\"ERROR\"": ("/", ["ERROR"], [], -1), - "4{\"test\":2}": ("/", [["test": 2]], [], -1), - "41": ("/", [1], [], -1), - "4[1, \"hello\"]": ("/", [1, "hello"], [], -1)] - func testDisconnect() { let message = "1" validateParseResult(message) @@ -108,7 +88,7 @@ class SocketParserTest: XCTestCase { func testInvalidInput() { let message = "8" do { - let _ = try testSocket.parseString(message) + let _ = try testManager.parseString(message) XCTFail() } catch { @@ -125,8 +105,8 @@ class SocketParserTest: XCTestCase { func validateParseResult(_ message: String) { let validValues = SocketParserTest.packetTypes[message]! - let packet = try! testSocket.parseString(message) - let type = String(message.characters.prefix(1)) + let packet = try! testManager.parseString(message) + let type = String(message.prefix(1)) XCTAssertEqual(packet.type, SocketPacket.PacketType(rawValue: Int(type) ?? -1)!) XCTAssertEqual(packet.nsp, validValues.0) @@ -139,8 +119,29 @@ class SocketParserTest: XCTestCase { let keys = Array(SocketParserTest.packetTypes.keys) measure { for item in keys.enumerated() { - _ = try! self.testSocket.parseString(item.element) + _ = try! self.testManager.parseString(item.element) } } } + + let testManager = SocketManager(socketURL: URL(string: "http://localhost/")!) + + //Format key: message; namespace-data-binary-id + static let packetTypes: [String: (String, [Any], [Data], Int)] = [ + "0": ("/", [], [], -1), "1": ("/", [], [], -1), + "25[\"test\"]": ("/", ["test"], [], 5), + "2[\"test\",\"~~0\"]": ("/", ["test", "~~0"], [], -1), + "2/swift,[\"testArrayEmitReturn\",[\"test3\",\"test4\"]]": ("/swift", ["testArrayEmitReturn", ["test3", "test4"] as NSArray], [], -1), + "51-/swift,[\"testMultipleItemsWithBufferEmitReturn\",[1,2],{\"test\":\"bob\"},25,\"polo\",{\"_placeholder\":true,\"num\":0}]": ("/swift", ["testMultipleItemsWithBufferEmitReturn", [1, 2] as NSArray, ["test": "bob"] as NSDictionary, 25, "polo", ["_placeholder": true, "num": 0] as NSDictionary], [], -1), + "3/swift,0[[\"test3\",\"test4\"]]": ("/swift", [["test3", "test4"] as NSArray], [], 0), + "61-/swift,19[[1,2],{\"test\":\"bob\"},25,\"polo\",{\"_placeholder\":true,\"num\":0}]": + ("/swift", [ [1, 2] as NSArray, ["test": "bob"] as NSDictionary, 25, "polo", ["_placeholder": true, "num": 0] as NSDictionary], [], 19), + "4/swift,": ("/swift", [], [], -1), + "0/swift": ("/swift", [], [], -1), + "1/swift": ("/swift", [], [], -1), + "4\"ERROR\"": ("/", ["ERROR"], [], -1), + "4{\"test\":2}": ("/", [["test": 2]], [], -1), + "41": ("/", [1], [], -1), + "4[1, \"hello\"]": ("/", [1, "hello"], [], -1) + ] } diff --git a/Tests/TestSocketIO/SocketSideEffectTest.swift b/Tests/TestSocketIO/SocketSideEffectTest.swift index d3466b1..b5b2cd5 100644 --- a/Tests/TestSocketIO/SocketSideEffectTest.swift +++ b/Tests/TestSocketIO/SocketSideEffectTest.swift @@ -34,7 +34,7 @@ class SocketSideEffectTest: XCTestCase { expect.fulfill() } - socket.parseSocketMessage("30[\"hello world\"]") + manager.parseEngineMessage("30[\"hello world\"]") waitForExpectations(timeout: 3, handler: nil) } @@ -45,8 +45,8 @@ class SocketSideEffectTest: XCTestCase { expect.fulfill() } - socket.parseSocketMessage("61-0[{\"_placeholder\":true,\"num\":0},{\"test\":true}]") - socket.parseBinaryData(Data()) + manager.parseEngineMessage("61-0[{\"_placeholder\":true,\"num\":0},{\"test\":true}]") + manager.parseEngineBinaryData(Data()) waitForExpectations(timeout: 3, handler: nil) } @@ -57,7 +57,7 @@ class SocketSideEffectTest: XCTestCase { expect.fulfill() } - socket.parseSocketMessage("2[\"test\",\"hello world\"]") + manager.parseEngineMessage("2[\"test\",\"hello world\"]") waitForExpectations(timeout: 3, handler: nil) } @@ -68,7 +68,7 @@ class SocketSideEffectTest: XCTestCase { expect.fulfill() } - socket.parseSocketMessage("2[\"test\",\"\\\"hello world\\\"\"]") + manager.parseEngineMessage("2[\"test\",\"\\\"hello world\\\"\"]") waitForExpectations(timeout: 3, handler: nil) } @@ -80,7 +80,7 @@ class SocketSideEffectTest: XCTestCase { expect.fulfill() } - socket.parseSocketMessage("2[\"test\",\"hello world\"]") + manager.parseEngineMessage("2[\"test\",\"hello world\"]") waitForExpectations(timeout: 3, handler: nil) } @@ -96,7 +96,7 @@ class SocketSideEffectTest: XCTestCase { DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.1) { // Fake connecting - self.socket.parseEngineMessage("0/") + self.manager.parseEngineMessage("0/") } waitForExpectations(timeout: 3, handler: nil) @@ -136,59 +136,47 @@ class SocketSideEffectTest: XCTestCase { } } - socket.parseSocketMessage("4\"test error\"") + manager.parseEngineMessage("4\"test error\"") waitForExpectations(timeout: 3, handler: nil) } func testHandleBinaryEvent() { let expect = expectation(description: "handled binary event") socket.on("test") {data, ack in - if let dict = data[0] as? NSDictionary, let data = dict["test"] as? NSData { + if let dict = data[0] as? [String: Any], let data = dict["test"] as? Data { XCTAssertEqual(data as Data, self.data) expect.fulfill() } } - socket.parseSocketMessage("51-[\"test\",{\"test\":{\"_placeholder\":true,\"num\":0}}]") - socket.parseBinaryData(data) + manager.parseEngineMessage("51-[\"test\",{\"test\":{\"_placeholder\":true,\"num\":0}}]") + manager.parseEngineBinaryData(data) waitForExpectations(timeout: 3, handler: nil) } func testHandleMultipleBinaryEvent() { let expect = expectation(description: "handled multiple binary event") socket.on("test") {data, ack in - if let dict = data[0] as? NSDictionary, let data = dict["test"] as? NSData, - let data2 = dict["test2"] as? NSData { - XCTAssertEqual(data as Data, self.data) - XCTAssertEqual(data2 as Data, self.data2) - expect.fulfill() + if let dict = data[0] as? [String: Any], let data = dict["test"] as? Data, + let data2 = dict["test2"] as? Data { + XCTAssertEqual(data as Data, self.data) + XCTAssertEqual(data2 as Data, self.data2) + expect.fulfill() } } - socket.parseSocketMessage("52-[\"test\",{\"test\":{\"_placeholder\":true,\"num\":0},\"test2\":{\"_placeholder\":true,\"num\":1}}]") - socket.parseBinaryData(data) - socket.parseBinaryData(data2) + manager.parseEngineMessage("52-[\"test\",{\"test\":{\"_placeholder\":true,\"num\":0},\"test2\":{\"_placeholder\":true,\"num\":1}}]") + manager.parseEngineBinaryData(data) + manager.parseEngineBinaryData(data2) waitForExpectations(timeout: 3, handler: nil) } - func testSocketManager() { - let manager = SocketClientManager.sharedManager - manager["test"] = socket - - XCTAssert(manager["test"] === socket, "failed to get socket") - - manager["test"] = nil - - XCTAssert(manager["test"] == nil, "socket not removed") - - } - func testChangingStatusCallsStatusChangeHandler() { let expect = expectation(description: "The client should announce when the status changes") - let statusChange = SocketIOClientStatus.connecting + let statusChange = SocketIOStatus.connecting socket.on("statusChange") {data, ack in - guard let status = data[0] as? SocketIOClientStatus else { + guard let status = data[0] as? SocketIOStatus else { XCTFail("Status should be one of the defined statuses") return @@ -251,9 +239,9 @@ class SocketSideEffectTest: XCTestCase { func testConnectTimesOutIfNotConnected() { let expect = expectation(description: "The client should call the timeout function") + socket = manager.socket(forNamespace: "/someNamespace") socket.setTestStatus(.notConnected) - socket.nsp = "/someNamespace" - socket.engine = TestEngine(client: socket, url: socket.socketURL, options: nil) + manager.engine = TestEngine(client: manager, url: manager.socketURL, options: nil) socket.connect(timeoutAfter: 0.5, withHandler: { expect.fulfill() @@ -266,7 +254,7 @@ class SocketSideEffectTest: XCTestCase { let expect = expectation(description: "The client should not call the timeout function") socket.setTestStatus(.notConnected) - socket.engine = TestEngine(client: socket, url: socket.socketURL, options: nil) + manager.engine = TestEngine(client: manager, url: manager.socketURL, options: nil) socket.on(clientEvent: .connect) {data, ack in expect.fulfill() @@ -278,7 +266,7 @@ class SocketSideEffectTest: XCTestCase { DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.1) { // Fake connecting - self.socket.parseEngineMessage("0/") + self.manager.parseEngineMessage("0/") } waitForExpectations(timeout: 2) @@ -288,7 +276,7 @@ class SocketSideEffectTest: XCTestCase { let expect = expectation(description: "The client call the connect handler") socket.setTestStatus(.notConnected) - socket.engine = TestEngine(client: socket, url: socket.socketURL, options: nil) + manager.engine = TestEngine(client: manager, url: manager.socketURL, options: nil) socket.on(clientEvent: .connect) {data, ack in expect.fulfill() @@ -305,9 +293,9 @@ class SocketSideEffectTest: XCTestCase { let expect = expectation(description: "The client should not call the timeout function") let nspString = "/swift" + socket = manager.socket(forNamespace: "/swift") socket.setTestStatus(.notConnected) - socket.nsp = nspString - socket.engine = TestEngine(client: socket, url: socket.socketURL, options: nil) + manager.engine = TestEngine(client: manager, url: manager.socketURL, options: nil) socket.on(clientEvent: .connect) {data, ack in guard let nsp = data[0] as? String else { @@ -327,7 +315,7 @@ class SocketSideEffectTest: XCTestCase { DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.1) { // Fake connecting - self.socket.parseEngineMessage("0/swift") + self.manager.parseEngineMessage("0/swift") } waitForExpectations(timeout: 2) @@ -377,48 +365,68 @@ class SocketSideEffectTest: XCTestCase { func testSettingConfigAfterInit() { socket.setTestStatus(.notConnected) - socket.config.insert(.log(true)) + manager.config.insert(.log(true)) XCTAssertTrue(DefaultSocketLogger.Logger.log, "It should set logging to true after creation") - socket.config = [.log(false), .nsp("/test")] + manager.config = [.log(false)] XCTAssertFalse(DefaultSocketLogger.Logger.log, "It should set logging to false after creation") - XCTAssertEqual(socket.nsp, "/test", "It should set the namespace after creation") } - func testSettingExtraHeadersAfterInit() { - socket.setTestStatus(.notConnected) - socket.config = [.extraHeaders(["new": "value"])] - socket.config.insert(.extraHeaders(["hello": "world"]), replacing: true) + func testSettingConfigAfterDisconnect() { + socket.setTestStatus(.disconnected) + manager.config.insert(.log(true)) - for config in socket.config { - switch config { - case let .extraHeaders(headers): - XCTAssertTrue(headers.keys.contains("hello"), "It should contain hello header key") - XCTAssertFalse(headers.keys.contains("new"), "It should not contain old data") - case .path: - continue - default: - XCTFail("It should only have two configs") - } + XCTAssertTrue(DefaultSocketLogger.Logger.log, "It should set logging to true after creation") + + manager.config = [.log(false)] + + XCTAssertFalse(DefaultSocketLogger.Logger.log, "It should set logging to false after creation") + } + + func testSettingConfigAfterInitWhenConnectedDoesNotIgnoreChanges() { + manager.setTestStatus(.connected) + manager.config = [.log(true)] + + XCTAssertTrue(DefaultSocketLogger.Logger.log, "It should set logging to false after creation") + } + + func testClientCallsSentPingHandler() { + let expect = expectation(description: "The client should emit a ping event") + + socket.on(clientEvent: .ping) {data, ack in + expect.fulfill() } + + manager.engineDidSendPing() + + waitForExpectations(timeout: 0.2) } - func testSettingConfigAfterInitWhenConnectedIgnoresChanges() { - socket.config = [.log(true), .nsp("/test")] + func testClientCallsGotPongHandler() { + let expect = expectation(description: "The client should emit a pong event") - XCTAssertFalse(DefaultSocketLogger.Logger.log, "It should set logging to false after creation") - XCTAssertEqual(socket.nsp, "/", "It should set the namespace after creation") + socket.on(clientEvent: .pong) {data, ack in + expect.fulfill() + } + + manager.engineDidReceivePong() + + waitForExpectations(timeout: 0.2) } let data = "test".data(using: String.Encoding.utf8)! let data2 = "test2".data(using: String.Encoding.utf8)! + + private var manager: SocketManager! private var socket: SocketIOClient! override func setUp() { super.setUp() - socket = SocketIOClient(socketURL: URL(string: "http://localhost/")!) + + manager = SocketManager(socketURL: URL(string: "http://localhost/")!, config: [.log(false)]) + socket = manager.defaultSocket socket.setTestable() } } @@ -437,6 +445,7 @@ struct ThrowingData : SocketData { class TestEngine : SocketEngineSpec { weak var client: SocketEngineClient? private(set) var closed = false + private(set) var compress = false private(set) var connected = false var connectParams: [String: Any]? = nil private(set) var cookies: [HTTPCookie]? = nil @@ -454,7 +463,7 @@ class TestEngine : SocketEngineSpec { private(set) var websocket = false private(set) var ws: WebSocket? = nil - required init(client: SocketEngineClient, url: URL, options: NSDictionary?) { + required init(client: SocketEngineClient, url: URL, options: [String: Any]?) { self.client = client } diff --git a/Tests/TestSocketIOObjc/ManagerObjectiveCTest.h b/Tests/TestSocketIOObjc/ManagerObjectiveCTest.h new file mode 100644 index 0000000..e715321 --- /dev/null +++ b/Tests/TestSocketIOObjc/ManagerObjectiveCTest.h @@ -0,0 +1,16 @@ +// +// Created by Erik Little on 10/21/17. +// + +#import "SocketIO_Tests-Swift.h" + +@import XCTest; +@import SocketIO; + +@interface ManagerObjectiveCTest : XCTestCase + +@property TestSocket* socket; +@property TestSocket* socket2; +@property TestManager* manager; + +@end diff --git a/Tests/TestSocketIOObjc/ManagerObjectiveCTest.m b/Tests/TestSocketIOObjc/ManagerObjectiveCTest.m new file mode 100644 index 0000000..9410ad0 --- /dev/null +++ b/Tests/TestSocketIOObjc/ManagerObjectiveCTest.m @@ -0,0 +1,122 @@ +// +// Created by Erik Little on 10/21/17. +// + +#import "ManagerObjectiveCTest.h" + +@import Dispatch; +@import Foundation; +@import XCTest; +@import SocketIO; + +@implementation ManagerObjectiveCTest + +- (void)testSettingConfig { + NSURL* url = [[NSURL alloc] initWithString:@"http://localhost"]; + self.manager = [[TestManager alloc] initWithSocketURL:url config:@{@"forceNew": @YES}]; + + XCTAssertTrue(self.manager.forceNew); +} + +- (void)testManagerProperties { + XCTAssertNotNil(self.manager.defaultSocket); + XCTAssertNil(self.manager.engine); + XCTAssertFalse(self.manager.forceNew); + XCTAssertEqual(self.manager.handleQueue, dispatch_get_main_queue()); + XCTAssertTrue(self.manager.reconnects); + XCTAssertEqual(self.manager.reconnectWait, 10); + XCTAssertEqual(self.manager.status, SocketIOStatusNotConnected); +} + +- (void)testConnectSocketSyntax { + [self setUpSockets]; + [self.manager connectSocket:self.socket]; +} + +- (void)testDisconnectSocketSyntax { + [self setUpSockets]; + [self.manager disconnectSocket:self.socket]; +} + +- (void)testSocketForNamespaceSyntax { + SocketIOClient* client = [self.manager socketForNamespace:@"/swift"]; + client = nil; +} + +- (void)testManagerCallsConnect { + [self setUpSockets]; + + XCTestExpectation* expect = [self expectationWithDescription:@"The manager should call connect on the default socket"]; + XCTestExpectation* expect2 = [self expectationWithDescription:@"The manager should call connect on the socket"]; + + self.socket.expects[@"didConnectCalled"] = expect; + self.socket2.expects[@"didConnectCalled"] = expect2; + + [self.socket connect]; + [self.socket2 connect]; + + [self.manager fakeConnecting]; + [self.manager fakeConnectingToNamespace:@"/swift"]; + + [self waitForExpectationsWithTimeout:0.3 handler:nil]; +} + +- (void)testManagerCallsDisconnect { + [self setUpSockets]; + + XCTestExpectation* expect = [self expectationWithDescription:@"The manager should call disconnect on the default socket"]; + XCTestExpectation* expect2 = [self expectationWithDescription:@"The manager should call disconnect on the socket"]; + + self.socket.expects[@"didDisconnectCalled"] = expect; + self.socket2.expects[@"didDisconnectCalled"] = expect2; + + [self.socket2 on:@"connect" callback:^(NSArray* data, SocketAckEmitter* ack) { + [self.manager disconnect]; + [self.manager fakeDisconnecting]; + }]; + + [self.socket connect]; + [self.socket2 connect]; + + [self.manager fakeConnecting]; + [self.manager fakeConnectingToNamespace:@"/swift"]; + + [self waitForExpectationsWithTimeout:0.3 handler:nil]; +} + +- (void)testManagerEmitAll { + [self setUpSockets]; + + XCTestExpectation* expect = [self expectationWithDescription:@"The manager should emit an event to the default socket"]; + XCTestExpectation* expect2 = [self expectationWithDescription:@"The manager should emit an event to the socket"]; + + self.socket.expects[@"emitAllEventCalled"] = expect; + self.socket2.expects[@"emitAllEventCalled"] = expect2; + + [self.socket2 on:@"connect" callback:^(NSArray* data, SocketAckEmitter* ack) { + [self.manager emitAll:@"event" withItems:@[@"testing"]]; + }]; + + [self.socket connect]; + [self.socket2 connect]; + + [self.manager fakeConnecting]; + [self.manager fakeConnectingToNamespace:@"/swift"]; + + [self waitForExpectationsWithTimeout:0.3 handler:nil]; +} + +- (void)setUpSockets { + self.socket = [self.manager testSocketForNamespace:@"/"]; + self.socket2 = [self.manager testSocketForNamespace:@"/swift"]; +} + +- (void)setUp { + [super setUp]; + NSURL* url = [[NSURL alloc] initWithString:@"http://localhost"]; + self.manager = [[TestManager alloc] initWithSocketURL:url config:@{@"log": @NO}]; + self.socket = nil; + self.socket2 = nil; +} + +@end diff --git a/Tests/TestSocketIOObjc/SocketObjectiveCTest.h b/Tests/TestSocketIOObjc/SocketObjectiveCTest.h new file mode 100644 index 0000000..1d0de3e --- /dev/null +++ b/Tests/TestSocketIOObjc/SocketObjectiveCTest.h @@ -0,0 +1,16 @@ +// +// Created by Erik Little on 10/21/17. +// + + +@import Dispatch; +@import Foundation; +@import XCTest; +@import SocketIO; + +@interface SocketObjectiveCTest : XCTestCase + +@property SocketIOClient* socket; +@property SocketManager* manager; + +@end diff --git a/Tests/TestSocketIOObjc/SocketObjectiveCTest.m b/Tests/TestSocketIOObjc/SocketObjectiveCTest.m index 6246701..7e18359 100644 --- a/Tests/TestSocketIOObjc/SocketObjectiveCTest.m +++ b/Tests/TestSocketIOObjc/SocketObjectiveCTest.m @@ -7,36 +7,20 @@ // Merely tests whether the Objective-C api breaks // +#import "SocketObjectiveCTest.h" + @import Dispatch; @import Foundation; @import XCTest; @import SocketIO; -@interface SocketObjectiveCTest : XCTestCase - -@property SocketIOClient* socket; - -@end +// TODO Manager interface tests @implementation SocketObjectiveCTest -- (void)setUp { - [super setUp]; - NSURL* url = [[NSURL alloc] initWithString:@"http://localhost"]; - self.socket = [[SocketIOClient alloc] initWithSocketURL:url config:@{@"log": @NO, @"forcePolling": @YES}]; -} - - (void)testProperties { - NSURL* url = nil; - - url = self.socket.socketURL; - self.socket.forceNew = false; - self.socket.handleQueue = dispatch_get_main_queue(); - self.socket.nsp = @"/objective-c"; - self.socket.reconnects = false; - self.socket.reconnectWait = 1; - if (self.socket.status == SocketIOClientStatusConnected) { } - if (self.socket.engine == NULL) { } + XCTAssertTrue([self.socket.nsp isEqualToString:@"/"]); + XCTAssertEqual(self.socket.status, SocketIOStatusNotConnected); } - (void)testOnSyntax { @@ -62,7 +46,7 @@ } - (void)testJoinNamespaceSyntax { - [self.socket joinNamespace:@"/objective-c"]; + [self.socket joinNamespace]; } - (void)testOnAnySyntax { @@ -74,10 +58,6 @@ }]; } -- (void)testReconnectSyntax { - [self.socket reconnect]; -} - - (void)testRemoveAllHandlersSyntax { [self.socket removeAllHandlers]; } @@ -94,15 +74,16 @@ [self.socket off:@"test"]; } -- (void)testSocketManager { - SocketClientManager* manager = [SocketClientManager sharedManager]; - [manager addSocket:self.socket labeledAs:@"test"]; - [manager removeSocketWithLabel:@"test"]; -} - - (void)testSSLSecurity { SSLSecurity* sec = [[SSLSecurity alloc] initWithUsePublicKeys:0]; sec = nil; } +- (void)setUp { + [super setUp]; + NSURL* url = [[NSURL alloc] initWithString:@"http://localhost"]; + self.manager = [[SocketManager alloc] initWithSocketURL:url config:@{@"log": @NO}]; + self.socket = [self.manager defaultSocket]; +} + @end diff --git a/Usage Docs/12to13.md b/Usage Docs/12to13.md new file mode 100644 index 0000000..740ab62 --- /dev/null +++ b/Usage Docs/12to13.md @@ -0,0 +1,109 @@ +# Upgrading from v12 + +This guide will help you navigate the changes that were introduced in v13. + +## What are the big changes? + +The biggest change is how to create and manage clients. Much like the native JS client and server, +the swift client now only uses one engine per connection. Previously in order to use namespaces it was required +to create multiple clients, and each client had its own engine. + +Some v12 code might've looked like this: + +```swift +let defaultSocket = SocketIOClient(socketURL: myURL) +let namespaceSocket = SocketIOClient(socketURL: myURL, config: [.nsp("/swift")]) + +// add handlers for sockets and connect + +``` + +In v12 this would have opened two connections to the socket.io. + + +In v13 the same code would look like this: + +```swift +let manager = SocketManager(socketURL: myURL) +let defaultSocket = manager.defaultSocket +let namespaceSocket = manager.socket(forNamespace: "/swift") + +// add handlers for sockets and connect +``` + +In v13 `defaultSocket` and `namespaceSocket` will share a single transport. This means one less connection to the server +needs to be opened. + +## What might I have to change? + +- The most obvious thing you will need to change is that instead of creating `SocketIOClient`s directly, you will create a +`SocketManager` and either use the `defaultSocket` property if you don't need namespaces, or call the +`socket(forNamespace:)` method on the manager. + +- `SocketIOClient` is no longer a client to an engine. So if you were overriding the engine methods, these have been moved +to the manager. + +- The library is now a single target. So you might have to change some of your Xcode project settings. + +- `SocketIOClient`s no longer take a configuration, they are shared from the manager. + +- The `joinNamespace()` and `leaveNamespace()` methods on `SocketIOClient` no longer take any arguments, and in most cases +no longer need to be called. Namespace joining/leaving can be managed by calling `connect()`/`disconnect()` on the socket +associated with that namespace. + +---------- + +# What things should I know? + +How sockets are stored +--- + +You should know that `SocketIOClient`s no longer need to be held around in properties, but the `SocketManager` should. + +One of the most common mistakes people made is not maintaining a strong reference to the client. + +```swift +class Manager { + func addHandlers() { + let socket = SocketIOClient(socketURL: myURL, config: [.nsp("/swift")]) + + // Add handlers + } +} +``` + +This would have resulted in the client being released and no handlers being called. + +A *correct* equivalent would be: + +```swift +class Manager { + let socketManager = SocketManager(socketURL: someURL) + + func addHandlers() { + let socket = socketManager.socket(forNamespace: "/swift") + + // Add handlers + } +} +``` + +This code is fine because the `SocketManager` will maintain a strong reference to the socket. + +It's also worth noting that subsequent calls to `socket(forNamespace:)` will return the *same* socket instance as the +first call. So you don't need to hold onto the socket directly just to access it again, just call `socket(forNamespace:)` +on the manager to get it. **This does mean that if you need multiple sockets on the same namespace, you will have to use +multiple managers.** + +What to call connect on +--- + +Connect can either be called on the manager directly, or on one of the sockets made from it. In either case, if the manager +was not already connected to the server, a connection will be made. Also in both cases the default socket (namespace "/") +will fire a `connect` event. + +The difference is that if `connect()` is just called on the manager, then any sockets for that manager that are not the default +socket will not automatically connect. `connect()` will need to be called individually for each socket. However, if `connect()` +is called on a client, then in addition to opening the connection if needed, the client will connect to the its namespace, +and a `connect` event fired. + diff --git a/Usage Docs/FAQ.md b/Usage Docs/FAQ.md index 1090073..dc4f741 100644 --- a/Usage Docs/FAQ.md +++ b/Usage Docs/FAQ.md @@ -13,11 +13,11 @@ One of the most common reasons your event might not be called is if the client i Take this code for example: ```swift -class SocketManager { +class Manager { func addHandlers() { - let socket = SocketIOClient(socketURL: URL(string: "http://somesocketioserver.com")!) + let manager = SocketManager(socketURL: URL(string: "http://somesocketioserver.com")!) - socket.on("myEvent") {data, ack in + manager.defaultSocket.on("myEvent") {data, ack in print(data) } } @@ -25,30 +25,20 @@ class SocketManager { } ``` -This code is **incorrect**, and the event handler will never be called. Because as soon as this method is called `socket` -will be released and its memory reclaimed. +This code is **incorrect**, and the event handler will never be called. Because as soon as this method is called `manager` +will be released, along with the socket, and its memory reclaimed. A correct way would be: ```swift -class SocketManager { - let socket = SocketIOClient(socketURL: URL(string: "http://somesocketioserver.com")!) +class Manager { + let manager = SocketManager(socketURL: URL(string: "http://somesocketioserver.com")!) func addHandlers() { - socket.on("myEvent") {data, ack in + manager.defaultSocket.on("myEvent") {data, ack in print(data) } } } ``` - ------- - -Another case where this might happen is if you use namespaces in your socket.io application. - -In the JavaScript client a url that looks like `http://somesocketioserver.com/client` would be done with the `nsp` config. - -```swift -let socket = SocketIOClient(socketURL: URL(string: "http://somesocketioserver.com")!, config: [.nsp("/client")]) -```