diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index f50bfa7ca..286876617 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -23,6 +23,7 @@ jobs:
- test:facebook_utils:ios
- test:twitter_utils:ios
- test:parseui:all
+ - test:parse_live_query:all
- package:release
fail-fast: false
runs-on: ${{ (matrix.script == 'package:release' && 'macos-11') || 'macos-12' }}
diff --git a/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata b/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 000000000..919434a62
--- /dev/null
+++ b/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/Cartfile b/Cartfile
index 4cc9402f3..19539dfd3 100644
--- a/Cartfile
+++ b/Cartfile
@@ -1,3 +1,5 @@
github "BoltsFramework/Bolts-ObjC" ~> 1.9.1
+github "BoltsFramework/Bolts-Swift" >= 1.5.0
github "facebook/facebook-ios-sdk" == 15.1.0
+github "daltoniam/Starscream" >= 4.0.4
diff --git a/Cartfile.resolved b/Cartfile.resolved
index cea6faaa8..b0b344042 100644
--- a/Cartfile.resolved
+++ b/Cartfile.resolved
@@ -1,2 +1,4 @@
github "BoltsFramework/Bolts-ObjC" "1.9.1"
+github "BoltsFramework/Bolts-Swift" "1.5.0"
+github "daltoniam/Starscream" "4.0.4"
github "facebook/facebook-ios-sdk" "v15.1.0"
diff --git a/Package.resolved b/Package.resolved
index b9cb840bb..8a581d81d 100644
--- a/Package.resolved
+++ b/Package.resolved
@@ -3,11 +3,20 @@
"pins": [
{
"package": "Bolts",
- "repositoryURL": "https://github.com/rocxteady/Bolts-ObjC",
+ "repositoryURL": "https://github.com/parse-community/Bolts-ObjC.git",
"state": {
"branch": null,
- "revision": "0419586ce3df0a004fbf94533198132de9c9aa0a",
- "version": null
+ "revision": "1eee96ad3bcfc8964c0a5815ce94f491eb6ac8c2",
+ "version": "1.10.0"
+ }
+ },
+ {
+ "package": "BoltsSwift",
+ "repositoryURL": "https://github.com/BoltsFramework/Bolts-Swift.git",
+ "state": {
+ "branch": null,
+ "revision": "d8c07eee2045a13f34330c0a4664053b5176e3f0",
+ "version": "1.5.0"
}
},
{
@@ -18,6 +27,15 @@
"revision": "7fd8a930a5b2c940a22efafe0e214ed0df671312",
"version": "15.1.0"
}
+ },
+ {
+ "package": "Starscream",
+ "repositoryURL": "https://github.com/daltoniam/Starscream.git",
+ "state": {
+ "branch": null,
+ "revision": "df8d82047f6654d8e4b655d1b1525c64e1059d21",
+ "version": "4.0.4"
+ }
}
]
},
diff --git a/Package.swift b/Package.swift
index a81ae1796..668117b1e 100644
--- a/Package.swift
+++ b/Package.swift
@@ -6,7 +6,7 @@ let package = Package(
name: "ParseObjC",
defaultLocalization: "en",
platforms: [.iOS(.v12),
- .macOS(.v10_10),
+ .macOS(.v10_15),
.tvOS(.v12),
.watchOS(.v2)],
products: [
@@ -14,10 +14,13 @@ let package = Package(
.library(name: "ParseFacebookUtilsiOS", targets: ["ParseFacebookUtilsiOS"]),
.library(name: "ParseFacebookUtilsTvOS", targets: ["ParseFacebookUtilsTvOS"]),
.library(name: "ParseTwitterUtils", targets: ["ParseTwitterUtils"]),
- .library(name: "ParseUI", targets: ["ParseUI"])
+ .library(name: "ParseUI", targets: ["ParseUI"]),
+ .library(name: "ParseLiveQuery", targets: ["ParseLiveQuery"])
],
dependencies: [
.package(url: "https://github.com/parse-community/Bolts-ObjC.git", from: "1.10.0"),
+ .package(url: "https://github.com/BoltsFramework/Bolts-Swift.git", from: "1.5.0"),
+ .package(url: "https://github.com/daltoniam/Starscream.git", from: "4.0.4"),
.package(url: "https://github.com/facebook/facebook-ios-sdk.git", from: "15.1.0")
],
targets: [
@@ -37,7 +40,7 @@ let package = Package(
.product(name: "FacebookCore", package: "facebook-ios-sdk", condition: .when(platforms: [.iOS, .tvOS])),
.product(name: "FacebookLogin", package: "facebook-ios-sdk", condition: .when(platforms: [.iOS, .tvOS]))],
path: "ParseFacebookUtils/ParseFacebookUtils",
- exclude: ["exclude", "Resources/Info-tvOS.plist", "Resources/Info-iOS.plist"],
+ exclude: ["Resources/Info-tvOS.plist", "Resources/Info-iOS.plist"],
resources: [.process("Resources")],
publicHeadersPath: "Source"),
.target(name: "ParseFacebookUtilsiOS",
@@ -45,7 +48,7 @@ let package = Package(
"ParseFacebookUtils"
],
path: "ParseFacebookUtilsiOS/ParseFacebookUtilsiOS",
- exclude: ["exclude", "Resources/Info-iOS.plist"],
+ exclude: ["Resources/Info-iOS.plist"],
resources: [.process("Resources")],
publicHeadersPath: "Source",
cSettings: [.headerSearchPath("Internal/**")]),
@@ -55,7 +58,7 @@ let package = Package(
.product(name: "FacebookTV", package: "facebook-ios-sdk", condition: .when(platforms: [.tvOS]))
],
path: "ParseFacebookUtilsTvOS/ParseFacebookUtilsTvOS",
- exclude: ["exclude", "Resources/Info-tvOS.plist"],
+ exclude: ["Resources/Info-tvOS.plist"],
resources: [.process("Resources")],
publicHeadersPath: "Source",
cSettings: [.headerSearchPath("Internal/**")]),
@@ -78,5 +81,14 @@ let package = Package(
resources: [.process("Resources")],
publicHeadersPath: "Source",
cSettings: [.headerSearchPath("Internal/**")]),
+ .target(name: "ParseLiveQuery",
+ dependencies: [
+ .product(name: "BoltsSwift", package: "Bolts-Swift"),
+ "Starscream",
+ "ParseCore"
+ ],
+ path: "ParseLiveQuery/ParseLiveQuery",
+ exclude: ["Resources/Info.plist"],
+ resources: [.process("Resources")])
]
)
diff --git a/Parse.xcworkspace/contents.xcworkspacedata b/Parse.xcworkspace/contents.xcworkspacedata
index 5a6b81197..0344fa5af 100644
--- a/Parse.xcworkspace/contents.xcworkspacedata
+++ b/Parse.xcworkspace/contents.xcworkspacedata
@@ -16,6 +16,9 @@
+
+
diff --git a/Parse/Parse.xcodeproj/project.pbxproj b/Parse/Parse.xcodeproj/project.pbxproj
index 82e7d358d..0b665bcca 100644
--- a/Parse/Parse.xcodeproj/project.pbxproj
+++ b/Parse/Parse.xcodeproj/project.pbxproj
@@ -2962,6 +2962,69 @@
remoteGlobalIDString = 81C3821B19CCA89E0066284A;
remoteInfo = "Parse-iOS";
};
+ 9575FF1E299136C60057B4CE /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 9575FF10299136C60057B4CE /* Starscream.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 33CCF0921F5DDC030099B092;
+ remoteInfo = Starscream;
+ };
+ 9575FF20299136C60057B4CE /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 9575FF10299136C60057B4CE /* Starscream.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 335FA2021F5DF71D00F6D2EC;
+ remoteInfo = "Starscream Tests";
+ };
+ 95AEEB192991373F00165C0D /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 95AEEB0F2991373F00165C0D /* BoltsSwift.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 87FEF3661A9085FA00C60678;
+ remoteInfo = "BoltsSwift-iOS";
+ };
+ 95AEEB1B2991373F00165C0D /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 95AEEB0F2991373F00165C0D /* BoltsSwift.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 87FEF3711A9085FA00C60678;
+ remoteInfo = "BoltsSwiftTests-iOS";
+ };
+ 95AEEB1D2991373F00165C0D /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 95AEEB0F2991373F00165C0D /* BoltsSwift.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 81CC14EC1A9BE0A100B28F86;
+ remoteInfo = "BoltsSwift-macOS";
+ };
+ 95AEEB1F2991373F00165C0D /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 95AEEB0F2991373F00165C0D /* BoltsSwift.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 81CC14F61A9BE0A100B28F86;
+ remoteInfo = "BoltsSwiftTests-macOS";
+ };
+ 95AEEB212991373F00165C0D /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 95AEEB0F2991373F00165C0D /* BoltsSwift.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 065894FF1C9A93B7000FDDA6;
+ remoteInfo = "BoltsSwift-tvOS";
+ };
+ 95AEEB232991373F00165C0D /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 95AEEB0F2991373F00165C0D /* BoltsSwift.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 0658951B1C9A947B000FDDA6;
+ remoteInfo = "BoltsSwiftTests-tvOS";
+ };
+ 95AEEB252991373F00165C0D /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 95AEEB0F2991373F00165C0D /* BoltsSwift.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 065894E71C9A933B000FDDA6;
+ remoteInfo = "BoltsSwift-watchOS";
+ };
BC105FC424C5D0C900295EF7 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = BC105FBA24C5D0C900295EF7 /* OCMock.xcodeproj */;
@@ -3575,6 +3638,8 @@
91DF24941A09BAF100CFC7D4 /* PFPinningEventuallyQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PFPinningEventuallyQueue.h; sourceTree = ""; };
91DF24951A09BAF100CFC7D4 /* PFPinningEventuallyQueue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PFPinningEventuallyQueue.m; sourceTree = ""; };
91DF24981A0B0FF200CFC7D4 /* PFEventuallyQueue_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PFEventuallyQueue_Private.h; sourceTree = ""; };
+ 9575FF10299136C60057B4CE /* Starscream.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Starscream.xcodeproj; path = ../Carthage/Checkouts/Starscream/Starscream.xcodeproj; sourceTree = ""; };
+ 95AEEB0F2991373F00165C0D /* BoltsSwift.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = BoltsSwift.xcodeproj; path = "../Carthage/Checkouts/Bolts-Swift/BoltsSwift.xcodeproj"; sourceTree = ""; };
97010FAC1630B18F00AB761E /* Parse.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Parse.framework; sourceTree = BUILT_PRODUCTS_DIR; };
97AA93B816780B7600445C2D /* Parse-OSX.Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Parse-OSX.Info.plist"; sourceTree = ""; };
97E18AE41623835600B17A67 /* PFLocationManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PFLocationManager.h; sourceTree = ""; };
@@ -3872,6 +3937,8 @@
7CE6ABDD292074C70054D9D2 /* AudioToolbox.framework */,
7CE6ABD2292074C10054D9D2 /* libsqlite3.tbd */,
BC105FBA24C5D0C900295EF7 /* OCMock.xcodeproj */,
+ 9575FF10299136C60057B4CE /* Starscream.xcodeproj */,
+ 95AEEB0F2991373F00165C0D /* BoltsSwift.xcodeproj */,
4A1351082027FCFB000F5FD5 /* Bolts.xcodeproj */,
);
name = Frameworks;
@@ -5148,6 +5215,29 @@
path = CurrentUserController;
sourceTree = "";
};
+ 9575FF11299136C60057B4CE /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 9575FF1F299136C60057B4CE /* Starscream.framework */,
+ 9575FF21299136C60057B4CE /* Starscream Tests.xctest */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ 95AEEB102991373F00165C0D /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 95AEEB1A2991373F00165C0D /* BoltsSwift.framework */,
+ 95AEEB1C2991373F00165C0D /* BoltsSwiftTests.xctest */,
+ 95AEEB1E2991373F00165C0D /* BoltsSwift.framework */,
+ 95AEEB202991373F00165C0D /* BoltsSwiftTests.xctest */,
+ 95AEEB222991373F00165C0D /* BoltsSwift.framework */,
+ 95AEEB242991373F00165C0D /* BoltsSwiftTests.xctest */,
+ 95AEEB262991373F00165C0D /* BoltsSwift.framework */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
BC105FBB24C5D0C900295EF7 /* Products */ = {
isa = PBXGroup;
children = (
@@ -7076,10 +7166,18 @@
ProductGroup = 4A13517620281768000F5FD5 /* Products */;
ProjectRef = 4A1351082027FCFB000F5FD5 /* Bolts.xcodeproj */;
},
+ {
+ ProductGroup = 95AEEB102991373F00165C0D /* Products */;
+ ProjectRef = 95AEEB0F2991373F00165C0D /* BoltsSwift.xcodeproj */;
+ },
{
ProductGroup = BC105FBB24C5D0C900295EF7 /* Products */;
ProjectRef = BC105FBA24C5D0C900295EF7 /* OCMock.xcodeproj */;
},
+ {
+ ProductGroup = 9575FF11299136C60057B4CE /* Products */;
+ ProjectRef = 9575FF10299136C60057B4CE /* Starscream.xcodeproj */;
+ },
);
projectRoot = "";
targets = (
@@ -7175,6 +7273,69 @@
remoteRef = 4A13519720281768000F5FD5 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
+ 9575FF1F299136C60057B4CE /* Starscream.framework */ = {
+ isa = PBXReferenceProxy;
+ fileType = wrapper.framework;
+ path = Starscream.framework;
+ remoteRef = 9575FF1E299136C60057B4CE /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 9575FF21299136C60057B4CE /* Starscream Tests.xctest */ = {
+ isa = PBXReferenceProxy;
+ fileType = wrapper.cfbundle;
+ path = "Starscream Tests.xctest";
+ remoteRef = 9575FF20299136C60057B4CE /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 95AEEB1A2991373F00165C0D /* BoltsSwift.framework */ = {
+ isa = PBXReferenceProxy;
+ fileType = wrapper.framework;
+ path = BoltsSwift.framework;
+ remoteRef = 95AEEB192991373F00165C0D /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 95AEEB1C2991373F00165C0D /* BoltsSwiftTests.xctest */ = {
+ isa = PBXReferenceProxy;
+ fileType = wrapper.cfbundle;
+ path = BoltsSwiftTests.xctest;
+ remoteRef = 95AEEB1B2991373F00165C0D /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 95AEEB1E2991373F00165C0D /* BoltsSwift.framework */ = {
+ isa = PBXReferenceProxy;
+ fileType = wrapper.framework;
+ path = BoltsSwift.framework;
+ remoteRef = 95AEEB1D2991373F00165C0D /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 95AEEB202991373F00165C0D /* BoltsSwiftTests.xctest */ = {
+ isa = PBXReferenceProxy;
+ fileType = wrapper.cfbundle;
+ path = BoltsSwiftTests.xctest;
+ remoteRef = 95AEEB1F2991373F00165C0D /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 95AEEB222991373F00165C0D /* BoltsSwift.framework */ = {
+ isa = PBXReferenceProxy;
+ fileType = wrapper.framework;
+ path = BoltsSwift.framework;
+ remoteRef = 95AEEB212991373F00165C0D /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 95AEEB242991373F00165C0D /* BoltsSwiftTests.xctest */ = {
+ isa = PBXReferenceProxy;
+ fileType = wrapper.cfbundle;
+ path = BoltsSwiftTests.xctest;
+ remoteRef = 95AEEB232991373F00165C0D /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 95AEEB262991373F00165C0D /* BoltsSwift.framework */ = {
+ isa = PBXReferenceProxy;
+ fileType = wrapper.framework;
+ path = BoltsSwift.framework;
+ remoteRef = 95AEEB252991373F00165C0D /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
BC105FC524C5D0C900295EF7 /* OCMock.framework */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
@@ -8868,7 +9029,7 @@
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
- MACOSX_DEPLOYMENT_TARGET = 10.9;
+ MACOSX_DEPLOYMENT_TARGET = 10.15;
};
name = Debug;
};
@@ -8885,7 +9046,7 @@
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
- MACOSX_DEPLOYMENT_TARGET = 10.9;
+ MACOSX_DEPLOYMENT_TARGET = 10.15;
SWIFT_COMPILATION_MODE = wholemodule;
};
name = Release;
@@ -9070,7 +9231,7 @@
isa = XCBuildConfiguration;
baseConfigurationReference = F55ABB5A1B4F39DA00A0ECD5 /* ParseUnitTests-macOS.xcconfig */;
buildSettings = {
- MACOSX_DEPLOYMENT_TARGET = 10.12;
+ MACOSX_DEPLOYMENT_TARGET = 10.15;
SWIFT_VERSION = 5.0;
};
name = Debug;
@@ -9079,7 +9240,7 @@
isa = XCBuildConfiguration;
baseConfigurationReference = F55ABB5A1B4F39DA00A0ECD5 /* ParseUnitTests-macOS.xcconfig */;
buildSettings = {
- MACOSX_DEPLOYMENT_TARGET = 10.12;
+ MACOSX_DEPLOYMENT_TARGET = 10.15;
SWIFT_VERSION = 5.0;
};
name = Release;
@@ -9098,7 +9259,7 @@
);
SUPPORTS_MACCATALYST = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
- SWIFT_VERSION = 5.0;
+ SWIFT_VERSION = 5.7;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
@@ -9116,7 +9277,7 @@
"@loader_path/Frameworks",
);
SUPPORTS_MACCATALYST = YES;
- SWIFT_VERSION = 5.0;
+ SWIFT_VERSION = 5.7;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
@@ -9188,7 +9349,7 @@
baseConfigurationReference = F55ABB541B4F39DA00A0ECD5 /* Parse-macOS.xcconfig */;
buildSettings = {
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
- MACOSX_DEPLOYMENT_TARGET = 10.12;
+ MACOSX_DEPLOYMENT_TARGET = 10.15;
};
name = Debug;
};
@@ -9197,7 +9358,7 @@
baseConfigurationReference = F55ABB541B4F39DA00A0ECD5 /* Parse-macOS.xcconfig */;
buildSettings = {
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
- MACOSX_DEPLOYMENT_TARGET = 10.12;
+ MACOSX_DEPLOYMENT_TARGET = 10.15;
};
name = Release;
};
diff --git a/ParseLiveQuery/Examples/LiveQueryDemo-ObjC.xcodeproj/project.pbxproj b/ParseLiveQuery/Examples/LiveQueryDemo-ObjC.xcodeproj/project.pbxproj
new file mode 100644
index 000000000..c63e2bcbf
--- /dev/null
+++ b/ParseLiveQuery/Examples/LiveQueryDemo-ObjC.xcodeproj/project.pbxproj
@@ -0,0 +1,393 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 46;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 395FFA7429D761B4006502C5 /* ParseLiveQuery.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 395FFA4429D75F1F006502C5 /* ParseLiveQuery.framework */; };
+ F509D5461CA9E5B8007B15B0 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = F519CBB41CA9CA04005295C0 /* main.m */; };
+ F509D5471CA9E5B8007B15B0 /* Message.m in Sources */ = {isa = PBXBuildFile; fileRef = F519CBBC1CA9CA2B005295C0 /* Message.m */; };
+ F509D5481CA9E5B8007B15B0 /* Room.m in Sources */ = {isa = PBXBuildFile; fileRef = F519CBBF1CA9CA34005295C0 /* Room.m */; };
+ F509D5491CA9E5B8007B15B0 /* ChatRoomManager.m in Sources */ = {isa = PBXBuildFile; fileRef = F519CBCF1CA9CC4D005295C0 /* ChatRoomManager.m */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ 395FFA4129D75F1F006502C5 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 395FFA3A29D75F1F006502C5 /* ParseLiveQuery.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = F5A9BFCA1BE0248D00E78326;
+ remoteInfo = "ParseLiveQuery-iOS";
+ };
+ 395FFA4329D75F1F006502C5 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 395FFA3A29D75F1F006502C5 /* ParseLiveQuery.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = F5903CEA1BD999C500C3EFFE;
+ remoteInfo = "ParseLiveQuery-OSX";
+ };
+ 395FFA4529D75F1F006502C5 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 395FFA3A29D75F1F006502C5 /* ParseLiveQuery.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 708836722561F502005B32F0;
+ remoteInfo = "ParseLiveQuery-watchOS";
+ };
+ 395FFA4729D75F1F006502C5 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 395FFA3A29D75F1F006502C5 /* ParseLiveQuery.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 708836942561F55B005B32F0;
+ remoteInfo = "ParseLiveQuery-tvOS";
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXFileReference section */
+ 395FFA3A29D75F1F006502C5 /* ParseLiveQuery.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = ParseLiveQuery.xcodeproj; path = ../ParseLiveQuery.xcodeproj; sourceTree = ""; };
+ F509D5321CA9E597007B15B0 /* LiveQueryDemo-ObjC.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "LiveQueryDemo-ObjC.app"; sourceTree = BUILT_PRODUCTS_DIR; };
+ F509D5441CA9E5AF007B15B0 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+ F519CBB41CA9CA04005295C0 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
+ F519CBBB1CA9CA2B005295C0 /* Message.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Message.h; sourceTree = ""; };
+ F519CBBC1CA9CA2B005295C0 /* Message.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Message.m; sourceTree = ""; };
+ F519CBBE1CA9CA34005295C0 /* Room.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Room.h; sourceTree = ""; };
+ F519CBBF1CA9CA34005295C0 /* Room.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Room.m; sourceTree = ""; };
+ F519CBCE1CA9CC4D005295C0 /* ChatRoomManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ChatRoomManager.h; sourceTree = ""; };
+ F519CBCF1CA9CC4D005295C0 /* ChatRoomManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ChatRoomManager.m; sourceTree = ""; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ F509D52F1CA9E597007B15B0 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 395FFA7429D761B4006502C5 /* ParseLiveQuery.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 395FFA3B29D75F1F006502C5 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 395FFA4229D75F1F006502C5 /* ParseLiveQuery.framework */,
+ 395FFA4429D75F1F006502C5 /* ParseLiveQuery.framework */,
+ 395FFA4629D75F1F006502C5 /* ParseLiveQuery_watchOS.framework */,
+ 395FFA4829D75F1F006502C5 /* ParseLiveQuery_tvOS.framework */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ E0B5CD933BEBE8518E7750F2 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 395FFA3A29D75F1F006502C5 /* ParseLiveQuery.xcodeproj */,
+ );
+ name = Frameworks;
+ sourceTree = "";
+ };
+ F519CBA81CA9CA04005295C0 = {
+ isa = PBXGroup;
+ children = (
+ F519CBB31CA9CA04005295C0 /* LiveQueryDemo-ObjC */,
+ F519CBB21CA9CA04005295C0 /* Products */,
+ E0B5CD933BEBE8518E7750F2 /* Frameworks */,
+ );
+ sourceTree = "";
+ };
+ F519CBB21CA9CA04005295C0 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ F509D5321CA9E597007B15B0 /* LiveQueryDemo-ObjC.app */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ F519CBB31CA9CA04005295C0 /* LiveQueryDemo-ObjC */ = {
+ isa = PBXGroup;
+ children = (
+ F509D5441CA9E5AF007B15B0 /* Info.plist */,
+ F519CBB41CA9CA04005295C0 /* main.m */,
+ F519CBBB1CA9CA2B005295C0 /* Message.h */,
+ F519CBBC1CA9CA2B005295C0 /* Message.m */,
+ F519CBBE1CA9CA34005295C0 /* Room.h */,
+ F519CBBF1CA9CA34005295C0 /* Room.m */,
+ F519CBCE1CA9CC4D005295C0 /* ChatRoomManager.h */,
+ F519CBCF1CA9CC4D005295C0 /* ChatRoomManager.m */,
+ );
+ path = "LiveQueryDemo-ObjC";
+ sourceTree = "";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ F509D5311CA9E597007B15B0 /* LiveQueryDemo-ObjC */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = F509D5431CA9E597007B15B0 /* Build configuration list for PBXNativeTarget "LiveQueryDemo-ObjC" */;
+ buildPhases = (
+ F509D52E1CA9E597007B15B0 /* Sources */,
+ F509D52F1CA9E597007B15B0 /* Frameworks */,
+ F509D5301CA9E597007B15B0 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "LiveQueryDemo-ObjC";
+ productName = LiveQueryDemo;
+ productReference = F509D5321CA9E597007B15B0 /* LiveQueryDemo-ObjC.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ F519CBA91CA9CA04005295C0 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastUpgradeCheck = 1100;
+ ORGANIZATIONNAME = parse;
+ TargetAttributes = {
+ F509D5311CA9E597007B15B0 = {
+ CreatedOnToolsVersion = 7.3;
+ };
+ };
+ };
+ buildConfigurationList = F519CBAC1CA9CA04005295C0 /* Build configuration list for PBXProject "LiveQueryDemo-ObjC" */;
+ compatibilityVersion = "Xcode 3.2";
+ developmentRegion = en;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ Base,
+ );
+ mainGroup = F519CBA81CA9CA04005295C0;
+ productRefGroup = F519CBB21CA9CA04005295C0 /* Products */;
+ projectDirPath = "";
+ projectReferences = (
+ {
+ ProductGroup = 395FFA3B29D75F1F006502C5 /* Products */;
+ ProjectRef = 395FFA3A29D75F1F006502C5 /* ParseLiveQuery.xcodeproj */;
+ },
+ );
+ projectRoot = "";
+ targets = (
+ F509D5311CA9E597007B15B0 /* LiveQueryDemo-ObjC */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXReferenceProxy section */
+ 395FFA4229D75F1F006502C5 /* ParseLiveQuery.framework */ = {
+ isa = PBXReferenceProxy;
+ fileType = wrapper.framework;
+ path = ParseLiveQuery.framework;
+ remoteRef = 395FFA4129D75F1F006502C5 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 395FFA4429D75F1F006502C5 /* ParseLiveQuery.framework */ = {
+ isa = PBXReferenceProxy;
+ fileType = wrapper.framework;
+ path = ParseLiveQuery.framework;
+ remoteRef = 395FFA4329D75F1F006502C5 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 395FFA4629D75F1F006502C5 /* ParseLiveQuery_watchOS.framework */ = {
+ isa = PBXReferenceProxy;
+ fileType = wrapper.framework;
+ path = ParseLiveQuery_watchOS.framework;
+ remoteRef = 395FFA4529D75F1F006502C5 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 395FFA4829D75F1F006502C5 /* ParseLiveQuery_tvOS.framework */ = {
+ isa = PBXReferenceProxy;
+ fileType = wrapper.framework;
+ path = ParseLiveQuery_tvOS.framework;
+ remoteRef = 395FFA4729D75F1F006502C5 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+/* End PBXReferenceProxy section */
+
+/* Begin PBXResourcesBuildPhase section */
+ F509D5301CA9E597007B15B0 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ F509D52E1CA9E597007B15B0 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ F509D5491CA9E5B8007B15B0 /* ChatRoomManager.m in Sources */,
+ F509D5481CA9E5B8007B15B0 /* Room.m in Sources */,
+ F509D5461CA9E5B8007B15B0 /* main.m in Sources */,
+ F509D5471CA9E5B8007B15B0 /* Message.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ F509D5401CA9E597007B15B0 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_IDENTITY = "-";
+ COMBINE_HIDPI_IMAGES = YES;
+ INFOPLIST_FILE = "$(SRCROOT)/LiveQueryDemo-ObjC/Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
+ MACOSX_DEPLOYMENT_TARGET = 10.15;
+ PRODUCT_BUNDLE_IDENTIFIER = com.parse.LiveQueryDemo;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_VERSION = 4.2;
+ };
+ name = Debug;
+ };
+ F509D5411CA9E597007B15B0 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_IDENTITY = "-";
+ COMBINE_HIDPI_IMAGES = YES;
+ INFOPLIST_FILE = "$(SRCROOT)/LiveQueryDemo-ObjC/Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
+ MACOSX_DEPLOYMENT_TARGET = 10.15;
+ PRODUCT_BUNDLE_IDENTIFIER = com.parse.LiveQueryDemo;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_VERSION = 4.2;
+ };
+ name = Release;
+ };
+ F519CBB61CA9CA04005295C0 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ CODE_SIGN_IDENTITY = "-";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ 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_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;
+ MACOSX_DEPLOYMENT_TARGET = 10.15;
+ MTL_ENABLE_DEBUG_INFO = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = macosx;
+ };
+ name = Debug;
+ };
+ F519CBB71CA9CA04005295C0 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ CODE_SIGN_IDENTITY = "-";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ 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;
+ MACOSX_DEPLOYMENT_TARGET = 10.15;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ SDKROOT = macosx;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ F509D5431CA9E597007B15B0 /* Build configuration list for PBXNativeTarget "LiveQueryDemo-ObjC" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ F509D5401CA9E597007B15B0 /* Debug */,
+ F509D5411CA9E597007B15B0 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ F519CBAC1CA9CA04005295C0 /* Build configuration list for PBXProject "LiveQueryDemo-ObjC" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ F519CBB61CA9CA04005295C0 /* Debug */,
+ F519CBB71CA9CA04005295C0 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = F519CBA91CA9CA04005295C0 /* Project object */;
+}
diff --git a/ParseLiveQuery/Examples/LiveQueryDemo-ObjC.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ParseLiveQuery/Examples/LiveQueryDemo-ObjC.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 000000000..18d981003
--- /dev/null
+++ b/ParseLiveQuery/Examples/LiveQueryDemo-ObjC.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+
+
+
+
+ IDEDidComputeMac32BitWarning
+
+
+
diff --git a/ParseLiveQuery/Examples/LiveQueryDemo-ObjC.xcodeproj/xcshareddata/xcschemes/LiveQueryDemo-ObjC.xcscheme b/ParseLiveQuery/Examples/LiveQueryDemo-ObjC.xcodeproj/xcshareddata/xcschemes/LiveQueryDemo-ObjC.xcscheme
new file mode 100644
index 000000000..6e7915b7b
--- /dev/null
+++ b/ParseLiveQuery/Examples/LiveQueryDemo-ObjC.xcodeproj/xcshareddata/xcschemes/LiveQueryDemo-ObjC.xcscheme
@@ -0,0 +1,87 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ParseLiveQuery/Examples/LiveQueryDemo-ObjC/ChatRoomManager.h b/ParseLiveQuery/Examples/LiveQueryDemo-ObjC/ChatRoomManager.h
new file mode 100644
index 000000000..a856ac609
--- /dev/null
+++ b/ParseLiveQuery/Examples/LiveQueryDemo-ObjC/ChatRoomManager.h
@@ -0,0 +1,46 @@
+/**
+ * Copyright (c) 2016-present, Parse, LLC.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+
+@import Foundation;
+@import ParseCore;
+@import ParseLiveQuery;
+
+#import "Message.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@class ChatRoomManager;
+
+@protocol ChatRoomManagerDataSource
+
+- (PFQuery *)queryForChatRoomManager:(ChatRoomManager *)manager;
+- (PFLiveQueryClient *)liveQueryClientForChatRoomManager:(ChatRoomManager *)manager;
+
+@end
+
+@protocol ChatRoomManagerDelegate
+
+- (void)chatRoomManager:(ChatRoomManager *)manager didReceiveMessage:(Message *)message;
+
+@end
+
+@interface ChatRoomManager : NSObject
+
+@property (nonatomic, assign, readonly, getter=isConnected) BOOL connected;
+@property (nonatomic, weak, readonly) id dataSource;
+@property (nonatomic, weak, readonly) id delegate;
+
+- (instancetype)initWithDataSource:(id)dataSource delegate:(id)delegate;
+
+- (void)connect;
+- (void)disconnect;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/ParseLiveQuery/Examples/LiveQueryDemo-ObjC/ChatRoomManager.m b/ParseLiveQuery/Examples/LiveQueryDemo-ObjC/ChatRoomManager.m
new file mode 100644
index 000000000..59d19bc3a
--- /dev/null
+++ b/ParseLiveQuery/Examples/LiveQueryDemo-ObjC/ChatRoomManager.m
@@ -0,0 +1,53 @@
+/**
+ * Copyright (c) 2016-present, Parse, LLC.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+
+#import "ChatRoomManager.h"
+
+@interface ChatRoomManager()
+
+@property (nonatomic, strong) PFLiveQueryClient *client;
+@property (nonatomic, strong) PFQuery *query;
+@property (nonatomic, strong) PFLiveQuerySubscription *subscription;
+
+@end
+
+@implementation ChatRoomManager
+
+- (instancetype)initWithDataSource:(id)dataSource delegate:(id)delegate{
+ self = [super init];
+ if (!self) return self;
+
+ _dataSource = dataSource;
+ _delegate = delegate;
+
+ return self;
+}
+
+- (BOOL)isConnected {
+ return self.subscription != nil;
+}
+
+- (void)connect {
+ self.client = [self.dataSource liveQueryClientForChatRoomManager:self];
+ self.query = [self.dataSource queryForChatRoomManager:self];
+
+ __weak typeof(self) weakSelf = self;
+
+ self.subscription = [[self.client subscribeToQuery:self.query] addCreateHandler:^(PFQuery *query, PFObject *message) {
+ [weakSelf.delegate chatRoomManager:weakSelf didReceiveMessage:(Message *)message];
+ }];
+}
+
+- (void)disconnect {
+ self.client = nil;
+ self.query = nil;
+ self.subscription = nil;
+}
+
+@end
diff --git a/ParseLiveQuery/Examples/LiveQueryDemo-ObjC/Info.plist b/ParseLiveQuery/Examples/LiveQueryDemo-ObjC/Info.plist
new file mode 100644
index 000000000..56c22a6bf
--- /dev/null
+++ b/ParseLiveQuery/Examples/LiveQueryDemo-ObjC/Info.plist
@@ -0,0 +1,32 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ en
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIconFile
+
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ 1.0
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ 1
+ LSMinimumSystemVersion
+ $(MACOSX_DEPLOYMENT_TARGET)
+ NSHumanReadableCopyright
+ Copyright © 2016 Parse. All rights reserved.
+ NSPrincipalClass
+ NSApplication
+
+
diff --git a/ParseLiveQuery/Examples/LiveQueryDemo-ObjC/Message.h b/ParseLiveQuery/Examples/LiveQueryDemo-ObjC/Message.h
new file mode 100644
index 000000000..bdb98a620
--- /dev/null
+++ b/ParseLiveQuery/Examples/LiveQueryDemo-ObjC/Message.h
@@ -0,0 +1,24 @@
+/**
+ * Copyright (c) 2016-present, Parse, LLC.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+
+@import ParseCore;
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface Message : PFObject
+
+@property (nullable, nonatomic, strong) PFUser *author;
+@property (nullable, nonatomic, strong) NSString *authorName;
+@property (nullable, nonatomic, strong) NSString *message;
+@property (nullable, nonatomic, strong) PFObject *room;
+@property (nullable, nonatomic, strong) NSString *roomName;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/ParseLiveQuery/Examples/LiveQueryDemo-ObjC/Message.m b/ParseLiveQuery/Examples/LiveQueryDemo-ObjC/Message.m
new file mode 100644
index 000000000..68b1fc340
--- /dev/null
+++ b/ParseLiveQuery/Examples/LiveQueryDemo-ObjC/Message.m
@@ -0,0 +1,20 @@
+/**
+ * Copyright (c) 2016-present, Parse, LLC.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+
+#import "Message.h"
+
+@implementation Message
+
+@dynamic author, authorName, message, room, roomName;
+
++ (NSString *)parseClassName {
+ return @"Message";
+}
+
+@end
diff --git a/ParseLiveQuery/Examples/LiveQueryDemo-ObjC/Room.h b/ParseLiveQuery/Examples/LiveQueryDemo-ObjC/Room.h
new file mode 100644
index 000000000..c368ad242
--- /dev/null
+++ b/ParseLiveQuery/Examples/LiveQueryDemo-ObjC/Room.h
@@ -0,0 +1,20 @@
+/**
+ * Copyright (c) 2016-present, Parse, LLC.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+
+#import
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface Room : PFObject
+
+@property (nullable, nonatomic, strong) NSString *name;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/ParseLiveQuery/Examples/LiveQueryDemo-ObjC/Room.m b/ParseLiveQuery/Examples/LiveQueryDemo-ObjC/Room.m
new file mode 100644
index 000000000..b4ebbb159
--- /dev/null
+++ b/ParseLiveQuery/Examples/LiveQueryDemo-ObjC/Room.m
@@ -0,0 +1,20 @@
+/**
+ * Copyright (c) 2016-present, Parse, LLC.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+
+#import "Room.h"
+
+@implementation Room
+
+@dynamic name;
+
++ (NSString *)parseClassName {
+ return @"Room";
+}
+
+@end
diff --git a/ParseLiveQuery/Examples/LiveQueryDemo-ObjC/main.m b/ParseLiveQuery/Examples/LiveQueryDemo-ObjC/main.m
new file mode 100644
index 000000000..5a2f5e87e
--- /dev/null
+++ b/ParseLiveQuery/Examples/LiveQueryDemo-ObjC/main.m
@@ -0,0 +1,154 @@
+/**
+ * Copyright (c) 2016-present, Parse, LLC.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+
+@import Foundation;
+@import ParseCore;
+@import ParseLiveQuery;
+
+#import "ChatRoomManager.h"
+#import "Message.h"
+#import "Room.h"
+
+BFTask *AttemptLogin() {
+ puts("Enter username: ");
+ char buffer[1024];
+ fgets(buffer, 1024, stdin);
+
+ NSString *usernameInput = [NSString stringWithUTF8String:buffer];
+
+ NSString *prompt = [NSString stringWithFormat:@"Enter password for %@", usernameInput];
+ NSString *passwordInput = [NSString stringWithUTF8String:getpass([prompt UTF8String])];
+
+ NSString *username = [usernameInput stringByTrimmingCharactersInSet:[NSCharacterSet newlineCharacterSet]];
+ NSString *password = [passwordInput stringByTrimmingCharactersInSet:[NSCharacterSet newlineCharacterSet]];
+
+ return [[PFUser logInWithUsernameInBackground:username password:password] continueWithBlock:^id (BFTask *task) {
+ if (task.result) {
+ return task.result;
+ }
+
+ puts("Login failed, please try again.");
+ return AttemptLogin();
+ }];
+}
+
+BFTask *AttemptRoom() {
+ puts("Enter chat room to connect to: ");
+ char buffer[1024];
+ fgets(buffer, 1024, stdin);
+
+ NSString *roomName = [NSString stringWithUTF8String:buffer];
+
+ return [[[[Room query] whereKey:@"name"
+ equalTo:[roomName stringByTrimmingCharactersInSet:[NSCharacterSet newlineCharacterSet]]]
+ getFirstObjectInBackground]
+ continueWithBlock:^id _Nullable(BFTask * _Nonnull task) {
+ if (task.result) {
+ return task.result;
+ }
+
+ puts("Room not found, please try again.");
+ return AttemptRoom();
+ }];
+}
+
+@interface ChatRoomHandler : NSObject
+
+@property (nonatomic, strong, readonly) Room *room;
+@property (nonatomic, strong, readonly) PFLiveQueryClient *client;
+
+@end
+
+@implementation ChatRoomHandler
+
+- (instancetype)initWithRoom:(Room *)room {
+ self = [super init];
+ if (!self) return self;
+
+ _room = room;
+ _client = [[PFLiveQueryClient alloc] init];
+
+ return self;
+}
+
+- (PFQuery *)queryForChatRoomManager:(ChatRoomManager *)manager {
+ return [[[Message query] whereKey:@"roomName"
+ equalTo:self.room.name]
+ orderByAscending:@"createdAt"];
+}
+
+- (PFLiveQueryClient *)liveQueryClientForChatRoomManager:(ChatRoomManager *)manager {
+ return _client;
+}
+
+- (void)chatRoomManager:(ChatRoomManager *)manager didReceiveMessage:(Message *)message {
+ NSString *formatted = [NSString stringWithFormat:@"%@ %@ %@", message.createdAt, message.authorName, message.message];
+ printf("%s\n", formatted.UTF8String);
+}
+
+@end
+
+int main(int argc, const char * argv[]) {
+ @autoreleasepool {
+ [Message registerSubclass];
+ [Room registerSubclass];
+
+ [Parse initializeWithConfiguration:[ParseClientConfiguration configurationWithBlock:^(id configuration) {
+ configuration.applicationId = @"myAppId";
+// configuration.clientKey = @"myClientKey";
+ configuration.server = @"http://localhost:1337/parse";
+ }]];
+
+ [[AttemptLogin() continueWithBlock:^id (BFTask *task) {
+ return AttemptRoom();
+ }] continueWithBlock:^id (BFTask *task) {
+ Room *room = task.result;
+ ChatRoomHandler *handler = [[ChatRoomHandler alloc] initWithRoom:room];
+ ChatRoomManager *manager = [[ChatRoomManager alloc] initWithDataSource:handler delegate:handler];
+
+ // Print out the previous messages
+ PFQuery *query = [handler queryForChatRoomManager:manager];
+ [[query findObjectsInBackground] continueWithBlock:^id (BFTask *task) {
+ for (Message *message in task.result) {
+ [handler chatRoomManager:manager didReceiveMessage:message];
+ }
+
+ [manager connect];
+ return nil;
+ }];
+
+ dispatch_io_t stdinChannel = dispatch_io_create(DISPATCH_IO_STREAM, STDIN_FILENO, dispatch_get_main_queue(), ^(int error) {
+ perror("dispatch_io_create");
+ });
+
+ dispatch_io_set_low_water(stdinChannel, 1);
+ dispatch_io_read(stdinChannel, 0, SIZE_MAX, dispatch_get_main_queue(), ^(bool done, dispatch_data_t data, int error) {
+ NSString *messageText = [[[NSString alloc] initWithData:(NSData *)data
+ encoding:NSUTF8StringEncoding]
+ stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
+
+
+ Message *message = [[Message alloc] init];
+ message.author = [PFUser currentUser];
+ message.authorName = [PFUser currentUser].username;
+ message.message = messageText;
+ message.room = room;
+ message.roomName = room.name;
+
+ [message saveInBackground];
+ });
+
+ return nil;
+ }];
+
+ dispatch_main();
+ }
+
+ return 0;
+}
diff --git a/ParseLiveQuery/Examples/LiveQueryDemo.xcodeproj/project.pbxproj b/ParseLiveQuery/Examples/LiveQueryDemo.xcodeproj/project.pbxproj
new file mode 100644
index 000000000..115b5245d
--- /dev/null
+++ b/ParseLiveQuery/Examples/LiveQueryDemo.xcodeproj/project.pbxproj
@@ -0,0 +1,389 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 46;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ F509D5291CA9E53D007B15B0 /* Message.swift in Sources */ = {isa = PBXBuildFile; fileRef = F59F85B61C9BB4B600566A29 /* Message.swift */; };
+ F509D52A1CA9E53D007B15B0 /* Room.swift in Sources */ = {isa = PBXBuildFile; fileRef = F59F85B71C9BB4B600566A29 /* Room.swift */; };
+ F509D52B1CA9E53D007B15B0 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = F59F85AF1C9BB48200566A29 /* main.swift */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ 395FFA9129D7740B006502C5 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 395FFA8A29D7740B006502C5 /* ParseLiveQuery.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = F5A9BFCA1BE0248D00E78326;
+ remoteInfo = "ParseLiveQuery-iOS";
+ };
+ 395FFA9329D7740B006502C5 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 395FFA8A29D7740B006502C5 /* ParseLiveQuery.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = F5903CEA1BD999C500C3EFFE;
+ remoteInfo = "ParseLiveQuery-OSX";
+ };
+ 395FFA9529D7740B006502C5 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 395FFA8A29D7740B006502C5 /* ParseLiveQuery.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 708836722561F502005B32F0;
+ remoteInfo = "ParseLiveQuery-watchOS";
+ };
+ 395FFA9729D7740B006502C5 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 395FFA8A29D7740B006502C5 /* ParseLiveQuery.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 708836942561F55B005B32F0;
+ remoteInfo = "ParseLiveQuery-tvOS";
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXFileReference section */
+ 395FFA8A29D7740B006502C5 /* ParseLiveQuery.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = ParseLiveQuery.xcodeproj; path = ../ParseLiveQuery.xcodeproj; sourceTree = ""; };
+ F509D5171CA9E4AE007B15B0 /* LiveQueryDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = LiveQueryDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ F509D5241CA9E4AE007B15B0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+ F59F85AF1C9BB48200566A29 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; };
+ F59F85B61C9BB4B600566A29 /* Message.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Message.swift; sourceTree = ""; };
+ F59F85B71C9BB4B600566A29 /* Room.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Room.swift; sourceTree = ""; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ F509D5141CA9E4AE007B15B0 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 2E2DAD338FCB65EC95CB7AA9 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 395FFA8A29D7740B006502C5 /* ParseLiveQuery.xcodeproj */,
+ );
+ name = Frameworks;
+ sourceTree = "";
+ };
+ 395FFA8B29D7740B006502C5 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 395FFA9229D7740B006502C5 /* ParseLiveQuery.framework */,
+ 395FFA9429D7740B006502C5 /* ParseLiveQuery.framework */,
+ 395FFA9629D7740B006502C5 /* ParseLiveQuery_watchOS.framework */,
+ 395FFA9829D7740B006502C5 /* ParseLiveQuery_tvOS.framework */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ F59F85A31C9BB48200566A29 = {
+ isa = PBXGroup;
+ children = (
+ F59F85AE1C9BB48200566A29 /* LiveQueryDemo */,
+ F59F85AD1C9BB48200566A29 /* Products */,
+ 2E2DAD338FCB65EC95CB7AA9 /* Frameworks */,
+ );
+ indentWidth = 4;
+ sourceTree = "";
+ tabWidth = 4;
+ };
+ F59F85AD1C9BB48200566A29 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ F509D5171CA9E4AE007B15B0 /* LiveQueryDemo.app */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ F59F85AE1C9BB48200566A29 /* LiveQueryDemo */ = {
+ isa = PBXGroup;
+ children = (
+ F509D5241CA9E4AE007B15B0 /* Info.plist */,
+ F59F85B61C9BB4B600566A29 /* Message.swift */,
+ F59F85B71C9BB4B600566A29 /* Room.swift */,
+ F59F85AF1C9BB48200566A29 /* main.swift */,
+ );
+ path = LiveQueryDemo;
+ sourceTree = "";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ F509D5161CA9E4AE007B15B0 /* LiveQueryDemo */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = F509D5251CA9E4AE007B15B0 /* Build configuration list for PBXNativeTarget "LiveQueryDemo" */;
+ buildPhases = (
+ F509D5131CA9E4AE007B15B0 /* Sources */,
+ F509D5141CA9E4AE007B15B0 /* Frameworks */,
+ F509D5151CA9E4AE007B15B0 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = LiveQueryDemo;
+ productName = AppKitDemo;
+ productReference = F509D5171CA9E4AE007B15B0 /* LiveQueryDemo.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ F59F85A41C9BB48200566A29 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastSwiftUpdateCheck = 0720;
+ LastUpgradeCheck = 1100;
+ ORGANIZATIONNAME = Parse;
+ TargetAttributes = {
+ F509D5161CA9E4AE007B15B0 = {
+ CreatedOnToolsVersion = 7.3;
+ LastSwiftMigration = 1120;
+ };
+ };
+ };
+ buildConfigurationList = F59F85A71C9BB48200566A29 /* Build configuration list for PBXProject "LiveQueryDemo" */;
+ compatibilityVersion = "Xcode 3.2";
+ developmentRegion = en;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ Base,
+ );
+ mainGroup = F59F85A31C9BB48200566A29;
+ productRefGroup = F59F85AD1C9BB48200566A29 /* Products */;
+ projectDirPath = "";
+ projectReferences = (
+ {
+ ProductGroup = 395FFA8B29D7740B006502C5 /* Products */;
+ ProjectRef = 395FFA8A29D7740B006502C5 /* ParseLiveQuery.xcodeproj */;
+ },
+ );
+ projectRoot = "";
+ targets = (
+ F509D5161CA9E4AE007B15B0 /* LiveQueryDemo */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXReferenceProxy section */
+ 395FFA9229D7740B006502C5 /* ParseLiveQuery.framework */ = {
+ isa = PBXReferenceProxy;
+ fileType = wrapper.framework;
+ path = ParseLiveQuery.framework;
+ remoteRef = 395FFA9129D7740B006502C5 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 395FFA9429D7740B006502C5 /* ParseLiveQuery.framework */ = {
+ isa = PBXReferenceProxy;
+ fileType = wrapper.framework;
+ path = ParseLiveQuery.framework;
+ remoteRef = 395FFA9329D7740B006502C5 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 395FFA9629D7740B006502C5 /* ParseLiveQuery_watchOS.framework */ = {
+ isa = PBXReferenceProxy;
+ fileType = wrapper.framework;
+ path = ParseLiveQuery_watchOS.framework;
+ remoteRef = 395FFA9529D7740B006502C5 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 395FFA9829D7740B006502C5 /* ParseLiveQuery_tvOS.framework */ = {
+ isa = PBXReferenceProxy;
+ fileType = wrapper.framework;
+ path = ParseLiveQuery_tvOS.framework;
+ remoteRef = 395FFA9729D7740B006502C5 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+/* End PBXReferenceProxy section */
+
+/* Begin PBXResourcesBuildPhase section */
+ F509D5151CA9E4AE007B15B0 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ F509D5131CA9E4AE007B15B0 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ F509D52A1CA9E53D007B15B0 /* Room.swift in Sources */,
+ F509D5291CA9E53D007B15B0 /* Message.swift in Sources */,
+ F509D52B1CA9E53D007B15B0 /* main.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ F509D5261CA9E4AE007B15B0 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
+ CLANG_ANALYZER_NONNULL = YES;
+ CODE_SIGN_IDENTITY = "-";
+ COMBINE_HIDPI_IMAGES = YES;
+ INFOPLIST_FILE = "$(SRCROOT)/LiveQueryDemo/Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
+ MACOSX_DEPLOYMENT_TARGET = 10.15;
+ PRODUCT_BUNDLE_IDENTIFIER = com.parse.LiveQueryDemo;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_VERSION = 5.0;
+ };
+ name = Debug;
+ };
+ F509D5271CA9E4AE007B15B0 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
+ CLANG_ANALYZER_NONNULL = YES;
+ CODE_SIGN_IDENTITY = "-";
+ COMBINE_HIDPI_IMAGES = YES;
+ INFOPLIST_FILE = "$(SRCROOT)/LiveQueryDemo/Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
+ MACOSX_DEPLOYMENT_TARGET = 10.15;
+ PRODUCT_BUNDLE_IDENTIFIER = com.parse.LiveQueryDemo;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_VERSION = 5.0;
+ };
+ name = Release;
+ };
+ F59F85B11C9BB48200566A29 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ CODE_SIGN_IDENTITY = "-";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ 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_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;
+ MACOSX_DEPLOYMENT_TARGET = 10.15;
+ MTL_ENABLE_DEBUG_INFO = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = macosx;
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ };
+ name = Debug;
+ };
+ F59F85B21C9BB48200566A29 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ CODE_SIGN_IDENTITY = "-";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ 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;
+ MACOSX_DEPLOYMENT_TARGET = 10.15;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ SDKROOT = macosx;
+ SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ F509D5251CA9E4AE007B15B0 /* Build configuration list for PBXNativeTarget "LiveQueryDemo" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ F509D5261CA9E4AE007B15B0 /* Debug */,
+ F509D5271CA9E4AE007B15B0 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ F59F85A71C9BB48200566A29 /* Build configuration list for PBXProject "LiveQueryDemo" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ F59F85B11C9BB48200566A29 /* Debug */,
+ F59F85B21C9BB48200566A29 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = F59F85A41C9BB48200566A29 /* Project object */;
+}
diff --git a/ParseLiveQuery/Examples/LiveQueryDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ParseLiveQuery/Examples/LiveQueryDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 000000000..919434a62
--- /dev/null
+++ b/ParseLiveQuery/Examples/LiveQueryDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/ParseLiveQuery/Examples/LiveQueryDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ParseLiveQuery/Examples/LiveQueryDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 000000000..18d981003
--- /dev/null
+++ b/ParseLiveQuery/Examples/LiveQueryDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+
+
+
+
+ IDEDidComputeMac32BitWarning
+
+
+
diff --git a/ParseLiveQuery/Examples/LiveQueryDemo.xcodeproj/xcshareddata/xcschemes/LiveQueryDemo.xcscheme b/ParseLiveQuery/Examples/LiveQueryDemo.xcodeproj/xcshareddata/xcschemes/LiveQueryDemo.xcscheme
new file mode 100644
index 000000000..5cba7a07e
--- /dev/null
+++ b/ParseLiveQuery/Examples/LiveQueryDemo.xcodeproj/xcshareddata/xcschemes/LiveQueryDemo.xcscheme
@@ -0,0 +1,87 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ParseLiveQuery/Examples/LiveQueryDemo/Info.plist b/ParseLiveQuery/Examples/LiveQueryDemo/Info.plist
new file mode 100644
index 000000000..ce936cd93
--- /dev/null
+++ b/ParseLiveQuery/Examples/LiveQueryDemo/Info.plist
@@ -0,0 +1,37 @@
+
+
+
+
+ NSAppTransportSecurity
+
+ NSAllowsArbitraryLoads
+
+
+ CFBundleDevelopmentRegion
+ en
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIconFile
+
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ 1.0
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ 1
+ LSMinimumSystemVersion
+ $(MACOSX_DEPLOYMENT_TARGET)
+ NSHumanReadableCopyright
+ Copyright © 2016 Parse. All rights reserved.
+ NSPrincipalClass
+ NSApplication
+
+
diff --git a/ParseLiveQuery/Examples/LiveQueryDemo/Message.swift b/ParseLiveQuery/Examples/LiveQueryDemo/Message.swift
new file mode 100644
index 000000000..49c57752e
--- /dev/null
+++ b/ParseLiveQuery/Examples/LiveQueryDemo/Message.swift
@@ -0,0 +1,23 @@
+/**
+ * Copyright (c) 2016-present, Parse, LLC.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+
+import Foundation
+import ParseCore
+
+class Message: PFObject, PFSubclassing {
+ @NSManaged var author: PFUser?
+ @NSManaged var authorName: String?
+ @NSManaged var message: String?
+ @NSManaged var room: PFObject?
+ @NSManaged var roomName: String?
+
+ class func parseClassName() -> String {
+ return "Message"
+ }
+}
diff --git a/ParseLiveQuery/Examples/LiveQueryDemo/Room.swift b/ParseLiveQuery/Examples/LiveQueryDemo/Room.swift
new file mode 100644
index 000000000..b99a2982c
--- /dev/null
+++ b/ParseLiveQuery/Examples/LiveQueryDemo/Room.swift
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2016-present, Parse, LLC.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+
+import Foundation
+import ParseCore
+
+class Room: PFObject, PFSubclassing {
+ @NSManaged var name: String?
+
+ static func parseClassName() -> String {
+ return "Room"
+ }
+}
diff --git a/ParseLiveQuery/Examples/LiveQueryDemo/main.swift b/ParseLiveQuery/Examples/LiveQueryDemo/main.swift
new file mode 100644
index 000000000..78c2d1b8b
--- /dev/null
+++ b/ParseLiveQuery/Examples/LiveQueryDemo/main.swift
@@ -0,0 +1,135 @@
+/**
+ * Copyright (c) 2016-present, Parse, LLC.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+
+import Foundation
+import ParseCore
+import ParseLiveQuery
+
+Message.registerSubclass()
+Room.registerSubclass()
+
+Parse.initialize(with: ParseClientConfiguration {
+ $0.applicationId = "myAppId"
+// $0.clientKey = "myClientKey"
+ $0.server = "http://localhost:1337/parse"
+ })
+
+let liveQueryClient = ParseLiveQuery.Client()
+
+class ChatRoomManager {
+ fileprivate var currentChatRoom: Room?
+ fileprivate var subscription: Subscription?
+
+ var connected: Bool { return currentChatRoom != nil }
+ var messagesQuery: PFQuery {
+ return (Message.query()?
+ .whereKey("roomName", equalTo: currentChatRoom!.name!)
+ .order(byAscending: "createdAt")) as! PFQuery
+ }
+
+ func connectToChatRoom(_ room: String) {
+ if connected {
+ disconnectFromChatRoom()
+ }
+
+ Room.query()?.whereKey("name", equalTo: room).getFirstObjectInBackground()
+ .continueOnSuccessWith(block: { task -> Any? in
+ self.currentChatRoom = task.result as? Room
+ print("Connected to room \(self.currentChatRoom?.name ?? "null")")
+
+ self.printPriorMessages()
+ self.subscribeToUpdates()
+
+ return nil
+ })
+ }
+
+ func disconnectFromChatRoom() {
+ liveQueryClient.unsubscribe(messagesQuery, handler: subscription!)
+ }
+
+ func sendMessage(_ msg: String) {
+ let message = Message()
+ message.author = PFUser.current()
+ message.authorName = message.author?.username
+ message.message = msg
+ message.room = currentChatRoom
+ message.roomName = currentChatRoom?.name
+
+ message.saveInBackground()
+ }
+
+ func printPriorMessages() {
+ messagesQuery.findObjectsInBackground()
+ .continueOnSuccessWith(block: { task -> Any? in
+ (task.result as? [Message])?.forEach(self.printMessage)
+
+ return nil
+ })
+ }
+
+ func subscribeToUpdates() {
+ subscription = liveQueryClient
+ .subscribe(messagesQuery)
+ .handle(Event.created) { _, message in
+ self.printMessage(message)
+ }
+ }
+
+ fileprivate func printMessage(_ message: Message) {
+ let createdAt = message.createdAt ?? Date()
+
+ print("\(createdAt) \(message.authorName ?? "unknown"): \(message.message ?? "")")
+ }
+}
+
+class InputManager {
+ let stdinChannel = DispatchIO(__type: DispatchIO.StreamType.stream.rawValue, fd: STDIN_FILENO, queue: DispatchQueue.main) { _ in }
+ let chatManager: ChatRoomManager
+
+ init(chatManager: ChatRoomManager) {
+ self.chatManager = chatManager
+
+ stdinChannel.setLimit(lowWater: 1)
+ stdinChannel.read(offset: 0, length: Int.max, queue: DispatchQueue.main, ioHandler: handleInput)
+ }
+
+ fileprivate func handleInput(_ done: Bool, data: DispatchData?, error: Int32) {
+ guard
+ let inputString = data?.withUnsafeBytes(body: {(b: UnsafePointer) -> String? in
+ return String(cString: b)
+ })?.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) else {
+ return
+ }
+
+ if chatManager.connected {
+ chatManager.sendMessage(inputString)
+ } else {
+ chatManager.connectToChatRoom(inputString)
+ }
+ }
+}
+
+print("Enter username: ")
+
+let username = readLine()!
+let password = "Enter password for \(username): ".withCString {
+ String(validatingUTF8: getpass($0))!
+}
+
+let chatManager = ChatRoomManager()
+let inputManager = InputManager(chatManager: chatManager)
+
+PFUser.logInWithUsername(inBackground: username, password: password)
+ .continueOnSuccessWith(block: { task -> Any? in
+ print("Enter chat room to connect to: ")
+ return nil
+})
+
+dispatchMain()
diff --git a/ParseLiveQuery/ParseLiveQuery-tvOS/Info.plist b/ParseLiveQuery/ParseLiveQuery-tvOS/Info.plist
new file mode 100644
index 000000000..b2b03b7e0
--- /dev/null
+++ b/ParseLiveQuery/ParseLiveQuery-tvOS/Info.plist
@@ -0,0 +1,22 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ $(PRODUCT_BUNDLE_PACKAGE_TYPE)
+ CFBundleShortVersionString
+ 2.2.0
+ CFBundleVersion
+ 2.2.0
+
+
diff --git a/ParseLiveQuery/ParseLiveQuery-tvOS/ParseLiveQuery_tvOS.h b/ParseLiveQuery/ParseLiveQuery-tvOS/ParseLiveQuery_tvOS.h
new file mode 100644
index 000000000..8f067e906
--- /dev/null
+++ b/ParseLiveQuery/ParseLiveQuery-tvOS/ParseLiveQuery_tvOS.h
@@ -0,0 +1,19 @@
+//
+// ParseLiveQuery_tvOS.h
+// ParseLiveQuery-tvOS
+//
+// Created by Corey Baker on 11/15/20.
+// Copyright © 2020 Parse. All rights reserved.
+//
+
+#import
+
+//! Project version number for ParseLiveQuery_tvOS.
+FOUNDATION_EXPORT double ParseLiveQuery_tvOSVersionNumber;
+
+//! Project version string for ParseLiveQuery_tvOS.
+FOUNDATION_EXPORT const unsigned char ParseLiveQuery_tvOSVersionString[];
+
+// In this header, you should import all the public headers of your framework using statements like #import
+
+
diff --git a/ParseLiveQuery/ParseLiveQuery-watchOS/Info.plist b/ParseLiveQuery/ParseLiveQuery-watchOS/Info.plist
new file mode 100644
index 000000000..b2b03b7e0
--- /dev/null
+++ b/ParseLiveQuery/ParseLiveQuery-watchOS/Info.plist
@@ -0,0 +1,22 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ $(PRODUCT_BUNDLE_PACKAGE_TYPE)
+ CFBundleShortVersionString
+ 2.2.0
+ CFBundleVersion
+ 2.2.0
+
+
diff --git a/ParseLiveQuery/ParseLiveQuery-watchOS/ParseLiveQuery_watchOS.h b/ParseLiveQuery/ParseLiveQuery-watchOS/ParseLiveQuery_watchOS.h
new file mode 100644
index 000000000..47b493a8a
--- /dev/null
+++ b/ParseLiveQuery/ParseLiveQuery-watchOS/ParseLiveQuery_watchOS.h
@@ -0,0 +1,19 @@
+//
+// ParseLiveQuery_watchOS.h
+// ParseLiveQuery-watchOS
+//
+// Created by Corey Baker on 11/15/20.
+// Copyright © 2020 Parse. All rights reserved.
+//
+
+#import
+
+//! Project version number for ParseLiveQuery_watchOS.
+FOUNDATION_EXPORT double ParseLiveQuery_watchOSVersionNumber;
+
+//! Project version string for ParseLiveQuery_watchOS.
+FOUNDATION_EXPORT const unsigned char ParseLiveQuery_watchOSVersionString[];
+
+// In this header, you should import all the public headers of your framework using statements like #import
+
+
diff --git a/ParseLiveQuery/ParseLiveQuery.xcodeproj/project.pbxproj b/ParseLiveQuery/ParseLiveQuery.xcodeproj/project.pbxproj
new file mode 100644
index 000000000..e4c06f74a
--- /dev/null
+++ b/ParseLiveQuery/ParseLiveQuery.xcodeproj/project.pbxproj
@@ -0,0 +1,1373 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 46;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 0632EDD41CA1A6DB00DD3CB8 /* Parse+LiveQuery.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0632EDD31CA1A6DB00DD3CB8 /* Parse+LiveQuery.swift */; };
+ 0632EDD51CA1A6DB00DD3CB8 /* Parse+LiveQuery.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0632EDD31CA1A6DB00DD3CB8 /* Parse+LiveQuery.swift */; };
+ 094AE9001E25AF3100F408BC /* libicucore.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 094AE8FF1E25AF3100F408BC /* libicucore.tbd */; };
+ 09D80FE21E26C05200AC7A2D /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 09D80FE11E26C05200AC7A2D /* libsqlite3.tbd */; };
+ 39506FFB2A304E6B007F9550 /* Common.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39506FFA2A304E6B007F9550 /* Common.swift */; };
+ 39506FFC2A3056B6007F9550 /* Common.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39506FFA2A304E6B007F9550 /* Common.swift */; };
+ 4A819D9D1D937866009C0F61 /* ObjCCompat.swift in Sources */ = {isa = PBXBuildFile; fileRef = F54D58B51C8E33D9009F8D6C /* ObjCCompat.swift */; };
+ 4A819D9E1D93786A009C0F61 /* ObjCCompat.swift in Sources */ = {isa = PBXBuildFile; fileRef = F54D58B51C8E33D9009F8D6C /* ObjCCompat.swift */; };
+ 708836762561F503005B32F0 /* ParseLiveQuery_watchOS.h in Headers */ = {isa = PBXBuildFile; fileRef = 708836742561F503005B32F0 /* ParseLiveQuery_watchOS.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 708836982561F55B005B32F0 /* ParseLiveQuery_tvOS.h in Headers */ = {isa = PBXBuildFile; fileRef = 708836962561F55B005B32F0 /* ParseLiveQuery_tvOS.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 9595D6E429AFAB0700D9B731 /* Starscream.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 95E916A52995270900EFDB34 /* Starscream.framework */; };
+ 9595D6E529AFAB0700D9B731 /* Starscream.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 95E916A52995270900EFDB34 /* Starscream.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
+ 9595D6E629AFAB3300D9B731 /* BoltsSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 95E9168D299526F200EFDB34 /* BoltsSwift.framework */; };
+ 9595D6E729AFAB3400D9B731 /* BoltsSwift.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 95E9168D299526F200EFDB34 /* BoltsSwift.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
+ 95E91676299526B200EFDB34 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 094AE9011E25AF3A00F408BC /* Foundation.framework */; };
+ 95E91677299526B200EFDB34 /* Foundation.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 094AE9011E25AF3A00F408BC /* Foundation.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
+ 95E91678299526B300EFDB34 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09D80FDF1E26C04800AC7A2D /* AudioToolbox.framework */; };
+ 95E91679299526B300EFDB34 /* AudioToolbox.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 09D80FDF1E26C04800AC7A2D /* AudioToolbox.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
+ 95E9167A299526B500EFDB34 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 094AE9031E25AF4300F408BC /* Security.framework */; };
+ 95E9167B299526B500EFDB34 /* Security.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 094AE9031E25AF4300F408BC /* Security.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
+ 95E9167C299526B900EFDB34 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09D80FDD1E26C03E00AC7A2D /* SystemConfiguration.framework */; };
+ 95E9167D299526B900EFDB34 /* SystemConfiguration.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 09D80FDD1E26C03E00AC7A2D /* SystemConfiguration.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
+ 95E916A82995272A00EFDB34 /* BoltsSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 95E91689299526F200EFDB34 /* BoltsSwift.framework */; };
+ 95E916A92995272A00EFDB34 /* BoltsSwift.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 95E91689299526F200EFDB34 /* BoltsSwift.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
+ 95E916AB2995273D00EFDB34 /* Starscream.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 95E916A52995270900EFDB34 /* Starscream.framework */; };
+ 95E916AC2995273D00EFDB34 /* Starscream.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 95E916A52995270900EFDB34 /* Starscream.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
+ 95E916B12995279800EFDB34 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09D80FDF1E26C04800AC7A2D /* AudioToolbox.framework */; };
+ 95E916B6299527DC00EFDB34 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09D80FDD1E26C03E00AC7A2D /* SystemConfiguration.framework */; };
+ F534A5B21BDAFE0200CBD11A /* Subscription.swift in Sources */ = {isa = PBXBuildFile; fileRef = F534A5B11BDAFE0200CBD11A /* Subscription.swift */; };
+ F534A5B41BDB09CE00CBD11A /* Operation.swift in Sources */ = {isa = PBXBuildFile; fileRef = F534A5B31BDB09CE00CBD11A /* Operation.swift */; };
+ F54D58B81C8E3446009F8D6C /* ClientPrivate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F54D58B71C8E3446009F8D6C /* ClientPrivate.swift */; };
+ F59CA92F1C8E496200329737 /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = F59CA92E1C8E496200329737 /* Errors.swift */; };
+ F5A88F4A1C9B6EBA002F0E0D /* PFQuery+Subscribe.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5A88F491C9B6EBA002F0E0D /* PFQuery+Subscribe.swift */; };
+ F5A88F4E1C9B7341002F0E0D /* QueryEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5591BA91BD97BB70072F966 /* QueryEncoder.swift */; };
+ F5A88F4F1C9B7341002F0E0D /* Operation.swift in Sources */ = {isa = PBXBuildFile; fileRef = F534A5B31BDB09CE00CBD11A /* Operation.swift */; };
+ F5A88F501C9B7341002F0E0D /* ClientPrivate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F54D58B71C8E3446009F8D6C /* ClientPrivate.swift */; };
+ F5A88F521C9B7341002F0E0D /* Client.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5591BA31BD720E10072F966 /* Client.swift */; };
+ F5A88F531C9B7341002F0E0D /* Subscription.swift in Sources */ = {isa = PBXBuildFile; fileRef = F534A5B11BDAFE0200CBD11A /* Subscription.swift */; };
+ F5A88F551C9B7341002F0E0D /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = F59CA92E1C8E496200329737 /* Errors.swift */; };
+ F5A88F561C9B7341002F0E0D /* PFQuery+Subscribe.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5A88F491C9B6EBA002F0E0D /* PFQuery+Subscribe.swift */; };
+ F5D965351BD99DA200C3AAFC /* Client.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5591BA31BD720E10072F966 /* Client.swift */; };
+ F5D965381BD99DA200C3AAFC /* QueryEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5591BA91BD97BB70072F966 /* QueryEncoder.swift */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ 39B857B329D75AE00023ADB0 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 39B8579E29D75AE00023ADB0 /* LiveQueryDemo-ObjC.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = F509D5321CA9E597007B15B0;
+ remoteInfo = "LiveQueryDemo-ObjC";
+ };
+ 39B857B629D75AE00023ADB0 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 39B8579A29D75AE00023ADB0 /* LiveQueryDemo.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = F509D5171CA9E4AE007B15B0;
+ remoteInfo = LiveQueryDemo;
+ };
+ 9595D6E229AFAAB400D9B731 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 95E916532995216A00EFDB34 /* Parse.xcodeproj */;
+ proxyType = 1;
+ remoteGlobalIDString = 97010FAB1630B18F00AB761E;
+ remoteInfo = "Parse-macOS";
+ };
+ 95E916602995216A00EFDB34 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 95E916532995216A00EFDB34 /* Parse.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 81C3821C19CCA89E0066284A;
+ remoteInfo = "Parse-iOS";
+ };
+ 95E916622995216A00EFDB34 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 95E916532995216A00EFDB34 /* Parse.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 81C5845D1C3B0A98000063C6;
+ remoteInfo = "Parse-iOS-Dynamic";
+ };
+ 95E916642995216A00EFDB34 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 95E916532995216A00EFDB34 /* Parse.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 816F449B1A8E8933009CDB32;
+ remoteInfo = "ParseUnitTests-iOS";
+ };
+ 95E916662995216A00EFDB34 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 95E916532995216A00EFDB34 /* Parse.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 97010FAC1630B18F00AB761E;
+ remoteInfo = "Parse-macOS";
+ };
+ 95E916682995216A00EFDB34 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 95E916532995216A00EFDB34 /* Parse.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 81C09F861AF97A490043B49C;
+ remoteInfo = "ParseUnitTests-macOS";
+ };
+ 95E9166A2995216A00EFDB34 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 95E916532995216A00EFDB34 /* Parse.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 815F24151BD04D150054659F;
+ remoteInfo = "Parse-tvOS";
+ };
+ 95E9166C2995216A00EFDB34 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 95E916532995216A00EFDB34 /* Parse.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 81C585BF1C3B0AA1000063C6;
+ remoteInfo = "Parse-tvOS-Dynamic";
+ };
+ 95E9166E2995216A00EFDB34 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 95E916532995216A00EFDB34 /* Parse.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 810156691BB3832700D7C7BD;
+ remoteInfo = "Parse-watchOS";
+ };
+ 95E916702995216A00EFDB34 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 95E916532995216A00EFDB34 /* Parse.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 81C5870F1C3B0AA9000063C6;
+ remoteInfo = "Parse-watchOS-Dynamic";
+ };
+ 95E916722995216A00EFDB34 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 95E916532995216A00EFDB34 /* Parse.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 4AE33A0B1F5451AD0088DCA0;
+ remoteInfo = "ParseUnitTests-iOS-host";
+ };
+ 95E916742995217600EFDB34 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 95E916532995216A00EFDB34 /* Parse.xcodeproj */;
+ proxyType = 1;
+ remoteGlobalIDString = 81C3821B19CCA89E0066284A;
+ remoteInfo = "Parse-iOS";
+ };
+ 95E91688299526F200EFDB34 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 95E9167E299526F200EFDB34 /* BoltsSwift.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 87FEF3661A9085FA00C60678;
+ remoteInfo = "BoltsSwift-iOS";
+ };
+ 95E9168A299526F200EFDB34 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 95E9167E299526F200EFDB34 /* BoltsSwift.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 87FEF3711A9085FA00C60678;
+ remoteInfo = "BoltsSwiftTests-iOS";
+ };
+ 95E9168C299526F200EFDB34 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 95E9167E299526F200EFDB34 /* BoltsSwift.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 81CC14EC1A9BE0A100B28F86;
+ remoteInfo = "BoltsSwift-macOS";
+ };
+ 95E9168E299526F200EFDB34 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 95E9167E299526F200EFDB34 /* BoltsSwift.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 81CC14F61A9BE0A100B28F86;
+ remoteInfo = "BoltsSwiftTests-macOS";
+ };
+ 95E91690299526F200EFDB34 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 95E9167E299526F200EFDB34 /* BoltsSwift.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 065894FF1C9A93B7000FDDA6;
+ remoteInfo = "BoltsSwift-tvOS";
+ };
+ 95E91692299526F200EFDB34 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 95E9167E299526F200EFDB34 /* BoltsSwift.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 0658951B1C9A947B000FDDA6;
+ remoteInfo = "BoltsSwiftTests-tvOS";
+ };
+ 95E91694299526F200EFDB34 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 95E9167E299526F200EFDB34 /* BoltsSwift.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 065894E71C9A933B000FDDA6;
+ remoteInfo = "BoltsSwift-watchOS";
+ };
+ 95E916A42995270900EFDB34 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 95E9169F2995270900EFDB34 /* Starscream.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 33CCF0921F5DDC030099B092;
+ remoteInfo = Starscream;
+ };
+ 95E916A62995270900EFDB34 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 95E9169F2995270900EFDB34 /* Starscream.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 335FA2021F5DF71D00F6D2EC;
+ remoteInfo = "Starscream Tests";
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+ 708836A22561F58F005B32F0 /* Embed Frameworks */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "";
+ dstSubfolderSpec = 10;
+ files = (
+ );
+ name = "Embed Frameworks";
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 708836A52561F5A6005B32F0 /* Embed Frameworks */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "";
+ dstSubfolderSpec = 10;
+ files = (
+ );
+ name = "Embed Frameworks";
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 9575FF0B299135220057B4CE /* Embed Frameworks */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 8;
+ dstPath = "";
+ dstSubfolderSpec = 10;
+ files = (
+ 95E91677299526B200EFDB34 /* Foundation.framework in Embed Frameworks */,
+ 9595D6E729AFAB3400D9B731 /* BoltsSwift.framework in Embed Frameworks */,
+ 95E9167B299526B500EFDB34 /* Security.framework in Embed Frameworks */,
+ 95E9167D299526B900EFDB34 /* SystemConfiguration.framework in Embed Frameworks */,
+ 9595D6E529AFAB0700D9B731 /* Starscream.framework in Embed Frameworks */,
+ 95E91679299526B300EFDB34 /* AudioToolbox.framework in Embed Frameworks */,
+ );
+ name = "Embed Frameworks";
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+ 95E916AA2995272A00EFDB34 /* Embed Frameworks */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "";
+ dstSubfolderSpec = 10;
+ files = (
+ 95E916A92995272A00EFDB34 /* BoltsSwift.framework in Embed Frameworks */,
+ 95E916AC2995273D00EFDB34 /* Starscream.framework in Embed Frameworks */,
+ );
+ name = "Embed Frameworks";
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+ 0632EDD31CA1A6DB00DD3CB8 /* Parse+LiveQuery.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Parse+LiveQuery.swift"; sourceTree = ""; };
+ 094AE8FF1E25AF3100F408BC /* libicucore.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libicucore.tbd; path = usr/lib/libicucore.tbd; sourceTree = SDKROOT; };
+ 094AE9011E25AF3A00F408BC /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
+ 094AE9031E25AF4300F408BC /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
+ 09D80FDD1E26C03E00AC7A2D /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
+ 09D80FDF1E26C04800AC7A2D /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; };
+ 09D80FE11E26C05200AC7A2D /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = usr/lib/libsqlite3.tbd; sourceTree = SDKROOT; };
+ 39506FFA2A304E6B007F9550 /* Common.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Common.swift; sourceTree = ""; };
+ 39B8579A29D75AE00023ADB0 /* LiveQueryDemo.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; path = LiveQueryDemo.xcodeproj; sourceTree = ""; };
+ 39B8579E29D75AE00023ADB0 /* LiveQueryDemo-ObjC.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; path = "LiveQueryDemo-ObjC.xcodeproj"; sourceTree = ""; };
+ 708836722561F502005B32F0 /* ParseLiveQuery_watchOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ParseLiveQuery_watchOS.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ 708836742561F503005B32F0 /* ParseLiveQuery_watchOS.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ParseLiveQuery_watchOS.h; sourceTree = ""; };
+ 708836752561F503005B32F0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+ 708836942561F55B005B32F0 /* ParseLiveQuery_tvOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ParseLiveQuery_tvOS.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ 708836962561F55B005B32F0 /* ParseLiveQuery_tvOS.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ParseLiveQuery_tvOS.h; sourceTree = ""; };
+ 708836972561F55B005B32F0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+ 95E916532995216A00EFDB34 /* Parse.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Parse.xcodeproj; path = ../Parse/Parse.xcodeproj; sourceTree = ""; };
+ 95E9167E299526F200EFDB34 /* BoltsSwift.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = BoltsSwift.xcodeproj; path = "../Carthage/Checkouts/Bolts-Swift/BoltsSwift.xcodeproj"; sourceTree = ""; };
+ 95E9169F2995270900EFDB34 /* Starscream.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Starscream.xcodeproj; path = ../Carthage/Checkouts/Starscream/Starscream.xcodeproj; sourceTree = ""; };
+ 95E916B2299527BD00EFDB34 /* Network.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Network.framework; path = System/Library/Frameworks/Network.framework; sourceTree = SDKROOT; };
+ 95E916B4299527CC00EFDB34 /* NetworkExtension.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = NetworkExtension.framework; path = System/Library/Frameworks/NetworkExtension.framework; sourceTree = SDKROOT; };
+ F5256FD31BD71F9A0052FB8A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+ F534A5B11BDAFE0200CBD11A /* Subscription.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Subscription.swift; sourceTree = ""; };
+ F534A5B31BDB09CE00CBD11A /* Operation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Operation.swift; sourceTree = ""; };
+ F54D58B51C8E33D9009F8D6C /* ObjCCompat.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObjCCompat.swift; sourceTree = ""; };
+ F54D58B71C8E3446009F8D6C /* ClientPrivate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ClientPrivate.swift; sourceTree = ""; };
+ F5591BA31BD720E10072F966 /* Client.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Client.swift; sourceTree = ""; };
+ F5591BA91BD97BB70072F966 /* QueryEncoder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QueryEncoder.swift; sourceTree = ""; };
+ F5903CEA1BD999C500C3EFFE /* ParseLiveQuery.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ParseLiveQuery.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ F59CA92E1C8E496200329737 /* Errors.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Errors.swift; path = Internal/Errors.swift; sourceTree = ""; };
+ F5A88F491C9B6EBA002F0E0D /* PFQuery+Subscribe.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "PFQuery+Subscribe.swift"; sourceTree = ""; };
+ F5A9BFCA1BE0248D00E78326 /* ParseLiveQuery.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ParseLiveQuery.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 7088366F2561F502005B32F0 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 708836912561F55B005B32F0 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ F5903CE61BD999C500C3EFFE /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 09D80FE21E26C05200AC7A2D /* libsqlite3.tbd in Frameworks */,
+ 9595D6E629AFAB3300D9B731 /* BoltsSwift.framework in Frameworks */,
+ 9595D6E429AFAB0700D9B731 /* Starscream.framework in Frameworks */,
+ 95E91676299526B200EFDB34 /* Foundation.framework in Frameworks */,
+ 094AE9001E25AF3100F408BC /* libicucore.tbd in Frameworks */,
+ 95E9167A299526B500EFDB34 /* Security.framework in Frameworks */,
+ 95E9167C299526B900EFDB34 /* SystemConfiguration.framework in Frameworks */,
+ 95E91678299526B300EFDB34 /* AudioToolbox.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ F5A9BFC01BE0248D00E78326 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 95E916AB2995273D00EFDB34 /* Starscream.framework in Frameworks */,
+ 95E916A82995272A00EFDB34 /* BoltsSwift.framework in Frameworks */,
+ 95E916B6299527DC00EFDB34 /* SystemConfiguration.framework in Frameworks */,
+ 95E916B12995279800EFDB34 /* AudioToolbox.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 0BD13CAB7945A6C1A2A7B613 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 95E916B4299527CC00EFDB34 /* NetworkExtension.framework */,
+ 95E916B2299527BD00EFDB34 /* Network.framework */,
+ 95E916532995216A00EFDB34 /* Parse.xcodeproj */,
+ 95E9167E299526F200EFDB34 /* BoltsSwift.xcodeproj */,
+ 95E9169F2995270900EFDB34 /* Starscream.xcodeproj */,
+ 09D80FDD1E26C03E00AC7A2D /* SystemConfiguration.framework */,
+ 09D80FDF1E26C04800AC7A2D /* AudioToolbox.framework */,
+ 09D80FE11E26C05200AC7A2D /* libsqlite3.tbd */,
+ 094AE9011E25AF3A00F408BC /* Foundation.framework */,
+ 094AE9031E25AF4300F408BC /* Security.framework */,
+ 094AE8FF1E25AF3100F408BC /* libicucore.tbd */,
+ );
+ name = Frameworks;
+ sourceTree = "";
+ };
+ 39B8575929D6446C0023ADB0 /* Resources */ = {
+ isa = PBXGroup;
+ children = (
+ F5256FD31BD71F9A0052FB8A /* Info.plist */,
+ );
+ path = Resources;
+ sourceTree = "";
+ };
+ 39B8579429D75AE00023ADB0 /* Examples */ = {
+ isa = PBXGroup;
+ children = (
+ 39B8579A29D75AE00023ADB0 /* LiveQueryDemo.xcodeproj */,
+ 39B8579E29D75AE00023ADB0 /* LiveQueryDemo-ObjC.xcodeproj */,
+ );
+ path = Examples;
+ sourceTree = "";
+ };
+ 39B8579B29D75AE00023ADB0 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 39B857B729D75AE00023ADB0 /* LiveQueryDemo.app */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ 39B8579F29D75AE00023ADB0 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 39B857B429D75AE00023ADB0 /* LiveQueryDemo-ObjC.app */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ 708836732561F503005B32F0 /* ParseLiveQuery-watchOS */ = {
+ isa = PBXGroup;
+ children = (
+ 708836742561F503005B32F0 /* ParseLiveQuery_watchOS.h */,
+ 708836752561F503005B32F0 /* Info.plist */,
+ );
+ path = "ParseLiveQuery-watchOS";
+ sourceTree = "";
+ };
+ 708836952561F55B005B32F0 /* ParseLiveQuery-tvOS */ = {
+ isa = PBXGroup;
+ children = (
+ 708836962561F55B005B32F0 /* ParseLiveQuery_tvOS.h */,
+ 708836972561F55B005B32F0 /* Info.plist */,
+ );
+ path = "ParseLiveQuery-tvOS";
+ sourceTree = "";
+ };
+ 95E916542995216A00EFDB34 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 95E916612995216A00EFDB34 /* Parse.framework */,
+ 95E916632995216A00EFDB34 /* Parse.framework */,
+ 95E916652995216A00EFDB34 /* ParseUnitTests-iOS.xctest */,
+ 95E916672995216A00EFDB34 /* Parse.framework */,
+ 95E916692995216A00EFDB34 /* ParseUnitTests-macOS.xctest */,
+ 95E9166B2995216A00EFDB34 /* Parse.framework */,
+ 95E9166D2995216A00EFDB34 /* Parse.framework */,
+ 95E9166F2995216A00EFDB34 /* Parse.framework */,
+ 95E916712995216A00EFDB34 /* Parse.framework */,
+ 95E916732995216A00EFDB34 /* ParseUnitTests-iOS-host.app */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ 95E9167F299526F200EFDB34 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 95E91689299526F200EFDB34 /* BoltsSwift.framework */,
+ 95E9168B299526F200EFDB34 /* BoltsSwiftTests.xctest */,
+ 95E9168D299526F200EFDB34 /* BoltsSwift.framework */,
+ 95E9168F299526F200EFDB34 /* BoltsSwiftTests.xctest */,
+ 95E91691299526F200EFDB34 /* BoltsSwift.framework */,
+ 95E91693299526F200EFDB34 /* BoltsSwiftTests.xctest */,
+ 95E91695299526F200EFDB34 /* BoltsSwift.framework */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ 95E916A02995270900EFDB34 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 95E916A52995270900EFDB34 /* Starscream.framework */,
+ 95E916A72995270900EFDB34 /* Starscream Tests.xctest */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ F5256FC41BD71F9A0052FB8A = {
+ isa = PBXGroup;
+ children = (
+ 39B8579429D75AE00023ADB0 /* Examples */,
+ F5256FD01BD71F9A0052FB8A /* ParseLiveQuery */,
+ 708836732561F503005B32F0 /* ParseLiveQuery-watchOS */,
+ 708836952561F55B005B32F0 /* ParseLiveQuery-tvOS */,
+ F5256FCF1BD71F9A0052FB8A /* Products */,
+ 0BD13CAB7945A6C1A2A7B613 /* Frameworks */,
+ );
+ indentWidth = 4;
+ sourceTree = "";
+ tabWidth = 4;
+ };
+ F5256FCF1BD71F9A0052FB8A /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ F5903CEA1BD999C500C3EFFE /* ParseLiveQuery.framework */,
+ F5A9BFCA1BE0248D00E78326 /* ParseLiveQuery.framework */,
+ 708836722561F502005B32F0 /* ParseLiveQuery_watchOS.framework */,
+ 708836942561F55B005B32F0 /* ParseLiveQuery_tvOS.framework */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ F5256FD01BD71F9A0052FB8A /* ParseLiveQuery */ = {
+ isa = PBXGroup;
+ children = (
+ F5DC9D381BD9BAFC00E8FF07 /* Internal */,
+ 39B8575929D6446C0023ADB0 /* Resources */,
+ F5591BA31BD720E10072F966 /* Client.swift */,
+ F534A5B11BDAFE0200CBD11A /* Subscription.swift */,
+ F54D58B51C8E33D9009F8D6C /* ObjCCompat.swift */,
+ F59CA92E1C8E496200329737 /* Errors.swift */,
+ 0632EDD31CA1A6DB00DD3CB8 /* Parse+LiveQuery.swift */,
+ F5A88F491C9B6EBA002F0E0D /* PFQuery+Subscribe.swift */,
+ );
+ path = ParseLiveQuery;
+ sourceTree = "";
+ };
+ F5DC9D381BD9BAFC00E8FF07 /* Internal */ = {
+ isa = PBXGroup;
+ children = (
+ F5591BA91BD97BB70072F966 /* QueryEncoder.swift */,
+ 39506FFA2A304E6B007F9550 /* Common.swift */,
+ F534A5B31BDB09CE00CBD11A /* Operation.swift */,
+ F54D58B71C8E3446009F8D6C /* ClientPrivate.swift */,
+ );
+ path = Internal;
+ sourceTree = "";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+ 7088366D2561F502005B32F0 /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 708836762561F503005B32F0 /* ParseLiveQuery_watchOS.h in Headers */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 7088368F2561F55B005B32F0 /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 708836982561F55B005B32F0 /* ParseLiveQuery_tvOS.h in Headers */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ F5903CE71BD999C500C3EFFE /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ F5A9BFC31BE0248D00E78326 /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+ 708836712561F502005B32F0 /* ParseLiveQuery-watchOS */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 7088368B2561F503005B32F0 /* Build configuration list for PBXNativeTarget "ParseLiveQuery-watchOS" */;
+ buildPhases = (
+ 7088366D2561F502005B32F0 /* Headers */,
+ 7088366E2561F502005B32F0 /* Sources */,
+ 7088366F2561F502005B32F0 /* Frameworks */,
+ 708836702561F502005B32F0 /* Resources */,
+ 708836A52561F5A6005B32F0 /* Embed Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "ParseLiveQuery-watchOS";
+ productName = "ParseLiveQuery-watchOS";
+ productReference = 708836722561F502005B32F0 /* ParseLiveQuery_watchOS.framework */;
+ productType = "com.apple.product-type.framework";
+ };
+ 708836932561F55B005B32F0 /* ParseLiveQuery-tvOS */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 708836992561F55B005B32F0 /* Build configuration list for PBXNativeTarget "ParseLiveQuery-tvOS" */;
+ buildPhases = (
+ 7088368F2561F55B005B32F0 /* Headers */,
+ 708836902561F55B005B32F0 /* Sources */,
+ 708836912561F55B005B32F0 /* Frameworks */,
+ 708836922561F55B005B32F0 /* Resources */,
+ 708836A22561F58F005B32F0 /* Embed Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "ParseLiveQuery-tvOS";
+ productName = "ParseLiveQuery-tvOS";
+ productReference = 708836942561F55B005B32F0 /* ParseLiveQuery_tvOS.framework */;
+ productType = "com.apple.product-type.framework";
+ };
+ F5903CE91BD999C500C3EFFE /* ParseLiveQuery-OSX */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = F5903CEF1BD999C500C3EFFE /* Build configuration list for PBXNativeTarget "ParseLiveQuery-OSX" */;
+ buildPhases = (
+ F5903CE51BD999C500C3EFFE /* Sources */,
+ F5903CE61BD999C500C3EFFE /* Frameworks */,
+ F5903CE71BD999C500C3EFFE /* Headers */,
+ F5903CE81BD999C500C3EFFE /* Resources */,
+ 9575FF0B299135220057B4CE /* Embed Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 9595D6E329AFAAB400D9B731 /* PBXTargetDependency */,
+ );
+ name = "ParseLiveQuery-OSX";
+ productName = ParseLiveQuery;
+ productReference = F5903CEA1BD999C500C3EFFE /* ParseLiveQuery.framework */;
+ productType = "com.apple.product-type.framework";
+ };
+ F5A9BFB61BE0248D00E78326 /* ParseLiveQuery-iOS */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = F5A9BFC71BE0248D00E78326 /* Build configuration list for PBXNativeTarget "ParseLiveQuery-iOS" */;
+ buildPhases = (
+ F5A9BFBA1BE0248D00E78326 /* Sources */,
+ F5A9BFC01BE0248D00E78326 /* Frameworks */,
+ F5A9BFC31BE0248D00E78326 /* Headers */,
+ F5A9BFC51BE0248D00E78326 /* Resources */,
+ 95E916AA2995272A00EFDB34 /* Embed Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 95E916752995217600EFDB34 /* PBXTargetDependency */,
+ );
+ name = "ParseLiveQuery-iOS";
+ productName = ParseLiveQuery;
+ productReference = F5A9BFCA1BE0248D00E78326 /* ParseLiveQuery.framework */;
+ productType = "com.apple.product-type.framework";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ F5256FC51BD71F9A0052FB8A /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastUpgradeCheck = 1120;
+ ORGANIZATIONNAME = Parse;
+ TargetAttributes = {
+ 708836712561F502005B32F0 = {
+ CreatedOnToolsVersion = 12.2;
+ ProvisioningStyle = Automatic;
+ };
+ 708836932561F55B005B32F0 = {
+ CreatedOnToolsVersion = 12.2;
+ ProvisioningStyle = Automatic;
+ };
+ F5903CE91BD999C500C3EFFE = {
+ CreatedOnToolsVersion = 7.1;
+ LastSwiftMigration = 1100;
+ };
+ F5A9BFB61BE0248D00E78326 = {
+ LastSwiftMigration = 1010;
+ };
+ };
+ };
+ buildConfigurationList = F5256FC81BD71F9A0052FB8A /* Build configuration list for PBXProject "ParseLiveQuery" */;
+ compatibilityVersion = "Xcode 3.2";
+ developmentRegion = en;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ Base,
+ );
+ mainGroup = F5256FC41BD71F9A0052FB8A;
+ productRefGroup = F5256FCF1BD71F9A0052FB8A /* Products */;
+ projectDirPath = "";
+ projectReferences = (
+ {
+ ProductGroup = 95E9167F299526F200EFDB34 /* Products */;
+ ProjectRef = 95E9167E299526F200EFDB34 /* BoltsSwift.xcodeproj */;
+ },
+ {
+ ProductGroup = 39B8579F29D75AE00023ADB0 /* Products */;
+ ProjectRef = 39B8579E29D75AE00023ADB0 /* LiveQueryDemo-ObjC.xcodeproj */;
+ },
+ {
+ ProductGroup = 39B8579B29D75AE00023ADB0 /* Products */;
+ ProjectRef = 39B8579A29D75AE00023ADB0 /* LiveQueryDemo.xcodeproj */;
+ },
+ {
+ ProductGroup = 95E916542995216A00EFDB34 /* Products */;
+ ProjectRef = 95E916532995216A00EFDB34 /* Parse.xcodeproj */;
+ },
+ {
+ ProductGroup = 95E916A02995270900EFDB34 /* Products */;
+ ProjectRef = 95E9169F2995270900EFDB34 /* Starscream.xcodeproj */;
+ },
+ );
+ projectRoot = "";
+ targets = (
+ F5A9BFB61BE0248D00E78326 /* ParseLiveQuery-iOS */,
+ F5903CE91BD999C500C3EFFE /* ParseLiveQuery-OSX */,
+ 708836712561F502005B32F0 /* ParseLiveQuery-watchOS */,
+ 708836932561F55B005B32F0 /* ParseLiveQuery-tvOS */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXReferenceProxy section */
+ 39B857B429D75AE00023ADB0 /* LiveQueryDemo-ObjC.app */ = {
+ isa = PBXReferenceProxy;
+ fileType = wrapper.application;
+ path = "LiveQueryDemo-ObjC.app";
+ remoteRef = 39B857B329D75AE00023ADB0 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 39B857B729D75AE00023ADB0 /* LiveQueryDemo.app */ = {
+ isa = PBXReferenceProxy;
+ fileType = wrapper.application;
+ path = LiveQueryDemo.app;
+ remoteRef = 39B857B629D75AE00023ADB0 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 95E916612995216A00EFDB34 /* Parse.framework */ = {
+ isa = PBXReferenceProxy;
+ fileType = wrapper.framework;
+ path = Parse.framework;
+ remoteRef = 95E916602995216A00EFDB34 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 95E916632995216A00EFDB34 /* Parse.framework */ = {
+ isa = PBXReferenceProxy;
+ fileType = wrapper.framework;
+ path = Parse.framework;
+ remoteRef = 95E916622995216A00EFDB34 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 95E916652995216A00EFDB34 /* ParseUnitTests-iOS.xctest */ = {
+ isa = PBXReferenceProxy;
+ fileType = wrapper.cfbundle;
+ path = "ParseUnitTests-iOS.xctest";
+ remoteRef = 95E916642995216A00EFDB34 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 95E916672995216A00EFDB34 /* Parse.framework */ = {
+ isa = PBXReferenceProxy;
+ fileType = wrapper.framework;
+ path = Parse.framework;
+ remoteRef = 95E916662995216A00EFDB34 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 95E916692995216A00EFDB34 /* ParseUnitTests-macOS.xctest */ = {
+ isa = PBXReferenceProxy;
+ fileType = wrapper.cfbundle;
+ path = "ParseUnitTests-macOS.xctest";
+ remoteRef = 95E916682995216A00EFDB34 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 95E9166B2995216A00EFDB34 /* Parse.framework */ = {
+ isa = PBXReferenceProxy;
+ fileType = wrapper.framework;
+ path = Parse.framework;
+ remoteRef = 95E9166A2995216A00EFDB34 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 95E9166D2995216A00EFDB34 /* Parse.framework */ = {
+ isa = PBXReferenceProxy;
+ fileType = wrapper.framework;
+ path = Parse.framework;
+ remoteRef = 95E9166C2995216A00EFDB34 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 95E9166F2995216A00EFDB34 /* Parse.framework */ = {
+ isa = PBXReferenceProxy;
+ fileType = wrapper.framework;
+ path = Parse.framework;
+ remoteRef = 95E9166E2995216A00EFDB34 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 95E916712995216A00EFDB34 /* Parse.framework */ = {
+ isa = PBXReferenceProxy;
+ fileType = wrapper.framework;
+ path = Parse.framework;
+ remoteRef = 95E916702995216A00EFDB34 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 95E916732995216A00EFDB34 /* ParseUnitTests-iOS-host.app */ = {
+ isa = PBXReferenceProxy;
+ fileType = wrapper.application;
+ path = "ParseUnitTests-iOS-host.app";
+ remoteRef = 95E916722995216A00EFDB34 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 95E91689299526F200EFDB34 /* BoltsSwift.framework */ = {
+ isa = PBXReferenceProxy;
+ fileType = wrapper.framework;
+ path = BoltsSwift.framework;
+ remoteRef = 95E91688299526F200EFDB34 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 95E9168B299526F200EFDB34 /* BoltsSwiftTests.xctest */ = {
+ isa = PBXReferenceProxy;
+ fileType = wrapper.cfbundle;
+ path = BoltsSwiftTests.xctest;
+ remoteRef = 95E9168A299526F200EFDB34 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 95E9168D299526F200EFDB34 /* BoltsSwift.framework */ = {
+ isa = PBXReferenceProxy;
+ fileType = wrapper.framework;
+ path = BoltsSwift.framework;
+ remoteRef = 95E9168C299526F200EFDB34 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 95E9168F299526F200EFDB34 /* BoltsSwiftTests.xctest */ = {
+ isa = PBXReferenceProxy;
+ fileType = wrapper.cfbundle;
+ path = BoltsSwiftTests.xctest;
+ remoteRef = 95E9168E299526F200EFDB34 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 95E91691299526F200EFDB34 /* BoltsSwift.framework */ = {
+ isa = PBXReferenceProxy;
+ fileType = wrapper.framework;
+ path = BoltsSwift.framework;
+ remoteRef = 95E91690299526F200EFDB34 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 95E91693299526F200EFDB34 /* BoltsSwiftTests.xctest */ = {
+ isa = PBXReferenceProxy;
+ fileType = wrapper.cfbundle;
+ path = BoltsSwiftTests.xctest;
+ remoteRef = 95E91692299526F200EFDB34 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 95E91695299526F200EFDB34 /* BoltsSwift.framework */ = {
+ isa = PBXReferenceProxy;
+ fileType = wrapper.framework;
+ path = BoltsSwift.framework;
+ remoteRef = 95E91694299526F200EFDB34 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 95E916A52995270900EFDB34 /* Starscream.framework */ = {
+ isa = PBXReferenceProxy;
+ fileType = wrapper.framework;
+ path = Starscream.framework;
+ remoteRef = 95E916A42995270900EFDB34 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 95E916A72995270900EFDB34 /* Starscream Tests.xctest */ = {
+ isa = PBXReferenceProxy;
+ fileType = wrapper.cfbundle;
+ path = "Starscream Tests.xctest";
+ remoteRef = 95E916A62995270900EFDB34 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+/* End PBXReferenceProxy section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 708836702561F502005B32F0 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 708836922561F55B005B32F0 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ F5903CE81BD999C500C3EFFE /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ F5A9BFC51BE0248D00E78326 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 7088366E2561F502005B32F0 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 708836902561F55B005B32F0 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ F5903CE51BD999C500C3EFFE /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ F54D58B81C8E3446009F8D6C /* ClientPrivate.swift in Sources */,
+ F5D965351BD99DA200C3AAFC /* Client.swift in Sources */,
+ 0632EDD51CA1A6DB00DD3CB8 /* Parse+LiveQuery.swift in Sources */,
+ F5D965381BD99DA200C3AAFC /* QueryEncoder.swift in Sources */,
+ F534A5B21BDAFE0200CBD11A /* Subscription.swift in Sources */,
+ F59CA92F1C8E496200329737 /* Errors.swift in Sources */,
+ F534A5B41BDB09CE00CBD11A /* Operation.swift in Sources */,
+ F5A88F4A1C9B6EBA002F0E0D /* PFQuery+Subscribe.swift in Sources */,
+ 39506FFC2A3056B6007F9550 /* Common.swift in Sources */,
+ 4A819D9E1D93786A009C0F61 /* ObjCCompat.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ F5A9BFBA1BE0248D00E78326 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ F5A88F531C9B7341002F0E0D /* Subscription.swift in Sources */,
+ 0632EDD41CA1A6DB00DD3CB8 /* Parse+LiveQuery.swift in Sources */,
+ F5A88F501C9B7341002F0E0D /* ClientPrivate.swift in Sources */,
+ F5A88F551C9B7341002F0E0D /* Errors.swift in Sources */,
+ F5A88F4E1C9B7341002F0E0D /* QueryEncoder.swift in Sources */,
+ F5A88F521C9B7341002F0E0D /* Client.swift in Sources */,
+ F5A88F4F1C9B7341002F0E0D /* Operation.swift in Sources */,
+ F5A88F561C9B7341002F0E0D /* PFQuery+Subscribe.swift in Sources */,
+ 39506FFB2A304E6B007F9550 /* Common.swift in Sources */,
+ 4A819D9D1D937866009C0F61 /* ObjCCompat.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+ 9595D6E329AFAAB400D9B731 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ name = "Parse-macOS";
+ targetProxy = 9595D6E229AFAAB400D9B731 /* PBXContainerItemProxy */;
+ };
+ 95E916752995217600EFDB34 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ name = "Parse-iOS";
+ targetProxy = 95E916742995217600EFDB34 /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
+/* Begin XCBuildConfiguration section */
+ 708836772561F503005B32F0 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ APPLICATION_EXTENSION_API_ONLY = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CODE_SIGN_STYLE = Automatic;
+ COPY_PHASE_STRIP = NO;
+ CURRENT_PROJECT_VERSION = 1;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ DEFINES_MODULE = YES;
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ DYLIB_INSTALL_NAME_BASE = "@rpath";
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ INFOPLIST_FILE = "ParseLiveQuery-watchOS/Info.plist";
+ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ MARKETING_VERSION = 2.8.1;
+ MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+ MTL_FAST_MATH = YES;
+ PRODUCT_BUNDLE_IDENTIFIER = "com.parse.livequery.watchos.ParseLiveQuery-watchOS";
+ PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
+ SDKROOT = watchos;
+ SKIP_INSTALL = YES;
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = 4;
+ VERSIONING_SYSTEM = "apple-generic";
+ VERSION_INFO_PREFIX = "";
+ WATCHOS_DEPLOYMENT_TARGET = 2.0;
+ };
+ name = Debug;
+ };
+ 708836782561F503005B32F0 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ APPLICATION_EXTENSION_API_ONLY = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CODE_SIGN_STYLE = Automatic;
+ 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;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ INFOPLIST_FILE = "ParseLiveQuery-watchOS/Info.plist";
+ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ MARKETING_VERSION = 2.8.1;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ MTL_FAST_MATH = YES;
+ PRODUCT_BUNDLE_IDENTIFIER = "com.parse.livequery.watchos.ParseLiveQuery-watchOS";
+ PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
+ SDKROOT = watchos;
+ SKIP_INSTALL = YES;
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = 4;
+ VALIDATE_PRODUCT = YES;
+ VERSIONING_SYSTEM = "apple-generic";
+ VERSION_INFO_PREFIX = "";
+ WATCHOS_DEPLOYMENT_TARGET = 2.0;
+ };
+ name = Release;
+ };
+ 7088369A2561F55B005B32F0 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CODE_SIGN_STYLE = Automatic;
+ COPY_PHASE_STRIP = NO;
+ CURRENT_PROJECT_VERSION = 1;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ DEFINES_MODULE = YES;
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ DYLIB_INSTALL_NAME_BASE = "@rpath";
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ INFOPLIST_FILE = "ParseLiveQuery-tvOS/Info.plist";
+ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ MARKETING_VERSION = 2.8.1;
+ MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+ MTL_FAST_MATH = YES;
+ PRODUCT_BUNDLE_IDENTIFIER = "com.parse.livequery.tvos.ParseLiveQuery-tvOS";
+ PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
+ SDKROOT = appletvos;
+ SKIP_INSTALL = YES;
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = 3;
+ TVOS_DEPLOYMENT_TARGET = 10.0;
+ VERSIONING_SYSTEM = "apple-generic";
+ VERSION_INFO_PREFIX = "";
+ };
+ name = Debug;
+ };
+ 7088369B2561F55B005B32F0 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CODE_SIGN_STYLE = Automatic;
+ 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;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ INFOPLIST_FILE = "ParseLiveQuery-tvOS/Info.plist";
+ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ MARKETING_VERSION = 2.8.1;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ MTL_FAST_MATH = YES;
+ PRODUCT_BUNDLE_IDENTIFIER = "com.parse.livequery.tvos.ParseLiveQuery-tvOS";
+ PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
+ SDKROOT = appletvos;
+ SKIP_INSTALL = YES;
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = 3;
+ TVOS_DEPLOYMENT_TARGET = 10.0;
+ VALIDATE_PRODUCT = YES;
+ VERSIONING_SYSTEM = "apple-generic";
+ VERSION_INFO_PREFIX = "";
+ };
+ name = Release;
+ };
+ F5256FE01BD71F9A0052FB8A /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+ MACOSX_DEPLOYMENT_TARGET = 10.15;
+ ONLY_ACTIVE_ARCH = YES;
+ SWIFT_OBJC_BRIDGING_HEADER = "";
+ SWIFT_VERSION = 4.2;
+ };
+ name = Debug;
+ };
+ F5256FE11BD71F9A0052FB8A /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+ MACOSX_DEPLOYMENT_TARGET = 10.15;
+ SWIFT_OBJC_BRIDGING_HEADER = "";
+ SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
+ SWIFT_VERSION = 4.2;
+ };
+ name = Release;
+ };
+ F5903CF01BD999C500C3EFFE /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CODE_SIGNING_REQUIRED = NO;
+ COMBINE_HIDPI_IMAGES = YES;
+ DEFINES_MODULE = YES;
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ DYLIB_INSTALL_NAME_BASE = "@rpath";
+ EXCLUDED_ARCHS = "";
+ FRAMEWORK_VERSION = A;
+ INFOPLIST_FILE = ParseLiveQuery/Resources/Info.plist;
+ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
+ MACOSX_DEPLOYMENT_TARGET = 10.15;
+ MARKETING_VERSION = 2.8.1;
+ PRODUCT_BUNDLE_IDENTIFIER = com.parse.livequery.osx;
+ PRODUCT_NAME = ParseLiveQuery;
+ SDKROOT = macosx;
+ SKIP_INSTALL = YES;
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_VERSION = 5.0;
+ };
+ name = Debug;
+ };
+ F5903CF11BD999C500C3EFFE /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CODE_SIGNING_REQUIRED = NO;
+ COMBINE_HIDPI_IMAGES = YES;
+ DEFINES_MODULE = YES;
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ DYLIB_INSTALL_NAME_BASE = "@rpath";
+ EXCLUDED_ARCHS = "";
+ FRAMEWORK_VERSION = A;
+ INFOPLIST_FILE = ParseLiveQuery/Resources/Info.plist;
+ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
+ MACOSX_DEPLOYMENT_TARGET = 10.15;
+ MARKETING_VERSION = 2.8.1;
+ PRODUCT_BUNDLE_IDENTIFIER = com.parse.livequery.osx;
+ PRODUCT_NAME = ParseLiveQuery;
+ SDKROOT = macosx;
+ SKIP_INSTALL = YES;
+ SWIFT_VERSION = 5.0;
+ };
+ name = Release;
+ };
+ F5A9BFC81BE0248D00E78326 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CODE_SIGNING_REQUIRED = NO;
+ DEFINES_MODULE = YES;
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ DYLIB_INSTALL_NAME_BASE = "@rpath";
+ EXCLUDED_ARCHS = arm64;
+ FRAMEWORK_VERSION = A;
+ INFOPLIST_FILE = ParseLiveQuery/Resources/Info.plist;
+ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+ IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ LIBRARY_SEARCH_PATHS = "$(inherited)";
+ MARKETING_VERSION = 2.8.1;
+ OTHER_LDFLAGS = "-lsqlite3";
+ PRODUCT_BUNDLE_IDENTIFIER = com.parse.livequery.ios;
+ PRODUCT_NAME = ParseLiveQuery;
+ SDKROOT = iphoneos;
+ SKIP_INSTALL = YES;
+ SWIFT_INSTALL_OBJC_HEADER = YES;
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ F5A9BFC91BE0248D00E78326 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CODE_SIGNING_REQUIRED = NO;
+ DEFINES_MODULE = YES;
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ DYLIB_INSTALL_NAME_BASE = "@rpath";
+ EXCLUDED_ARCHS = arm64;
+ FRAMEWORK_VERSION = A;
+ INFOPLIST_FILE = ParseLiveQuery/Resources/Info.plist;
+ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+ IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ LIBRARY_SEARCH_PATHS = "$(inherited)";
+ MARKETING_VERSION = 2.8.1;
+ OTHER_LDFLAGS = "-lsqlite3";
+ PRODUCT_BUNDLE_IDENTIFIER = com.parse.livequery.ios;
+ PRODUCT_NAME = ParseLiveQuery;
+ SDKROOT = iphoneos;
+ SKIP_INSTALL = YES;
+ SWIFT_INSTALL_OBJC_HEADER = YES;
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 7088368B2561F503005B32F0 /* Build configuration list for PBXNativeTarget "ParseLiveQuery-watchOS" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 708836772561F503005B32F0 /* Debug */,
+ 708836782561F503005B32F0 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 708836992561F55B005B32F0 /* Build configuration list for PBXNativeTarget "ParseLiveQuery-tvOS" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 7088369A2561F55B005B32F0 /* Debug */,
+ 7088369B2561F55B005B32F0 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ F5256FC81BD71F9A0052FB8A /* Build configuration list for PBXProject "ParseLiveQuery" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ F5256FE01BD71F9A0052FB8A /* Debug */,
+ F5256FE11BD71F9A0052FB8A /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ F5903CEF1BD999C500C3EFFE /* Build configuration list for PBXNativeTarget "ParseLiveQuery-OSX" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ F5903CF01BD999C500C3EFFE /* Debug */,
+ F5903CF11BD999C500C3EFFE /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ F5A9BFC71BE0248D00E78326 /* Build configuration list for PBXNativeTarget "ParseLiveQuery-iOS" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ F5A9BFC81BE0248D00E78326 /* Debug */,
+ F5A9BFC91BE0248D00E78326 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = F5256FC51BD71F9A0052FB8A /* Project object */;
+}
diff --git a/ParseLiveQuery/ParseLiveQuery.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ParseLiveQuery/ParseLiveQuery.xcodeproj/project.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 000000000..71ce19170
--- /dev/null
+++ b/ParseLiveQuery/ParseLiveQuery.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/ParseLiveQuery/ParseLiveQuery.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ParseLiveQuery/ParseLiveQuery.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 000000000..18d981003
--- /dev/null
+++ b/ParseLiveQuery/ParseLiveQuery.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+
+
+
+
+ IDEDidComputeMac32BitWarning
+
+
+
diff --git a/ParseLiveQuery/ParseLiveQuery.xcodeproj/xcshareddata/xcschemes/ParseLiveQuery-OSX.xcscheme b/ParseLiveQuery/ParseLiveQuery.xcodeproj/xcshareddata/xcschemes/ParseLiveQuery-OSX.xcscheme
new file mode 100644
index 000000000..71c9ab194
--- /dev/null
+++ b/ParseLiveQuery/ParseLiveQuery.xcodeproj/xcshareddata/xcschemes/ParseLiveQuery-OSX.xcscheme
@@ -0,0 +1,76 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ParseLiveQuery/ParseLiveQuery.xcodeproj/xcshareddata/xcschemes/ParseLiveQuery-iOS.xcscheme b/ParseLiveQuery/ParseLiveQuery.xcodeproj/xcshareddata/xcschemes/ParseLiveQuery-iOS.xcscheme
new file mode 100644
index 000000000..31b1f25f7
--- /dev/null
+++ b/ParseLiveQuery/ParseLiveQuery.xcodeproj/xcshareddata/xcschemes/ParseLiveQuery-iOS.xcscheme
@@ -0,0 +1,76 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ParseLiveQuery/ParseLiveQuery.xcodeproj/xcshareddata/xcschemes/ParseLiveQuery-tvOS.xcscheme b/ParseLiveQuery/ParseLiveQuery.xcodeproj/xcshareddata/xcschemes/ParseLiveQuery-tvOS.xcscheme
new file mode 100644
index 000000000..8c4e08c92
--- /dev/null
+++ b/ParseLiveQuery/ParseLiveQuery.xcodeproj/xcshareddata/xcschemes/ParseLiveQuery-tvOS.xcscheme
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ParseLiveQuery/ParseLiveQuery.xcodeproj/xcshareddata/xcschemes/ParseLiveQuery-watchOS.xcscheme b/ParseLiveQuery/ParseLiveQuery.xcodeproj/xcshareddata/xcschemes/ParseLiveQuery-watchOS.xcscheme
new file mode 100644
index 000000000..25b3a19b0
--- /dev/null
+++ b/ParseLiveQuery/ParseLiveQuery.xcodeproj/xcshareddata/xcschemes/ParseLiveQuery-watchOS.xcscheme
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ParseLiveQuery/ParseLiveQuery/Client.swift b/ParseLiveQuery/ParseLiveQuery/Client.swift
new file mode 100644
index 000000000..7fdf7cb8a
--- /dev/null
+++ b/ParseLiveQuery/ParseLiveQuery/Client.swift
@@ -0,0 +1,263 @@
+/**
+ * Copyright (c) 2016-present, Parse, LLC.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+
+import Foundation
+import BoltsSwift
+import Starscream
+
+/**
+ This is the 'advanced' view of live query subscriptions. It allows you to customize your subscriptions
+ to a live query server, have connections to multiple servers, cleanly handle disconnect and reconnect.
+ */
+@objc(PFLiveQueryClient)
+open class Client: NSObject {
+ let host: URL
+ let applicationId: String
+ let clientKey: String?
+
+ var socket: WebSocket?
+ public var shouldPrintWebSocketLog = true
+ public var shouldPrintWebSocketTrace = false
+ public var userDisconnected = false
+ var isConnecting = false
+
+ // This allows us to easily plug in another request ID generation scheme, or more easily change the request id type
+ // if needed (technically this could be a string).
+ let requestIdGenerator: () -> RequestId
+ var subscriptions = [SubscriptionRecord]()
+
+ let queue = DispatchQueue(label: "com.parse.livequery", attributes: [])
+
+ /**
+ Creates a Client which automatically attempts to connect to the custom parse-server URL set in Parse.currentConfiguration().
+ */
+ public override convenience init() {
+ self.init(server: Parse.validatedCurrentConfiguration().server)
+ }
+
+ /**
+ Creates a client which will connect to a specific server with an optional application id and client key
+
+ - parameter server: The server to connect to
+ - parameter applicationId: The application id to use
+ - parameter clientKey: The client key to use
+ */
+ @objc(initWithServer:applicationId:clientKey:)
+ public init(server: String, applicationId: String? = nil, clientKey: String? = nil) {
+ guard let cmpts = URLComponents(string: server) else {
+ fatalError("Server should be a valid URL.")
+ }
+ var components = cmpts
+ components.scheme = (components.scheme == "https" || components.scheme == "wss") ? "wss" : "ws"
+
+ // Simple incrementing generator - can't use ++, that operator is deprecated!
+ var currentRequestId = 0
+ requestIdGenerator = {
+ currentRequestId += 1
+ return RequestId(value: currentRequestId)
+ }
+
+ self.applicationId = applicationId ?? Parse.validatedCurrentConfiguration().applicationId!
+ self.clientKey = clientKey ?? Parse.validatedCurrentConfiguration().clientKey
+
+ self.host = components.url!
+ }
+}
+
+extension Client {
+ // Swift is lame and doesn't allow storage to directly be in extensions.
+ // So we create an inner struct to wrap it up.
+ fileprivate class Storage {
+ private static var __once: () = {
+ sharedStorage = Storage()
+ }()
+ static var onceToken: Int = 0
+ static var sharedStorage: Storage!
+ static var shared: Storage {
+ _ = Storage.__once
+ return sharedStorage
+ }
+
+ let queue: DispatchQueue = DispatchQueue(label: "com.parse.livequery.client.storage", attributes: [])
+ var client: Client?
+ }
+
+ /// Gets or sets shared live query client to be used for default subscriptions
+ @objc(sharedClient)
+ public static var shared: Client! {
+ get {
+ let storage = Storage.shared
+ var client: Client?
+ storage.queue.sync {
+ client = storage.client
+ if client == nil {
+ let configuration = Parse.validatedCurrentConfiguration()
+ client = Client(
+ server: configuration.server,
+ applicationId: configuration.applicationId,
+ clientKey: configuration.clientKey
+ )
+ storage.client = client
+ }
+ }
+ return client
+ }
+ set {
+ let storage = Storage.shared
+ storage.queue.sync {
+ storage.client = newValue
+ }
+ }
+ }
+}
+
+extension Client {
+ /**
+ Registers a query for live updates, using the default subscription handler
+
+ - parameter query: The query to register for updates.
+ - parameter subclassType: The subclass of PFObject to be used as the type of the Subscription.
+ This parameter can be automatically inferred from context most of the time
+
+ - returns: The subscription that has just been registered
+ */
+ public func subscribe(
+ _ query: PFQuery,
+ subclassType: T.Type = T.self
+ ) -> Subscription {
+ return subscribe(query, handler: Subscription())
+ }
+
+ /**
+ Registers a query for live updates, using a custom subscription handler
+
+ - parameter query: The query to register for updates.
+ - parameter handler: A custom subscription handler.
+
+ - returns: Your subscription handler, for easy chaining.
+ */
+ public func subscribe(
+ _ query: PFQuery,
+ handler: T
+ ) -> T where T: SubscriptionHandling {
+ let subscriptionRecord = SubscriptionRecord(
+ query: query,
+ requestId: requestIdGenerator(),
+ handler: handler
+ )
+
+ self.subscriptions.append(subscriptionRecord)
+
+ if socket != nil {
+ _ = self.sendOperationAsync(.subscribe(requestId: subscriptionRecord.requestId, query: query as! PFQuery,
+ sessionToken: PFUser.current()?.sessionToken))
+ } else if !self.userDisconnected {
+ self.reconnect()
+ self.subscriptions.removeLast()
+ return self.subscribe(query, handler: handler)
+ } else {
+ NSLog("ParseLiveQuery: Warning: The client was explicitly disconnected! You must explicitly call .reconnect() in order to process your subscriptions.")
+ }
+
+ return handler
+ }
+
+ /**
+ Updates an existing subscription with a new query.
+ Upon completing the registration, the subscribe handler will be called with the new query
+
+ - parameter handler: The specific handler to update.
+ - parameter query: The new query for that handler.
+ */
+ public func update(
+ _ handler: T,
+ toQuery query: PFQuery
+ ) where T: SubscriptionHandling {
+ subscriptions = subscriptions.map {
+ if $0.subscriptionHandler === handler {
+ _ = sendOperationAsync(.update(requestId: $0.requestId, query: query as! PFQuery))
+ return SubscriptionRecord(query: query, requestId: $0.requestId, handler: $0.subscriptionHandler as! T)
+ }
+ return $0
+ }
+ }
+
+ /**
+ Unsubscribes all current subscriptions for a given query.
+
+ - parameter query: The query to unsubscribe from.
+ */
+ @objc(unsubscribeFromQuery:)
+ public func unsubscribe(_ query: PFQuery) {
+ unsubscribe { $0.query == query }
+ }
+
+ /**
+ Unsubscribes from a specific query-handler pair.
+
+ - parameter query: The query to unsubscribe from.
+ - parameter handler: The specific handler to unsubscribe from.
+ */
+ public func unsubscribe(_ query: PFQuery, handler: T) where T: SubscriptionHandling {
+ unsubscribe { $0.query == query && $0.subscriptionHandler === handler }
+ }
+
+ func unsubscribe(matching matcher: @escaping (SubscriptionRecord) -> Bool) {
+ var temp = [SubscriptionRecord]()
+ subscriptions.forEach {
+ if matcher($0) {
+ _ = sendOperationAsync(.unsubscribe(requestId: $0.requestId))
+ } else {
+ temp.append($0)
+ }
+ }
+ subscriptions = temp
+ }
+}
+
+extension Client {
+ /**
+ Reconnects this client to the server.
+
+ This will disconnect and resubscribe all existing subscriptions. This is not required to be called the first time
+ you use the client, and should usually only be called when an error occurs.
+ */
+ @objc(reconnect)
+ public func reconnect() {
+ guard socket == nil || !isConnecting else { return }
+ socket?.disconnect()
+ socket = {
+ let socket = WebSocket(request: .init(url: host))
+ socket.delegate = self
+ socket.callbackQueue = queue
+ socket.connect()
+ isConnecting = true
+ userDisconnected = false
+ return socket
+ }()
+ }
+
+ /**
+ Explicitly disconnects this client from the server.
+
+ This does not remove any subscriptions - if you `reconnect()` your existing subscriptions will be restored.
+ Use this if you wish to dispose of the live query client.
+ */
+ @objc(disconnect)
+ public func disconnect() {
+ isConnecting = false
+ guard let socket = socket
+ else {
+ return
+ }
+ socket.disconnect()
+ self.socket = nil
+ userDisconnected = true
+ }
+}
diff --git a/ParseLiveQuery/ParseLiveQuery/Internal/ClientPrivate.swift b/ParseLiveQuery/ParseLiveQuery/Internal/ClientPrivate.swift
new file mode 100644
index 000000000..83fab187a
--- /dev/null
+++ b/ParseLiveQuery/ParseLiveQuery/Internal/ClientPrivate.swift
@@ -0,0 +1,280 @@
+/**
+ * Copyright (c) 2016-present, Parse, LLC.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+
+import Foundation
+import Starscream
+import BoltsSwift
+
+private func parseObject(_ objectDictionary: [String:AnyObject]) throws -> T {
+ guard let _ = objectDictionary["className"] as? String else {
+ throw LiveQueryErrors.InvalidJSONError(json: objectDictionary, expectedKey: "parseClassName")
+ }
+ guard let _ = objectDictionary["objectId"] as? String else {
+ throw LiveQueryErrors.InvalidJSONError(json: objectDictionary, expectedKey: "objectId")
+ }
+
+ guard let object = PFDecoder.object().decode(objectDictionary) as? T else {
+ throw LiveQueryErrors.InvalidJSONObject(json: objectDictionary, details: "cannot decode json into \(T.self)")
+ }
+
+ return object
+}
+
+// ---------------
+// MARK: Subscriptions
+// ---------------
+
+extension Client {
+ class SubscriptionRecord {
+ var subscriptionHandler: AnyObject?
+ // HandlerClosure captures the generic type info passed into the constructor of SubscriptionRecord,
+ // and 'unwraps' it so that it can be used with just a 'PFObject' instance.
+ // Technically, this should be a compiler no-op, as no witness tables should be used as 'PFObject' currently inherits from NSObject.
+ // Should we make PFObject ever a native swift class without the backing Objective-C runtime however,
+ // this becomes extremely important to have, and makes a ton more sense than just unsafeBitCast-ing everywhere.
+ var eventHandlerClosure: (Event, Client) -> Void
+ var errorHandlerClosure: (Error, Client) -> Void
+ var subscribeHandlerClosure: (Client) -> Void
+ var unsubscribeHandlerClosure: (Client) -> Void
+
+ let query: PFQuery
+ let requestId: RequestId
+
+ init(query: PFQuery, requestId: RequestId, handler: T) where T:SubscriptionHandling {
+ self.query = query as! PFQuery
+ self.requestId = requestId
+
+ subscriptionHandler = handler
+
+ // This is needed because swift requires 'handlerClosure' to be fully initialized before we setup the
+ // capture list for the closure.
+ eventHandlerClosure = { _, _ in }
+ errorHandlerClosure = { _, _ in }
+ subscribeHandlerClosure = { _ in }
+ unsubscribeHandlerClosure = { _ in }
+
+ eventHandlerClosure = { [weak self] event, client in
+ guard let handler = self?.subscriptionHandler as? T else {
+ return
+ }
+
+ handler.didReceive(Event(event: event), forQuery: query, inClient: client)
+ }
+
+ errorHandlerClosure = { [weak self] error, client in
+ guard let handler = self?.subscriptionHandler as? T else {
+ return
+ }
+
+ handler.didEncounter(error, forQuery: query, inClient: client)
+ }
+
+ subscribeHandlerClosure = { [weak self] client in
+ guard let handler = self?.subscriptionHandler as? T else {
+ return
+ }
+
+ handler.didSubscribe(toQuery: query, inClient: client)
+ }
+
+ unsubscribeHandlerClosure = { [weak self] client in
+ guard let handler = self?.subscriptionHandler as? T else {
+ return
+ }
+
+ handler.didUnsubscribe(fromQuery: query, inClient: client)
+ }
+ }
+ }
+}
+extension Client {
+ // An opaque placeholder structed used to ensure that we type-safely create request IDs and don't shoot ourself in
+ // the foot with array indexes.
+ struct RequestId: Equatable {
+ let value: Int
+
+ init(value: Int) {
+ self.value = value
+ }
+ }
+}
+
+func == (first: Client.RequestId, second: Client.RequestId) -> Bool {
+ return first.value == second.value
+}
+
+// ---------------
+// MARK: Web Socket
+// ---------------
+
+extension Client: WebSocketDelegate {
+ public func didReceive(event: WebSocketEvent, client: WebSocket) {
+ switch event {
+
+ case .connected(_):
+ isConnecting = false
+ let sessionToken = PFUser.current()?.sessionToken ?? ""
+ _ = self.sendOperationAsync(.connect(applicationId: applicationId, sessionToken: sessionToken, clientKey: clientKey))
+ case .disconnected(let reason, let code):
+ isConnecting = false
+ if shouldPrintWebSocketLog { NSLog("ParseLiveQuery: WebSocket did disconnect with error: \(reason) code:\(code)") }
+
+ // TODO: Better retry logic, unless `disconnect()` was explicitly called
+ if !userDisconnected {
+ reconnect()
+ }
+ case .text(let text):
+ handleOperationAsync(text).continueWith { [weak self] task in
+ if let error = task.error, self?.shouldPrintWebSocketLog == true {
+ NSLog("ParseLiveQuery: Error processing message: \(error)")
+ }
+ }
+ case .binary(_):
+ if shouldPrintWebSocketLog { NSLog("ParseLiveQuery: Received binary data but we don't handle it...") }
+ case .error(let error):
+ NSLog("ParseLiveQuery: Error processing message: \(String(describing: error))")
+ case .viabilityChanged(let isViable):
+ if shouldPrintWebSocketLog { NSLog("ParseLiveQuery: WebSocket viability channged to \(isViable ? "" : "not-")viable") }
+ if !isViable {
+ isConnecting = false
+ }
+ // TODO: Better retry logic, unless `disconnect()` was explicitly called
+ if !userDisconnected, isViable {
+ reconnect()
+ }
+ case .reconnectSuggested(let isSuggested):
+ if shouldPrintWebSocketLog { NSLog("ParseLiveQuery: WebSocket reconnect is \(isSuggested ? "" : "not ")suggested") }
+ // TODO: Better retry logic, unless `disconnect()` was explicitly called
+ if !userDisconnected, isSuggested {
+ reconnect()
+ }
+ case .cancelled:
+ isConnecting = false
+ if shouldPrintWebSocketLog { NSLog("ParseLiveQuery: WebSocket connection cancelled...") }
+ // TODO: Better retry logic, unless `disconnect()` was explicitly called
+ if !userDisconnected {
+ reconnect()
+ }
+ case .pong(_):
+ if shouldPrintWebSocketLog { NSLog("ParseLiveQuery: Received pong but we don't handle it...") }
+ case .ping(_):
+ if shouldPrintWebSocketLog { NSLog("ParseLiveQuery: Received ping but we don't handle it...") }
+ }
+ }
+}
+
+// -------------------
+// MARK: Operations
+// -------------------
+
+extension Event {
+ init(serverResponse: ServerResponse, requestId: inout Client.RequestId) throws {
+ switch serverResponse {
+ case .enter(let reqId, let object):
+ requestId = reqId
+ self = .entered(try parseObject(object))
+
+ case .leave(let reqId, let object):
+ requestId = reqId
+ self = .left(try parseObject(object))
+
+ case .create(let reqId, let object):
+ requestId = reqId
+ self = .created(try parseObject(object))
+
+ case .update(let reqId, let object):
+ requestId = reqId
+ self = .updated(try parseObject(object))
+
+ case .delete(let reqId, let object):
+ requestId = reqId
+ self = .deleted(try parseObject(object))
+
+ default: fatalError("Invalid state reached")
+ }
+ }
+}
+
+extension Client {
+ fileprivate func subscriptionRecord(_ requestId: RequestId) -> SubscriptionRecord? {
+ guard
+ let recordIndex = self.subscriptions.firstIndex(where: { $0.requestId == requestId }) else {
+ return nil
+ }
+ let record = self.subscriptions[recordIndex]
+ return record.subscriptionHandler != nil ? record : nil
+ }
+
+ func sendOperationAsync(_ operation: ClientOperation) -> Task {
+ return Task(.queue(queue)) {
+ let jsonEncoded = operation.JSONObjectRepresentation
+ let jsonData = try JSONSerialization.data(withJSONObject: jsonEncoded, options: JSONSerialization.WritingOptions(rawValue: 0))
+ let jsonString = String(data: jsonData, encoding: String.Encoding.utf8)
+ if self.shouldPrintWebSocketTrace { NSLog("ParseLiveQuery: Sending message: \(jsonString!)") }
+ self.socket?.write(string: jsonString!)
+ }
+ }
+
+ func handleOperationAsync(_ string: String) -> Task {
+ return Task(.queue(queue)) {
+ if self.shouldPrintWebSocketTrace { NSLog("ParseLiveQuery: Received message: \(string)") }
+ guard
+ let jsonData = string.data(using: String.Encoding.utf8),
+ let jsonDecoded = try JSONSerialization.jsonObject(with: jsonData, options: JSONSerialization.ReadingOptions(rawValue: 0))
+ as? [String:AnyObject],
+ let response: ServerResponse = try? ServerResponse(json: jsonDecoded)
+ else {
+ throw LiveQueryErrors.InvalidResponseError(response: string)
+ }
+
+ switch response {
+ case .connected:
+ let sessionToken = PFUser.current()?.sessionToken
+ self.subscriptions.forEach {
+ _ = self.sendOperationAsync(.subscribe(requestId: $0.requestId, query: $0.query, sessionToken: sessionToken))
+ }
+
+ case .redirect:
+ // TODO: Handle redirect.
+ break
+
+ case .subscribed(let requestId):
+ self.subscriptionRecord(requestId)?.subscribeHandlerClosure(self)
+
+ case .unsubscribed(let requestId):
+ guard
+ let recordIndex = self.subscriptions.firstIndex(where: { $0.requestId == requestId })
+ else {
+ break
+ }
+ let record: SubscriptionRecord = self.subscriptions[recordIndex]
+ record.unsubscribeHandlerClosure(self)
+ self.subscriptions.remove(at: recordIndex)
+
+ case .create, .delete, .enter, .leave, .update:
+ var requestId: RequestId = RequestId(value: 0)
+ guard
+ let event: Event = try? Event(serverResponse: response, requestId: &requestId),
+ let record = self.subscriptionRecord(requestId)
+ else {
+ break
+ }
+ record.eventHandlerClosure(event, self)
+
+ case .error(let requestId, let code, let error, let reconnect):
+ let error = LiveQueryErrors.ServerReportedError(code: code, error: error, reconnect: reconnect)
+ if let requestId = requestId {
+ self.subscriptionRecord(requestId)?.errorHandlerClosure(error, self)
+ } else {
+ throw error
+ }
+ }
+ }
+ }
+}
diff --git a/ParseLiveQuery/ParseLiveQuery/Internal/Common.swift b/ParseLiveQuery/ParseLiveQuery/Internal/Common.swift
new file mode 100644
index 000000000..673ecc16a
--- /dev/null
+++ b/ParseLiveQuery/ParseLiveQuery/Internal/Common.swift
@@ -0,0 +1,17 @@
+/**
+ * Copyright (c) 2016-present, Parse, LLC.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+
+/**
+ * Add support for both SPM and Dynamic Framework Imports TODO: (@dplewis)
+ */
+#if canImport(ParseCore)
+ @_exported import ParseCore
+#else
+ @_exported import Parse
+#endif
diff --git a/ParseLiveQuery/ParseLiveQuery/Internal/Errors.swift b/ParseLiveQuery/ParseLiveQuery/Internal/Errors.swift
new file mode 100644
index 000000000..d657a1f48
--- /dev/null
+++ b/ParseLiveQuery/ParseLiveQuery/Internal/Errors.swift
@@ -0,0 +1,61 @@
+/**
+ * Copyright (c) 2016-present, Parse, LLC.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+
+/**
+ Namespace struct for all errors reported by the Live Query SDK.
+ */
+public struct LiveQueryErrors {
+ fileprivate init() {}
+
+ /**
+ An error that is reported when the server returns a response that cannot be parsed.
+ */
+ public struct InvalidResponseError: Error {
+ /// Response string of the error.
+ public let response: String
+ }
+
+ /**
+ An error that is reported when the server does not accept a query we've sent to it.
+ */
+ public struct InvalidQueryError: Error {
+ }
+
+ /**
+ An error that is reported when the server returns valid JSON, but it doesn't match the format we expect.
+ */
+ public struct InvalidJSONError: Error {
+ /// JSON used for matching.
+ public let json: [String:AnyObject]
+ /// Key that was expected to match.
+ public let expectedKey: String
+ }
+
+ /**
+ An error that is reported when the server returns valid JSON, but it doesn't match the format we expect.
+ */
+ public struct InvalidJSONObject: Error {
+ /// JSON used for matching.
+ public let json: [String:AnyObject]
+ /// Details about the error
+ public let details: String
+ }
+
+ /**
+ An error that is reported when the live query server encounters an internal error.
+ */
+ public struct ServerReportedError: Error {
+ /// Error code reported by the server.
+ public let code: Int
+ /// String error reported by the server.
+ public let error: String
+ /// Boolean value representing whether a client should reconnect.
+ public let reconnect: Bool
+ }
+}
diff --git a/ParseLiveQuery/ParseLiveQuery/Internal/Operation.swift b/ParseLiveQuery/ParseLiveQuery/Internal/Operation.swift
new file mode 100644
index 000000000..ba6325847
--- /dev/null
+++ b/ParseLiveQuery/ParseLiveQuery/Internal/Operation.swift
@@ -0,0 +1,110 @@
+/**
+ * Copyright (c) 2016-present, Parse, LLC.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+
+import Foundation
+
+enum ClientOperation {
+ case connect(applicationId: String, sessionToken: String, clientKey: String?)
+ case subscribe(requestId: Client.RequestId, query: PFQuery, sessionToken: String?)
+ case update(requestId: Client.RequestId, query: PFQuery)
+ case unsubscribe(requestId: Client.RequestId)
+
+ var JSONObjectRepresentation: [String : Any] {
+ switch self {
+ case .connect(let applicationId, let sessionToken, let clientKey):
+ var message: [String: Any] = [ "op": "connect", "applicationId": applicationId, "sessionToken": sessionToken ]
+ if let clientKey = clientKey {
+ message.updateValue(clientKey, forKey: "clientKey")
+ }
+ return message
+
+ case .subscribe(let requestId, let query, let sessionToken):
+ var result: [String: Any] = [ "op": "subscribe", "requestId": requestId.value, "query": Dictionary(query: query) ]
+ if let sessionToken = sessionToken {
+ result["sessionToken"] = sessionToken
+ }
+ return result
+
+ case .update(let requestId, let query):
+ return [ "op": "update", "requestId": requestId.value, "query": Dictionary(query: query) ]
+
+ case .unsubscribe(let requestId):
+ return [ "op": "unsubscribe", "requestId": requestId.value ]
+ }
+ }
+}
+
+enum ServerResponse {
+ case redirect(url: String)
+ case connected
+
+ case subscribed(requestId: Client.RequestId)
+ case unsubscribed(requestId: Client.RequestId)
+
+ case enter(requestId: Client.RequestId, object: [String : AnyObject])
+ case leave(requestId: Client.RequestId, object: [String : AnyObject])
+ case update(requestId: Client.RequestId, object: [String : AnyObject])
+ case create(requestId: Client.RequestId, object: [String : AnyObject])
+ case delete(requestId: Client.RequestId, object: [String : AnyObject])
+
+ case error(requestId: Client.RequestId?, code: Int, error: String, reconnect: Bool)
+
+ init(json: [String : AnyObject]) throws {
+ func jsonValue(_ json: [String:AnyObject], _ key: String) throws -> T {
+ guard let value = json[key] as? T
+ else {
+ throw LiveQueryErrors.InvalidJSONError(json: json, expectedKey: key)
+ }
+ return value
+ }
+
+ func jsonRequestId(_ json: [String:AnyObject]) throws -> Client.RequestId {
+ let requestId: Int = try jsonValue(json, "requestId")
+ return Client.RequestId(value: requestId)
+ }
+
+ func subscriptionEvent(
+ _ json: [String:AnyObject],
+ _ eventType: (Client.RequestId, [String : AnyObject]) -> ServerResponse
+ ) throws -> ServerResponse {
+ return eventType(try jsonRequestId(json), try jsonValue(json, "object"))
+ }
+
+ let rawOperation: String = try jsonValue(json, "op")
+ switch rawOperation {
+ case "connected":
+ self = .connected
+
+ case "redirect":
+ self = .redirect(url: try jsonValue(json, "url"))
+
+ case "subscribed":
+ self = .subscribed(requestId: try jsonRequestId(json))
+ case "unsubscribed":
+ self = .unsubscribed(requestId: try jsonRequestId(json))
+
+ case "enter": self = try subscriptionEvent(json, ServerResponse.enter)
+ case "leave": self = try subscriptionEvent(json, ServerResponse.leave)
+ case "update": self = try subscriptionEvent(json, ServerResponse.update)
+ case "create": self = try subscriptionEvent(json, ServerResponse.create)
+ case "delete": self = try subscriptionEvent(json, ServerResponse.delete)
+
+ case "error":
+ self = .error(
+ requestId: try? jsonRequestId(json),
+ code: try jsonValue(json, "code"),
+ error: try jsonValue(json, "error"),
+ reconnect: try jsonValue(json, "reconnect")
+ )
+
+ default:
+ throw LiveQueryErrors.InvalidJSONError(json: json, expectedKey: "op")
+ }
+ }
+}
diff --git a/ParseLiveQuery/ParseLiveQuery/Internal/QueryEncoder.swift b/ParseLiveQuery/ParseLiveQuery/Internal/QueryEncoder.swift
new file mode 100644
index 000000000..8d84f0e6c
--- /dev/null
+++ b/ParseLiveQuery/ParseLiveQuery/Internal/QueryEncoder.swift
@@ -0,0 +1,93 @@
+/**
+ * Copyright (c) 2016-present, Parse, LLC.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+
+import Foundation
+
+/**
+ NOTE: This is super hacky, and we need a better answer for this.
+ */
+extension Dictionary where Key: ExpressibleByStringLiteral, Value: AnyObject {
+ init(query: PFQuery) {
+ self.init()
+ let queryState = query.value(forKey: "state") as AnyObject?
+ if let className = queryState?.value(forKey: "parseClassName") {
+ self["className"] = className as? Value
+ }
+ if let conditions = queryState?.value(forKey: "conditions") as? [String:AnyObject] {
+ self["where"] = conditions.encodedQueryDictionary as? Value
+ } else {
+ self["where"] = [:] as? Value
+ }
+ }
+}
+
+extension Dictionary where Key: ExpressibleByStringLiteral, Value: AnyObject {
+ var encodedQueryDictionary: Dictionary {
+ var encodedQueryDictionary = Dictionary()
+ for (key, val) in self {
+ if let array = val as? [PFQuery] {
+ var queries:[Value] = []
+ for query in array {
+ let queryState = query.value(forKey: "state") as AnyObject?
+ if let conditions: [String:AnyObject] = queryState?.value(forKey: "conditions") as? [String:AnyObject], let encoded = conditions.encodedQueryDictionary as? Value {
+ queries.append(encoded)
+ }
+ }
+ encodedQueryDictionary[key] = queries as? Value
+ } else if let geoPoints = val as? [PFGeoPoint] {
+ var points:[Value] = []
+ for point in geoPoints {
+ points.append(point.encodedDictionary as! Value)
+ }
+ encodedQueryDictionary[key] = points as? Value
+ } else if let dict = val as? [String:AnyObject] {
+ encodedQueryDictionary[key] = dict.encodedQueryDictionary as? Value
+ } else if let geoPoint = val as? PFGeoPoint {
+ encodedQueryDictionary[key] = geoPoint.encodedDictionary as? Value
+ } else if let object = val as? PFObject {
+ encodedQueryDictionary[key] = (try? PFPointerObjectEncoder.object().encode(object)) as? Value
+ } else if let query = val as? PFQuery {
+ let queryState = query.value(forKey: "state") as AnyObject?
+ if let conditions: [String:AnyObject] = queryState?.value(forKey: "conditions") as? [String:AnyObject], let encoded = conditions.encodedQueryDictionary as? Value {
+ encodedQueryDictionary[key] = encoded
+ }
+ } else if let date = val as? Date {
+ encodedQueryDictionary[key] = ["__type": "Date", "iso": date.encodedString] as? Value
+ } else {
+ encodedQueryDictionary[key] = val
+ }
+ }
+ return encodedQueryDictionary
+ }
+}
+
+extension PFGeoPoint {
+ var encodedDictionary: [String:Any] {
+ return ["__type": "GeoPoint",
+ "latitude": latitude,
+ "longitude": longitude]
+ }
+}
+
+fileprivate extension Formatter {
+ static let iso8601: DateFormatter = {
+ let formatter = DateFormatter()
+ formatter.calendar = Calendar(identifier: .iso8601)
+ formatter.locale = Locale(identifier: "en_US_POSIX")
+ formatter.timeZone = TimeZone(secondsFromGMT: 0)
+ formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSXXXXX"
+ return formatter
+ }()
+}
+
+fileprivate extension Date {
+ var encodedString: String {
+ return Formatter.iso8601.string(from: self)
+ }
+}
diff --git a/ParseLiveQuery/ParseLiveQuery/ObjCCompat.swift b/ParseLiveQuery/ParseLiveQuery/ObjCCompat.swift
new file mode 100644
index 000000000..26ab1e192
--- /dev/null
+++ b/ParseLiveQuery/ParseLiveQuery/ObjCCompat.swift
@@ -0,0 +1,367 @@
+/**
+ * Copyright (c) 2016-present, Parse, LLC.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+
+import Foundation
+import BoltsSwift
+
+/**
+ This protocol describes the interface for handling events from a live query client.
+
+ You can use this protocol on any custom class of yours, instead of Subscription, if it fits your use case better.
+ */
+@objc(PFLiveQuerySubscriptionHandling)
+public protocol ObjCCompat_SubscriptionHandling {
+
+ /**
+ Tells the handler that an event has been received from the live query server.
+
+ - parameter query: The query that the event occurred on.
+ - parameter event: The event that has been recieved from the server.
+ - parameter client: The live query client which received this event.
+ */
+ @objc(liveQuery:didRecieveEvent:inClient:)
+ optional func didRecieveEvent(_ query: PFQuery, event: PFLiveQueryEvent, client: Client)
+
+ /**
+ Tells the handler that an error has been received from the live query server.
+
+ - parameter query: The query that the error occurred on.
+ - parameter error: The error that the server has encountered.
+ - parameter client: The live query client which received this error.
+ */
+ @objc(liveQuery:didEncounterError:inClient:)
+ optional func didRecieveError(_ query: PFQuery, error: NSError, client: Client)
+
+ /**
+ Tells the handler that a query has been successfully registered with the server.
+
+ - note: This may be invoked multiple times if the client disconnects/reconnects.
+
+ - parameter query: The query that has been subscribed.
+ - parameter client: The live query client which subscribed this query.
+ */
+ @objc(liveQuery:didSubscribeInClient:)
+ optional func didSubscribe(_ query: PFQuery, client: Client)
+
+ /**
+ Tells the handler that a query has been successfully deregistered from the server.
+
+ - note: This is not called unless `unregister()` is explicitly called.
+
+ - parameter query: The query that has been unsubscribed.
+ - parameter client: The live query client which unsubscribed this query.
+ */
+ @objc(liveQuery:didUnsubscribeInClient:)
+ optional func didUnsubscribe(_ query: PFQuery, client: Client)
+}
+
+// HACK: Compiler bug causes enums (and sometimes classes) that are declared in structs that are marked as @objc
+// to not actually be emitted by the compiler (lolwut?). Moving this to global scope fixes the problem, but we can't
+// change the objc name of an enum either, so we pollute the swift namespace here.
+// TODO: Fix this eventually.
+
+/**
+ A type of an update event on a specific object from the live query server.
+ */
+@objc
+public enum PFLiveQueryEventType: Int {
+ /// The object has been updated, and is now included in the query.
+ case entered
+ /// The object has been updated, and is no longer included in the query.
+ case left
+ /// The object has been created, and is a part of the query.
+ case created
+ /// The object has been updated, and is still a part of the query.
+ case updated
+ /// The object has been deleted, and is no longer included in the query.
+ case deleted
+}
+
+/**
+ Represents an update on a specific object from the live query server.
+ */
+@objc
+open class PFLiveQueryEvent: NSObject {
+ /// Type of the event.
+ @objc
+ public let type: PFLiveQueryEventType
+
+ /// Object this event is for.
+ @objc
+ public let object: PFObject
+
+ init(type: PFLiveQueryEventType, object: PFObject) {
+ self.type = type
+ self.object = object
+ }
+}
+
+/**
+ This struct wraps up all of our Objective-C compatibility layer. You should never need to touch this if you're using Swift.
+ */
+public struct ObjCCompat {
+ fileprivate init() { }
+
+ /**
+ A default implementation of the SubscriptionHandling protocol, using blocks for callbacks.
+ */
+ @objc(PFLiveQuerySubscription)
+ open class Subscription: NSObject {
+ public typealias SubscribeHandler = @convention(block) (PFQuery) -> Void
+ public typealias ErrorHandler = @convention(block) (PFQuery, NSError) -> Void
+ public typealias EventHandler = @convention(block) (PFQuery, PFLiveQueryEvent) -> Void
+ public typealias ObjectHandler = @convention(block) (PFQuery, PFObject) -> Void
+
+ var subscribeHandlers = [SubscribeHandler]()
+ var unsubscribeHandlers = [SubscribeHandler]()
+ var errorHandlers = [ErrorHandler]()
+ var eventHandlers = [EventHandler]()
+
+ /**
+ Register a callback for when a client succesfully subscribes to a query.
+
+ - parameter handler: The callback to register.
+
+ - returns: The same subscription, for easy chaining.
+ */
+ @objc(addSubscribeHandler:)
+ open func addSubscribeHandler(_ handler: @escaping SubscribeHandler) -> Subscription {
+ subscribeHandlers.append(handler)
+ return self
+ }
+
+ /**
+ Register a callback for when a query has been unsubscribed.
+
+ - parameter handler: The callback to register.
+
+ - returns: The same subscription, for easy chaining.
+ */
+ @objc(addUnsubscribeHandler:)
+ open func addUnsubscribeHandler(_ handler: @escaping SubscribeHandler) -> Subscription {
+ unsubscribeHandlers.append(handler)
+ return self
+ }
+
+ /**
+ Register a callback for when an error occurs.
+
+ - parameter handler: The callback to register.
+
+ - returns: The same subscription, for easy chaining.
+ */
+ @objc(addErrorHandler:)
+ open func addErrorHandler(_ handler: @escaping ErrorHandler) -> Subscription {
+ errorHandlers.append(handler)
+ return self
+ }
+
+ /**
+ Register a callback for when an event occurs.
+
+ - parameter handler: The callback to register.
+
+ - returns: The same subscription, for easy chaining.
+ */
+ @objc(addEventHandler:)
+ open func addEventHandler(_ handler: @escaping EventHandler) -> Subscription {
+ eventHandlers.append(handler)
+ return self
+ }
+
+ /**
+ Register a callback for when an object enters a query.
+
+ - parameter handler: The callback to register.
+
+ - returns: The same subscription, for easy chaining.
+ */
+ @objc(addEnterHandler:)
+ open func addEnterHandler(_ handler: @escaping ObjectHandler) -> Subscription {
+ return addEventHandler { $1.type == .entered ? handler($0, $1.object) : () }
+ }
+
+ /**
+ Register a callback for when an object leaves a query.
+
+ - parameter handler: The callback to register.
+
+ - returns: The same subscription, for easy chaining.
+ */
+ @objc(addLeaveHandler:)
+ open func addLeaveHandler(_ handler: @escaping ObjectHandler) -> Subscription {
+ return addEventHandler { $1.type == .left ? handler($0, $1.object) : () }
+ }
+
+ /**
+ Register a callback for when an object that matches the query is created.
+
+ - parameter handler: The callback to register.
+
+ - returns: The same subscription, for easy chaining.
+ */
+ @objc(addCreateHandler:)
+ open func addCreateHandler(_ handler: @escaping ObjectHandler) -> Subscription {
+ return addEventHandler { $1.type == .created ? handler($0, $1.object) : () }
+ }
+
+ /**
+ Register a callback for when an object that matches the query is updated.
+
+ - parameter handler: The callback to register.
+
+ - returns: The same subscription, for easy chaining.
+ */
+ @objc(addUpdateHandler:)
+ open func addUpdateHandler(_ handler: @escaping ObjectHandler) -> Subscription {
+ return addEventHandler { $1.type == .updated ? handler($0, $1.object) : () }
+ }
+
+ /**
+ Register a callback for when an object that matches the query is deleted.
+
+ - parameter handler: The callback to register.
+
+ - returns: The same subscription, for easy chaining.
+ */
+ @objc(addDeleteHandler:)
+ open func addDeleteHandler(_ handler: @escaping ObjectHandler) -> Subscription {
+ return addEventHandler { $1.type == .deleted ? handler($0, $1.object) : () }
+ }
+ }
+}
+
+extension ObjCCompat.Subscription: ObjCCompat_SubscriptionHandling {
+ public func didRecieveEvent(_ query: PFQuery, event: PFLiveQueryEvent, client: Client) {
+ eventHandlers.forEach { $0(query, event) }
+ }
+
+ public func didRecieveError(_ query: PFQuery, error: NSError, client: Client) {
+ errorHandlers.forEach { $0(query, error) }
+ }
+
+ public func didSubscribe(_ query: PFQuery, client: Client) {
+ subscribeHandlers.forEach { $0(query) }
+ }
+
+ public func didUnsubscribe(_ query: PFQuery, client: Client) {
+ unsubscribeHandlers.forEach { $0(query) }
+ }
+}
+
+extension Client {
+ fileprivate class HandlerConverter: SubscriptionHandling {
+ typealias T = PFObject
+
+ fileprivate static var associatedObjectKey: Int = 0
+ fileprivate weak var handler: ObjCCompat_SubscriptionHandling?
+
+ init(handler: ObjCCompat_SubscriptionHandling) {
+ self.handler = handler
+
+ objc_setAssociatedObject(handler, &HandlerConverter.associatedObjectKey, self, .OBJC_ASSOCIATION_RETAIN)
+ }
+
+ fileprivate func didReceive(_ event: Event, forQuery query: PFQuery, inClient client: Client) {
+ handler?.didRecieveEvent?(query, event: PFLiveQueryEvent(event: event), client: client)
+ }
+
+ fileprivate func didEncounter(_ error: Error, forQuery query: PFQuery, inClient client: Client) {
+ handler?.didRecieveError?(query, error: error as NSError, client: client)
+ }
+
+ fileprivate func didSubscribe(toQuery query: PFQuery, inClient client: Client) {
+ handler?.didSubscribe?(query, client: client)
+ }
+
+ fileprivate func didUnsubscribe(fromQuery query: PFQuery, inClient client: Client) {
+ handler?.didUnsubscribe?(query, client: client)
+ }
+ }
+
+ /**
+ Registers a query for live updates, using a custom subscription handler.
+
+ - parameter query: The query to register for updates.
+ - parameter handler: A custom subscription handler.
+
+ - returns: The subscription that has just been registered.
+ */
+ @objc(subscribeToQuery:withHandler:)
+ public func _PF_objc_subscribe(
+ _ query: PFQuery, handler: ObjCCompat_SubscriptionHandling
+ ) -> ObjCCompat_SubscriptionHandling {
+ let swiftHandler = HandlerConverter(handler: handler)
+ _ = subscribe(query, handler: swiftHandler)
+ return handler
+ }
+
+ /**
+ Registers a query for live updates, using the default subscription handler.
+
+ - parameter query: The query to register for updates.
+
+ - returns: The subscription that has just been registered.
+ */
+ @objc(subscribeToQuery:)
+ public func _PF_objc_subscribe(_ query: PFQuery) -> ObjCCompat.Subscription {
+ let subscription = ObjCCompat.Subscription()
+ _ = _PF_objc_subscribe(query, handler: subscription)
+ return subscription
+ }
+
+ /**
+ Unsubscribes a specific handler from a query.
+
+ - parameter query: The query to unsubscribe from.
+ - parameter handler: The specific handler to unsubscribe from.
+ */
+ @objc(unsubscribeFromQuery:withHandler:)
+ public func _PF_objc_unsubscribe(_ query: PFQuery, subscriptionHandler: ObjCCompat_SubscriptionHandling) {
+ unsubscribe { record in
+ guard let handler = record.subscriptionHandler as? HandlerConverter
+ else {
+ return false
+ }
+ return record.query == query && handler.handler === subscriptionHandler
+ }
+ }
+}
+
+// HACK: Another compiler bug - if you have a required initializer with a generic type, the compiler simply refuses to
+// emit the entire class altogether. Moving this to an extension for now solves the issue.
+
+extension PFLiveQueryEvent {
+ convenience init(event: ParseLiveQuery.Event) {
+ let results: (type: PFLiveQueryEventType, object: PFObject) = {
+ switch event {
+ case .entered(let object): return (.entered, object)
+ case .left(let object): return (.left, object)
+ case .created(let object): return (.created, object)
+ case .updated(let object): return (.updated, object)
+ case .deleted(let object): return (.deleted, object)
+ }
+ }()
+
+ self.init(type: results.type, object: results.object)
+ }
+}
+
+extension PFQuery {
+ /**
+ Register this PFQuery for updates with Live Queries.
+ This uses the shared live query client, and creates a default subscription handler for you.
+
+ - returns: The created subscription for observing.
+ */
+ @objc(subscribe)
+ public func _PF_objc_subscribe() -> ObjCCompat.Subscription {
+ return Client.shared._PF_objc_subscribe(self as! PFQuery)
+ }
+}
diff --git a/ParseLiveQuery/ParseLiveQuery/PFQuery+Subscribe.swift b/ParseLiveQuery/ParseLiveQuery/PFQuery+Subscribe.swift
new file mode 100644
index 000000000..62e4a12eb
--- /dev/null
+++ b/ParseLiveQuery/ParseLiveQuery/PFQuery+Subscribe.swift
@@ -0,0 +1,10 @@
+/**
+ * Copyright (c) 2016-present, Parse, LLC.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+
+import Foundation
diff --git a/ParseLiveQuery/ParseLiveQuery/Parse+LiveQuery.swift b/ParseLiveQuery/ParseLiveQuery/Parse+LiveQuery.swift
new file mode 100644
index 000000000..06110a609
--- /dev/null
+++ b/ParseLiveQuery/ParseLiveQuery/Parse+LiveQuery.swift
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2016-present, Parse, LLC.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+
+//import ParseCore
+
+extension Parse {
+ static func validatedCurrentConfiguration() -> ParseClientConfiguration {
+ guard let configuration = Parse.currentConfiguration else {
+ preconditionFailure("Parse SDK is not initialized. Call Parse.initializeWithConfiguration() before loading live query client.")
+ }
+ return configuration
+ }
+}
diff --git a/ParseLiveQuery/ParseLiveQuery/Resources/Info.plist b/ParseLiveQuery/ParseLiveQuery/Resources/Info.plist
new file mode 100644
index 000000000..39fee82e8
--- /dev/null
+++ b/ParseLiveQuery/ParseLiveQuery/Resources/Info.plist
@@ -0,0 +1,24 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ en
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ BNDL
+ CFBundleShortVersionString
+ 2.2.0
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ 2.2.0
+
+
diff --git a/ParseLiveQuery/ParseLiveQuery/Subscription.swift b/ParseLiveQuery/ParseLiveQuery/Subscription.swift
new file mode 100644
index 000000000..c0d041e80
--- /dev/null
+++ b/ParseLiveQuery/ParseLiveQuery/Subscription.swift
@@ -0,0 +1,250 @@
+/**
+ * Copyright (c) 2016-present, Parse, LLC.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+
+import Foundation
+//import ParseCore
+import BoltsSwift
+
+/**
+ This protocol describes the interface for handling events from a liveQuery client.
+
+ You can use this protocol on any custom class of yours, instead of Subscription, if it fits your use case better.
+ */
+public protocol SubscriptionHandling: AnyObject {
+ /// The type of the PFObject subclass that this handler uses.
+ associatedtype PFObjectSubclass: PFObject
+
+ /**
+ Tells the handler that an event has been received from the live query server.
+
+ - parameter event: The event that has been recieved from the server.
+ - parameter query: The query that the event occurred on.
+ - parameter client: The live query client which received this event.
+ */
+ func didReceive(_ event: Event, forQuery query: PFQuery, inClient client: Client)
+
+ /**
+ Tells the handler that an error has been received from the live query server.
+
+ - parameter error: The error that the server has encountered.
+ - parameter query: The query that the error occurred on.
+ - parameter client: The live query client which received this error.
+ */
+ func didEncounter(_ error: Error, forQuery query: PFQuery, inClient client: Client)
+
+ /**
+ Tells the handler that a query has been successfully registered with the server.
+
+ - note: This may be invoked multiple times if the client disconnects/reconnects.
+
+ - parameter query: The query that has been subscribed.
+ - parameter client: The live query client which subscribed this query.
+ */
+ func didSubscribe(toQuery query: PFQuery, inClient client: Client)
+
+ /**
+ Tells the handler that a query has been successfully deregistered from the server.
+
+ - note: This is not called unless `unregister()` is explicitly called.
+
+ - parameter query: The query that has been unsubscribed.
+ - parameter client: The live query client which unsubscribed this query.
+ */
+ func didUnsubscribe(fromQuery query: PFQuery, inClient client: Client)
+}
+
+/**
+ Represents an update on a specific object from the live query server.
+
+ - Entered: The object has been updated, and is now included in the query.
+ - Left: The object has been updated, and is no longer included in the query.
+ - Created: The object has been created, and is a part of the query.
+ - Updated: The object has been updated, and is still a part of the query.
+ - Deleted: The object has been deleted, and is no longer included in the query.
+ */
+public enum Event where T: PFObject {
+ /// The object has been updated, and is now included in the query
+ case entered(T)
+
+ /// The object has been updated, and is no longer included in the query
+ case left(T)
+
+ /// The object has been created, and is a part of the query
+ case created(T)
+
+ /// The object has been updated, and is still a part of the query
+ case updated(T)
+
+ /// The object has been deleted, and is no longer included in the query
+ case deleted(T)
+
+ init(event: Event) {
+ switch event {
+ case .entered(let value as T): self = .entered(value)
+ case .left(let value as T): self = .left(value)
+ case .created(let value as T): self = .created(value)
+ case .updated(let value as T): self = .updated(value)
+ case .deleted(let value as T): self = .deleted(value)
+ default: fatalError()
+ }
+ }
+}
+
+private func == (lhs: Event, rhs: Event) -> Bool {
+ switch (lhs, rhs) {
+ case (.entered(let obj1), .entered(let obj2)): return obj1 == obj2
+ case (.left(let obj1), .left(let obj2)): return obj1 == obj2
+ case (.created(let obj1), .created(let obj2)): return obj1 == obj2
+ case (.updated(let obj1), .updated(let obj2)): return obj1 == obj2
+ case (.deleted(let obj1), .deleted(let obj2)): return obj1 == obj2
+ default: return false
+ }
+}
+
+/**
+ A default implementation of the SubscriptionHandling protocol, using closures for callbacks.
+ */
+open class Subscription: SubscriptionHandling where T: PFObject {
+ fileprivate var errorHandlers: [(PFQuery, Error) -> Void] = []
+ fileprivate var eventHandlers: [(PFQuery, Event) -> Void] = []
+ fileprivate var subscribeHandlers: [(PFQuery) -> Void] = []
+ fileprivate var unsubscribeHandlers: [(PFQuery) -> Void] = []
+
+ /**
+ Creates a new subscription that can be used to handle updates.
+ */
+ public init() {
+ }
+
+ /**
+ Register a callback for when an error occurs.
+
+ - parameter handler: The callback to register.
+
+ - returns: The same subscription, for easy chaining
+ */
+ @discardableResult open func handleError(_ handler: @escaping (PFQuery, Error) -> Void) -> Subscription {
+ errorHandlers.append(handler)
+ return self
+ }
+
+ /**
+ Register a callback for when an event occurs.
+
+ - parameter handler: The callback to register.
+
+ - returns: The same subscription, for easy chaining.
+ */
+ @discardableResult open func handleEvent(_ handler: @escaping (PFQuery, Event) -> Void) -> Subscription {
+ eventHandlers.append(handler)
+ return self
+ }
+
+ /**
+ Register a callback for when a client succesfully subscribes to a query.
+
+ - parameter handler: The callback to register.
+
+ - returns: The same subscription, for easy chaining.
+ */
+ @discardableResult open func handleSubscribe(_ handler: @escaping (PFQuery) -> Void) -> Subscription {
+ subscribeHandlers.append(handler)
+ return self
+ }
+
+ /**
+ Register a callback for when a query has been unsubscribed.
+
+ - parameter handler: The callback to register.
+
+ - returns: The same subscription, for easy chaining.
+ */
+ @discardableResult open func handleUnsubscribe(_ handler: @escaping (PFQuery) -> Void) -> Subscription {
+ unsubscribeHandlers.append(handler)
+ return self
+ }
+
+ // ---------------
+ // MARK: SubscriptionHandling
+ // TODO: Move to extension once swift compiler is less crashy
+ // ---------------
+ public typealias PFObjectSubclass = T
+
+ open func didReceive(_ event: Event, forQuery query: PFQuery, inClient client: Client) {
+ eventHandlers.forEach { $0(query, event) }
+ }
+
+ open func didEncounter(_ error: Error, forQuery query: PFQuery, inClient client: Client) {
+ errorHandlers.forEach { $0(query, error) }
+ }
+
+ open func didSubscribe(toQuery query: PFQuery, inClient client: Client) {
+ subscribeHandlers.forEach { $0(query) }
+ }
+
+ open func didUnsubscribe(fromQuery query: PFQuery, inClient client: Client) {
+ unsubscribeHandlers.forEach { $0(query) }
+ }
+}
+
+extension Subscription {
+ /**
+ Register a callback for when an error occcurs of a specific type
+
+ Example:
+
+ subscription.handle(LiveQueryErrors.InvalidJSONError.self) { query, error in
+ print(error)
+ }
+
+ - parameter errorType: The error type to register for
+ - parameter handler: The callback to register
+
+ - returns: The same subscription, for easy chaining
+ */
+ @discardableResult public func handle(
+ _ errorType: E.Type = E.self,
+ _ handler: @escaping (PFQuery, E) -> Void
+ ) -> Subscription {
+ errorHandlers.append { query, error in
+ if let error = error as? E {
+ handler(query, error)
+ }
+ }
+ return self
+ }
+
+ /**
+ Register a callback for when an event occurs of a specific type
+
+ Example:
+
+ subscription.handle(Event.Created) { query, object in
+ // Called whenever an object is creaated
+ }
+
+ - parameter eventType: The event type to handle. You should pass one of the enum cases in `Event`
+ - parameter handler: The callback to register
+
+ - returns: The same subscription, for easy chaining
+
+ */
+ @discardableResult public func handle(_ eventType: @escaping (T) -> Event, _ handler: @escaping (PFQuery, T) -> Void) -> Subscription {
+ return handleEvent { query, event in
+ switch event {
+ case .entered(let obj) where eventType(obj) == event: handler(query, obj)
+ case .left(let obj) where eventType(obj) == event: handler(query, obj)
+ case .created(let obj) where eventType(obj) == event: handler(query, obj)
+ case .updated(let obj) where eventType(obj) == event: handler(query, obj)
+ case .deleted(let obj) where eventType(obj) == event: handler(query, obj)
+ default: return
+ }
+ }
+ }
+}
diff --git a/ParseStarterProject/OSX/ParseOSXStarterProject-Swift/ParseOSXStarterProject-Swift.xcodeproj/project.pbxproj b/ParseStarterProject/OSX/ParseOSXStarterProject-Swift/ParseOSXStarterProject-Swift.xcodeproj/project.pbxproj
index 4b0a00578..6515f8336 100644
--- a/ParseStarterProject/OSX/ParseOSXStarterProject-Swift/ParseOSXStarterProject-Swift.xcodeproj/project.pbxproj
+++ b/ParseStarterProject/OSX/ParseOSXStarterProject-Swift/ParseOSXStarterProject-Swift.xcodeproj/project.pbxproj
@@ -575,7 +575,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- MACOSX_DEPLOYMENT_TARGET = 10.9;
+ MACOSX_DEPLOYMENT_TARGET = 10.15;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
@@ -622,7 +622,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- MACOSX_DEPLOYMENT_TARGET = 10.9;
+ MACOSX_DEPLOYMENT_TARGET = 10.15;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = macosx;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
diff --git a/ParseStarterProject/OSX/ParseOSXStarterProject/ParseOSXStarterProject.xcodeproj/project.pbxproj b/ParseStarterProject/OSX/ParseOSXStarterProject/ParseOSXStarterProject.xcodeproj/project.pbxproj
index 7802a4ed8..e355fb058 100644
--- a/ParseStarterProject/OSX/ParseOSXStarterProject/ParseOSXStarterProject.xcodeproj/project.pbxproj
+++ b/ParseStarterProject/OSX/ParseOSXStarterProject/ParseOSXStarterProject.xcodeproj/project.pbxproj
@@ -605,7 +605,7 @@
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
LD_RUNPATH_SEARCH_PATHS = "@executable_path/../Frameworks";
- MACOSX_DEPLOYMENT_TARGET = 10.9;
+ MACOSX_DEPLOYMENT_TARGET = 10.15;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
};
@@ -648,7 +648,7 @@
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
LD_RUNPATH_SEARCH_PATHS = "@executable_path/../Frameworks";
- MACOSX_DEPLOYMENT_TARGET = 10.9;
+ MACOSX_DEPLOYMENT_TARGET = 10.15;
SDKROOT = macosx;
};
name = Release;
diff --git a/ParseStarterProject/OSX/ParseOSXStarterProject/ParseOSXStarterProject/AppDelegate.m b/ParseStarterProject/OSX/ParseOSXStarterProject/ParseOSXStarterProject/AppDelegate.m
index 497b40d7c..94c118032 100644
--- a/ParseStarterProject/OSX/ParseOSXStarterProject/ParseOSXStarterProject/AppDelegate.m
+++ b/ParseStarterProject/OSX/ParseOSXStarterProject/ParseOSXStarterProject/AppDelegate.m
@@ -9,7 +9,7 @@
#import "AppDelegate.h"
-#import
+#import
@implementation AppDelegate
diff --git a/ParseStarterProject/iOS/ParseStarterProject/ParseStarterProject/ParseStarterProjectAppDelegate.m b/ParseStarterProject/iOS/ParseStarterProject/ParseStarterProject/ParseStarterProjectAppDelegate.m
index adc76983e..3395f01ad 100644
--- a/ParseStarterProject/iOS/ParseStarterProject/ParseStarterProject/ParseStarterProjectAppDelegate.m
+++ b/ParseStarterProject/iOS/ParseStarterProject/ParseStarterProject/ParseStarterProjectAppDelegate.m
@@ -7,7 +7,7 @@
* of patent rights can be found in the PATENTS file in the same directory.
*/
-#import
+#import
// If you want to use any of the UI components, uncomment this line
// #import
diff --git a/ParseStarterProject/iOS/ParseStarterProject/ParseStarterProject/ParseStarterProjectViewController.m b/ParseStarterProject/iOS/ParseStarterProject/ParseStarterProject/ParseStarterProjectViewController.m
index 4a2382c54..296e4e4f1 100644
--- a/ParseStarterProject/iOS/ParseStarterProject/ParseStarterProject/ParseStarterProjectViewController.m
+++ b/ParseStarterProject/iOS/ParseStarterProject/ParseStarterProject/ParseStarterProjectViewController.m
@@ -9,7 +9,7 @@
#import "ParseStarterProjectViewController.h"
-#import
+#import
@implementation ParseStarterProjectViewController
diff --git a/Rakefile b/Rakefile
index dffb7ae41..3261c8042 100644
--- a/Rakefile
+++ b/Rakefile
@@ -16,7 +16,8 @@ release_folder = File.join(build_folder, 'release')
bolts_build_folder = File.join(script_folder, 'Carthage', 'Build')
bolts_folder = File.join(script_folder, 'Carthage', 'Checkouts', 'Bolts-ObjC')
ios_simulator = 'platform="iOS Simulator",name="iPhone 14"'
-tvos_simulator = 'platform="tvOS Simulator",name="Apple TV 4K"'
+tvos_simulator = 'platform="tvOS Simulator",name="Apple TV"'
+watchos_simulator = 'platform="watchOS Simulator",name="Apple Watch Series 8 (45mm)"'
module Constants
require 'plist'
@@ -34,6 +35,9 @@ module Constants
File.join(script_folder, 'ParseFacebookUtils', 'ParseFacebookUtils', 'Resources', 'Info-tvOS.plist'),
File.join(script_folder, 'ParseTwitterUtils', 'ParseTwitterUtils', 'Resources', 'Info-iOS.plist'),
File.join(script_folder, 'ParseUI', 'ParseUI', 'Resources', 'Info-iOS.plist'),
+ File.join(script_folder, 'ParseLiveQuery', 'ParseLiveQuery', 'Resources', 'Info.plist'),
+ File.join(script_folder, 'ParseLiveQuery', 'ParseLiveQuery-tvOS', 'Info.plist'),
+ File.join(script_folder, 'ParseLiveQuery', 'ParseLiveQuery-watchOS', 'Info.plist'),
File.join(script_folder, 'ParseStarterProject', 'iOS', 'ParseStarterProject', 'Resources', 'Info.plist'),
File.join(script_folder, 'ParseStarterProject', 'iOS', 'ParseStarterProject-Swift', 'Resources', 'Info.plist'),
File.join(script_folder, 'ParseStarterProject', 'OSX', 'ParseOSXStarterProject', 'Resources', 'Info.plist'),
@@ -148,6 +152,80 @@ namespace :build do
end
end
+ namespace :parse_live_query do
+ desc 'Build iOS LiveQuery framework.'
+ task :ios do
+ task = XCTask::BuildFrameworkTask.new do |t|
+ t.directory = script_folder
+ t.build_directory = File.join(build_folder, 'iOS')
+ t.framework_type = XCTask::FrameworkType::IOS
+ t.framework_name = 'ParseLiveQuery.framework'
+ t.workspace = 'Parse.xcworkspace'
+ t.scheme = 'ParseLiveQuery-iOS'
+ t.configuration = 'Release'
+ end
+ result = task.execute
+ unless result
+ puts 'Failed to build iOS LiveQuery Framework.'
+ exit(1)
+ end
+ end
+
+ desc 'Build macOS LiveQuery framework.'
+ task :macos do
+ task = XCTask::BuildFrameworkTask.new do |t|
+ t.directory = script_folder
+ t.build_directory = File.join(build_folder, 'macOS')
+ t.framework_type = XCTask::FrameworkType::OSX
+ t.framework_name = 'ParseLiveQuery.framework'
+ t.workspace = 'Parse.xcworkspace'
+ t.scheme = 'ParseLiveQuery-OSX'
+ t.configuration = 'Release'
+ end
+ result = task.execute
+ unless result
+ puts 'Failed to build macOS LiveQuery Framework.'
+ exit(1)
+ end
+ end
+
+ desc 'Build watchOS LiveQuery framework.'
+ task :watchos do
+ task = XCTask::BuildFrameworkTask.new do |t|
+ t.directory = script_folder
+ t.build_directory = File.join(build_folder, 'watchOS')
+ t.framework_type = XCTask::FrameworkType::WATCHOS
+ t.framework_name = 'ParseLiveQuery_watchOS.framework'
+ t.workspace = 'Parse.xcworkspace'
+ t.scheme = 'ParseLiveQuery-watchOS'
+ t.configuration = 'Release'
+ end
+ result = task.execute
+ unless result
+ puts 'Failed to build watchOS LiveQuery Framework.'
+ exit(1)
+ end
+ end
+
+ desc 'Build tvOS LiveQuery framework.'
+ task :tvos do
+ task = XCTask::BuildFrameworkTask.new do |t|
+ t.directory = script_folder
+ t.build_directory = File.join(build_folder, 'tvOS')
+ t.framework_type = XCTask::FrameworkType::TVOS
+ t.framework_name = 'ParseLiveQuery_tvOS.framework'
+ t.workspace = 'Parse.xcworkspace'
+ t.scheme = 'ParseLiveQuery-tvOS'
+ t.configuration = 'Release'
+ end
+ result = task.execute
+ unless result
+ puts 'Failed to build tvOS LiveQuery Framework.'
+ exit(1)
+ end
+ end
+ end
+
namespace :facebook_utils do
desc 'Build iOS FacebookUtils framework.'
task :ios do
@@ -356,6 +434,23 @@ namespace :package do
make_package(release_folder,
[parseui_framework_path],
package_parseui_name)
+
+ Rake::Task['build:parse_live_query:ios'].invoke
+ ios_lq_framework_path = File.join(build_folder, 'iOS', 'ParseLiveQuery.framework')
+ make_package(release_folder, [ios_lq_framework_path], 'ParseLiveQuery-iOS.zip')
+
+ Rake::Task['build:parse_live_query:watchos'].invoke
+ watchos_lq_fb_utils_framework_path = File.join(build_folder, 'watchOS', 'ParseLiveQuery_watchOS.framework')
+ make_package(release_folder, [watchos_lq_fb_utils_framework_path], 'ParseLiveQuery-watchOS.zip')
+
+ Rake::Task['build:parse_live_query:tvos'].invoke
+ tvos_lq_framework_path = File.join(build_folder, 'tvOS', 'ParseLiveQuery_tvOS.framework')
+ make_package(release_folder, [tvos_lq_framework_path], 'ParseLiveQuery-tvOS.zip')
+
+ Rake::Task['build:parse_live_query:macos'].invoke
+ macos_lq_utils_framework_path = File.join(build_folder, 'macOS', 'ParseLiveQuery.framework')
+ make_package(release_folder, [macos_lq_utils_framework_path], 'ParseLiveQuery-OSX.zip')
+
end
desc 'Build and package all starter projects for the release'
@@ -610,6 +705,99 @@ namespace :test do
end
end
+ namespace :parse_live_query do
+ task :all do
+ Rake::Task['test:parse_live_query:ios'].invoke
+ Rake::Task['test:parse_live_query:tvos'].invoke
+ Rake::Task['test:parse_live_query:watchos'].invoke
+ Rake::Task['test:parse_live_query:osx'].invoke
+ end
+
+ task :ios do
+ task = XCTask::BuildTask.new do |t|
+ t.directory = script_folder
+ t.workspace = 'Parse.xcworkspace'
+
+ t.scheme = 'ParseLiveQuery-iOS'
+ t.sdk = 'iphonesimulator'
+ t.destinations = [ios_simulator]
+ t.configuration = 'Debug'
+
+ t.actions = [XCTask::BuildAction::CLEAN, XCTask::BuildAction::BUILD]
+ t.formatter = XCTask::BuildFormatter::XCPRETTY
+ end
+
+ result = task.execute
+ unless result
+ puts 'Failed to build ParseLiveQuery'
+ exit(1)
+ end
+ end
+
+ task :tvos do
+ task = XCTask::BuildTask.new do |t|
+ t.directory = script_folder
+ t.workspace = 'Parse.xcworkspace'
+
+ t.scheme = 'ParseLiveQuery-tvOS'
+ t.destinations = [tvos_simulator]
+ t.configuration = 'Debug'
+
+
+ t.actions = [XCTask::BuildAction::CLEAN, XCTask::BuildAction::BUILD]
+ t.formatter = XCTask::BuildFormatter::XCPRETTY
+ end
+
+ result = task.execute
+ unless result
+ puts 'Failed to build ParseLiveQuery-tvOS.'
+ exit(1)
+ end
+ end
+
+ task :watchos do
+ task = XCTask::BuildTask.new do |t|
+ t.directory = script_folder
+ t.workspace = 'Parse.xcworkspace'
+
+ t.scheme = 'ParseLiveQuery-watchOS'
+ t.destinations = [watchos_simulator]
+ t.configuration = 'Debug'
+
+
+ t.actions = [XCTask::BuildAction::CLEAN, XCTask::BuildAction::BUILD]
+ t.formatter = XCTask::BuildFormatter::XCPRETTY
+ end
+
+ result = task.execute
+ unless result
+ puts 'Failed to build ParseLiveQuery-watchOS.'
+ exit(1)
+ end
+ end
+
+ task :osx do
+ task = XCTask::BuildTask.new do |t|
+ t.directory = script_folder
+ t.workspace = 'Parse.xcworkspace'
+
+ t.scheme = 'ParseLiveQuery-OSX'
+ t.configuration = 'Debug'
+
+
+ t.actions = [XCTask::BuildAction::CLEAN, XCTask::BuildAction::BUILD]
+ t.formatter = XCTask::BuildFormatter::XCPRETTY
+ end
+
+ result = task.execute
+ unless result
+ puts 'Failed to build ParseLiveQuery-OSX.'
+ exit(1)
+ end
+ end
+ end
+
+
desc 'Run Starter Project Tests'
task :starters do |_|
results = []
diff --git a/Tests/Parse-SDK-iOS-OSXTests/Parse_SDK_iOS_OSXTests.swift b/Tests/Parse-SDK-iOS-OSXTests/Parse_SDK_iOS_OSXTests.swift
new file mode 100644
index 000000000..60488957a
--- /dev/null
+++ b/Tests/Parse-SDK-iOS-OSXTests/Parse_SDK_iOS_OSXTests.swift
@@ -0,0 +1,11 @@
+import XCTest
+@testable import Parse_SDK_iOS_OSX
+
+final class Parse_SDK_iOS_OSXTests: XCTestCase {
+ func testExample() throws {
+ // This is an example of a functional test case.
+ // Use XCTAssert and related functions to verify your tests produce the correct
+ // results.
+ XCTAssertEqual(Parse_SDK_iOS_OSX().text, "Hello, World!")
+ }
+}