diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..23d77f7
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,6 @@
+*.xccheckout
+*.xcuserstate
+*.xcscmblueprint
+**/xcuserdata/*
+.DS_Store
+
diff --git a/.swiftlint.yml b/.swiftlint.yml
new file mode 100644
index 0000000..37fbace
--- /dev/null
+++ b/.swiftlint.yml
@@ -0,0 +1,6 @@
+disabled_rules:
+ - line_length
+ - cyclomatic_complexity
+ - multiple_closures_with_trailing_closure
+ - function_body_length
+ - file_length
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..a6090c2
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2018 Nick Romano
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..7d00285
--- /dev/null
+++ b/README.md
@@ -0,0 +1,135 @@
+# ⌚️WatchSync
+
+[![CocoaPods](https://img.shields.io/cocoapods/v/WatchSync.svg)](http://cocoadocs.org/docsets/WatchSync/)
+[![Carthage Compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)
+
+WatchConnectivity wrapper with typed messages, better error handling, and simplified subscription APIs.
+
+## Example
+
+### Send messages
+
+Create a new message type that conforms to the `SyncableMessage` protocol. Uses `Codable` under the hood.
+
+```swift
+import WatchSync
+
+struct MyMessage: SyncableMessage {
+ var myString: String?
+ var myDate: Date?
+}
+```
+
+Send the message from anywhere in the iOS or watchOS app.
+
+```swift
+let myMessage = MyMessage(myString: "Test", myDate: Date())
+
+WatchSync.shared.sendMessage(myMessage) { result in
+}
+```
+
+You can also send a simple dictionary as well.
+
+```swift
+WatchSync.shared.sendMessage(["test": "message"]) { result in
+}
+```
+
+### Subscribe to new messages
+
+Listen for changes from the paired device (iOS or watchOS)
+
+```swift
+class ViewController: UIViewController {
+ var subscriptionToken: SubscriptionToken?
+
+ override func viewDidLoad() {
+ super.viewDidLoad()
+
+ subscriptionToken = WatchSync.shared.subscribeToMessages(ofType: MyMessage.self) { myMessage in
+ print(String(describing: myMessage.myString), String(describing: myMessage.myDate))
+ }
+ }
+}
+```
+
+### Update application context
+
+```swift
+WatchSync.shared.update(applicationContext: ["test": "context"]) { result in
+}
+```
+
+### Subscribe to application context updates
+
+```swift
+appDelegateObserver =
+
+class ViewController: UIViewController {
+ var subscriptionToken: SubscriptionToken?
+
+ override func viewDidLoad() {
+ super.viewDidLoad()
+
+ subscriptionToken = WatchSync.shared.subscribeToApplicationContext { applicationContext in
+ print(applicationContext)
+ }
+ }
+}
+```
+
+## How it works
+
+* If the paired device is reachable, `WatchSync` will try to send using an interactive message with `session.sendMessage()`.
+* If the paired device is unreachable, it will fall back to using `sendUserInfo()` instead.
+* All messages conforming to `SyncableMessage` will be JSON serialized to reduce the size of the payload. This is to reduce the likelyhood of running into a `WCErrorCodePayloadTooLarge` error.
+* For interactive messages it uses the `replyHandler` for delivery acknowledgments.
+
+## Installation & Setup
+
+In your `AppDelegate` (iOS) and `ExtensionDelegate` (watchOS) under `applicationDidFinishLaunching` you will need to activate the Watch Connectivity session.
+
+```swift
+WatchSync.shared.activateSession { error in
+ if let error = error {
+ print("Error activating session \(error.localizedDescription)")
+ return
+ }
+ print("Activated")
+}
+```
+
+## Error handling
+
+The `sendMessage` method returns a closure with a result to switch on that reduces the number of possible states and [errors](https://developer.apple.com/documentation/watchconnectivity/wcerror) your app can end up in.
+
+```swift
+WatchSync.shared.sendMessage(myMessage) { result in
+ switch result {
+ case .failure(let failure):
+ switch failure {
+ case .sessionNotActivated:
+ break
+ case .watchConnectivityNotAvailable:
+ break
+ case .unableToSerializeMessageAsJSON(let error):
+ break
+ case .watchAppNotPaired:
+ break
+ case .watchAppNotInstalled:
+ break
+ case .unhandledError(let error):
+ break
+ case .badPayloadError(let error):
+ break
+ case failedToDeliver(let error):
+ break
+ }
+ case .sent:
+ break
+ case .delivered:
+ break
+ }
+}
+```
diff --git a/Sources/Info-iOS.plist b/Sources/Info-iOS.plist
new file mode 100644
index 0000000..1007fd9
--- /dev/null
+++ b/Sources/Info-iOS.plist
@@ -0,0 +1,24 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ FMWK
+ CFBundleShortVersionString
+ 1.0
+ CFBundleVersion
+ $(CURRENT_PROJECT_VERSION)
+ NSPrincipalClass
+
+
+
diff --git a/Sources/Info-iOSTests.plist b/Sources/Info-iOSTests.plist
new file mode 100644
index 0000000..6c40a6c
--- /dev/null
+++ b/Sources/Info-iOSTests.plist
@@ -0,0 +1,22 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ BNDL
+ CFBundleShortVersionString
+ 1.0
+ CFBundleVersion
+ 1
+
+
diff --git a/Sources/Info-watchOS.plist b/Sources/Info-watchOS.plist
new file mode 100644
index 0000000..1007fd9
--- /dev/null
+++ b/Sources/Info-watchOS.plist
@@ -0,0 +1,24 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ FMWK
+ CFBundleShortVersionString
+ 1.0
+ CFBundleVersion
+ $(CURRENT_PROJECT_VERSION)
+ NSPrincipalClass
+
+
+
diff --git a/Sources/WatchSync.h b/Sources/WatchSync.h
new file mode 100644
index 0000000..fedd09c
--- /dev/null
+++ b/Sources/WatchSync.h
@@ -0,0 +1,18 @@
+//
+// WatchSync.h
+// WatchSync
+//
+// Created by Nicholas Romano on 3/15/18.
+//
+
+#import
+
+//! Project version number for WatchSync.
+FOUNDATION_EXPORT double WatchSyncVersionNumber;
+
+//! Project version string for WatchSync.
+FOUNDATION_EXPORT const unsigned char WatchSyncVersionString[];
+
+// In this header, you should import all the public headers of your framework using statements like #import
+
+
diff --git a/Sources/WatchSync/Extensions/Codable+JSON.swift b/Sources/WatchSync/Extensions/Codable+JSON.swift
new file mode 100644
index 0000000..e721571
--- /dev/null
+++ b/Sources/WatchSync/Extensions/Codable+JSON.swift
@@ -0,0 +1,24 @@
+//
+// Codable+JSON.swift
+// WatchConnectivityExample
+//
+// Created by Nicholas Romano on 3/15/18.
+// Copyright © 2018 Ten Minute Wait. All rights reserved.
+//
+
+import Foundation
+
+extension Encodable {
+ func toJSONString() throws -> String {
+ let encoder = JSONEncoder()
+ let data = try encoder.encode(self)
+ return String(data: data, encoding: .utf8)!
+ }
+}
+
+extension Decodable {
+ static func fromJSONString(_ string: String) throws -> Self {
+ let decoder = JSONDecoder()
+ return try decoder.decode(Self.self, from: string.data(using: .utf8)!)
+ }
+}
diff --git a/Sources/WatchSync/Results/FileTransferResult.swift b/Sources/WatchSync/Results/FileTransferResult.swift
new file mode 100644
index 0000000..5e385bd
--- /dev/null
+++ b/Sources/WatchSync/Results/FileTransferResult.swift
@@ -0,0 +1,29 @@
+//
+// FileTransferResult.swift
+// WatchSync iOS
+//
+// Created by Nick Romano on 3/26/18.
+//
+
+import Foundation
+
+public typealias FileTransferCallback = (FileTransferResult) -> Void
+
+public enum FileTransferFailure {
+ /// `WatchSync.shared.activateSession()` must finish before transfering files
+ case sessionNotActivated
+ case watchConnectivityNotAvailable
+
+ #if os(iOS)
+ case watchAppNotPaired
+ case watchAppNotInstalled
+ #endif
+
+ case failedToSend(Error)
+}
+
+public enum FileTransferResult {
+ case failure(FileTransferFailure)
+ case sent
+ case delivered
+}
diff --git a/Sources/WatchSync/Results/SendResult.swift b/Sources/WatchSync/Results/SendResult.swift
new file mode 100644
index 0000000..ddb91a0
--- /dev/null
+++ b/Sources/WatchSync/Results/SendResult.swift
@@ -0,0 +1,36 @@
+//
+// SendResult.swift
+// WatchSync
+//
+// Created by Nicholas Romano on 3/15/18.
+//
+
+import Foundation
+
+public typealias SendResultCallback = (SendResult) -> Void
+
+public enum SendResultFailure {
+ /// `WatchSync.shared.activateSession()` must finish before sending messages
+ case sessionNotActivated
+ case watchConnectivityNotAvailable
+ /// The `WatchSyncable` message could not be encoded as JSON
+ case unableToSerializeMessageAsJSON(Error)
+
+ #if os(iOS)
+ case watchAppNotPaired
+ case watchAppNotInstalled
+ #endif
+
+ /// Can be timeouts or general connectivity failures, could retry
+ case failedToDeliver(Error)
+
+ case unhandledError(Error)
+ case badPayloadError(Error)
+}
+
+/// Return codes for sending a message
+public enum SendResult {
+ case failure(SendResultFailure)
+ case sent
+ case delivered
+}
diff --git a/Sources/WatchSync/Results/UpdateContextResult.swift b/Sources/WatchSync/Results/UpdateContextResult.swift
new file mode 100644
index 0000000..e3b2de9
--- /dev/null
+++ b/Sources/WatchSync/Results/UpdateContextResult.swift
@@ -0,0 +1,29 @@
+//
+// UpdateContextResult.swift
+// WatchSync iOS
+//
+// Created by Nick Romano on 3/21/18.
+//
+
+import Foundation
+
+public typealias UpdateContextCallback = (UpdateContextResult) -> Void
+
+public enum UpdateContextFailure {
+ /// `WatchSync.shared.activateSession()` must finish before updating application context
+ case sessionNotActivated
+ case watchConnectivityNotAvailable
+
+ #if os(iOS)
+ case watchAppNotPaired
+ case watchAppNotInstalled
+ #endif
+
+ case unhandledError(Error)
+ case badPayloadError(Error)
+}
+
+public enum UpdateContextResult {
+ case failure(UpdateContextFailure)
+ case success
+}
diff --git a/Sources/WatchSync/Subscriptions/ApplicationContextSubscription.swift b/Sources/WatchSync/Subscriptions/ApplicationContextSubscription.swift
new file mode 100644
index 0000000..a84c75e
--- /dev/null
+++ b/Sources/WatchSync/Subscriptions/ApplicationContextSubscription.swift
@@ -0,0 +1,26 @@
+//
+// ApplicationContextSubscription.swift
+// WatchSync iOS
+//
+// Created by Nick Romano on 3/21/18.
+//
+
+import Foundation
+
+public typealias ApplicationContextListener = ([String: Any]) -> Void
+
+class ApplicationContextSubscription {
+ private var callback: ApplicationContextListener?
+ private var dispatchQueue: DispatchQueue
+
+ func callCallback(_ message: [String: Any]) {
+ dispatchQueue.async { [weak self] in
+ self?.callback?(message)
+ }
+ }
+
+ init(callback: ApplicationContextListener?, dispatchQueue: DispatchQueue) {
+ self.callback = callback
+ self.dispatchQueue = dispatchQueue
+ }
+}
diff --git a/Sources/WatchSync/Subscriptions/FileTransferSubscription.swift b/Sources/WatchSync/Subscriptions/FileTransferSubscription.swift
new file mode 100644
index 0000000..784f3a6
--- /dev/null
+++ b/Sources/WatchSync/Subscriptions/FileTransferSubscription.swift
@@ -0,0 +1,27 @@
+//
+// FileTransferSubscription.swift
+// WatchSync iOS
+//
+// Created by Nick Romano on 3/26/18.
+//
+
+import Foundation
+import WatchConnectivity
+
+public typealias FileTransferListener = (WCSessionFile) -> Void
+
+class FileTransferSubscription {
+ private var callback: FileTransferListener?
+ private var dispatchQueue: DispatchQueue
+
+ func callCallback(_ message: WCSessionFile) {
+ dispatchQueue.async { [weak self] in
+ self?.callback?(message)
+ }
+ }
+
+ init(callback: FileTransferListener?, dispatchQueue: DispatchQueue) {
+ self.callback = callback
+ self.dispatchQueue = dispatchQueue
+ }
+}
diff --git a/Sources/WatchSync/Subscriptions/MessageSubscription.swift b/Sources/WatchSync/Subscriptions/MessageSubscription.swift
new file mode 100644
index 0000000..543c7d9
--- /dev/null
+++ b/Sources/WatchSync/Subscriptions/MessageSubscription.swift
@@ -0,0 +1,26 @@
+//
+// MessageSubscription.swift
+// WatchSync iOS
+//
+// Created by Nicholas Romano on 3/15/18.
+//
+
+import Foundation
+
+public typealias MessageListener = ([String: Any]) -> Void
+
+class MessageSubscription {
+ private var callback: MessageListener?
+ private var dispatchQueue: DispatchQueue
+
+ func callCallback(_ message: [String: Any]) {
+ dispatchQueue.async { [weak self] in
+ self?.callback?(message)
+ }
+ }
+
+ init(callback: MessageListener?, dispatchQueue: DispatchQueue) {
+ self.callback = callback
+ self.dispatchQueue = dispatchQueue
+ }
+}
diff --git a/Sources/WatchSync/Subscriptions/SubscriptionToken.swift b/Sources/WatchSync/Subscriptions/SubscriptionToken.swift
new file mode 100644
index 0000000..21ee64f
--- /dev/null
+++ b/Sources/WatchSync/Subscriptions/SubscriptionToken.swift
@@ -0,0 +1,16 @@
+//
+// SubscriptionToken.swift
+// WatchSync iOS
+//
+// Created by Nicholas Romano on 3/15/18.
+//
+
+import Foundation
+
+/// Keep a strong reference to this when you want to continue receiving messages
+public class SubscriptionToken {
+ private var object: Any?
+ init(object: Any) {
+ self.object = object
+ }
+}
diff --git a/Sources/WatchSync/Subscriptions/SyncableMessageSubscription.swift b/Sources/WatchSync/Subscriptions/SyncableMessageSubscription.swift
new file mode 100644
index 0000000..ebf65d8
--- /dev/null
+++ b/Sources/WatchSync/Subscriptions/SyncableMessageSubscription.swift
@@ -0,0 +1,34 @@
+//
+// SyncableMessageSubscription.swift
+// WatchSync iOS
+//
+// Created by Nicholas Romano on 3/15/18.
+//
+
+import Foundation
+
+public typealias SyncableMessageListener = (T) -> Void
+
+protocol SubscriptionCallable: class {
+ func callCallback(_ message: SyncableMessage)
+}
+
+class SyncableMessageSunscription: SubscriptionCallable {
+ private var callback: SyncableMessageListener?
+ private var dispatchQueue: DispatchQueue
+
+ func callCallback(_ message: SyncableMessage) {
+ guard let message = message as? T else {
+ // Drop message of other types
+ return
+ }
+ dispatchQueue.async { [weak self] in
+ self?.callback?(message)
+ }
+ }
+
+ init(callback: SyncableMessageListener?, dispatchQueue: DispatchQueue) {
+ self.callback = callback
+ self.dispatchQueue = dispatchQueue
+ }
+}
diff --git a/Sources/WatchSync/SyncableMessage.swift b/Sources/WatchSync/SyncableMessage.swift
new file mode 100644
index 0000000..f4b53cc
--- /dev/null
+++ b/Sources/WatchSync/SyncableMessage.swift
@@ -0,0 +1,28 @@
+//
+// WatchMessages.swift
+// WatchConnectivityExample
+//
+// Created by Nicholas Romano on 3/15/18.
+// Copyright © 2018 Ten Minute Wait. All rights reserved.
+//
+
+import Foundation
+
+/**
+ Protocol for creating typed Watch/Phone messages
+
+ To reduce the size of each message in transit, the object is JSON encoded.
+ This is to help prevent running into the `WCErrorCodePayloadTooLarge` error.
+
+ Unless your message schema will never change, I recommend making all fields
+ optional. Otherwise Decodable will throw this error when new fields are
+ added: `"No value associated with key"` from old message data.
+ */
+public protocol SyncableMessage: Codable {
+}
+
+extension SyncableMessage {
+ static var messageKey: String {
+ return String(describing: self)
+ }
+}
diff --git a/Sources/WatchSync/WatchSync.swift b/Sources/WatchSync/WatchSync.swift
new file mode 100644
index 0000000..58529a9
--- /dev/null
+++ b/Sources/WatchSync/WatchSync.swift
@@ -0,0 +1,484 @@
+//
+// WatchSync.swift
+// WatchConnectivityExample
+//
+// Created by Nicholas Romano on 3/15/18.
+// Copyright © 2018 Ten Minute Wait. All rights reserved.
+//
+
+import Foundation
+import WatchConnectivity
+
+public struct CouldNotActivateError: Error {
+}
+
+/// Singleton to manage phone and watch communication
+open class WatchSync: NSObject {
+ public static let shared = WatchSync()
+
+ public let session: WCSession? = WCSession.isSupported() ? WCSession.default : nil
+
+ private var activationCallback: ((Error?) -> Void)?
+
+ /// Loop through these when processing an incoming message
+ ///
+ /// I would prefer to use a Set here but not sure not sure how
+ /// to implement the `Hashable` protocol on metatype `Type`
+ private var registeredMessageTypes: [SyncableMessage.Type] = []
+
+ /// Weak references to subscriptions for `SyncableMessage` messages
+ private var syncableMessageSubscriptions = NSPointerArray.weakObjects()
+
+ /// Weak references to subscriptions for `[String: Any]` messages
+ private var messageSubscriptions = NSPointerArray.weakObjects()
+
+ /// Weak references to subscriptions for applicationContext
+ private var applicationContextSubscriptions = NSPointerArray.weakObjects()
+
+ /// Weak references to subscriptions for file transfers
+ private var fileTransferSubscriptions = NSPointerArray.weakObjects()
+
+ /// Store callbacks until we receive a response from didFinish userInfoTransfer
+ private var userInfoCallbacks: [WCSessionUserInfoTransfer: SendResultCallback?] = [:]
+
+ /// Store callbacks until we receive a response from didFinish fileTransfer
+ private var fileTransferCallbacks: [WCSessionFileTransfer: FileTransferCallback?] = [:]
+
+ /// Called when launching the app for the first time to setup Watch Connectivity
+ ///
+ /// - Parameter activationCallback: Closure called when activation has finished.
+ public func activateSession(activationCallback: @escaping (Error?) -> Void) {
+ self.activationCallback = activationCallback
+ session?.delegate = self
+ session?.activate()
+ }
+
+ /// Observe messages of Type (Recommended)
+ ///
+ /// - Parameters:
+ /// - ofType: Message that conforms to `WatchSyncable` protocol
+ /// - queue: Queue to call the callback on. Defaults to `.main`
+ /// - callback: Closure to be called when receiving a message
+ /// - Returns: `SubscriptionToken` store this for as long as you would like to receive messages
+ public func subscribeToMessages(ofType: T.Type, on queue: DispatchQueue = DispatchQueue.main, callback: @escaping SyncableMessageListener) -> SubscriptionToken {
+ let subscription = SyncableMessageSunscription(callback: callback, dispatchQueue: queue)
+
+ let pointer = Unmanaged.passUnretained(subscription).toOpaque()
+ syncableMessageSubscriptions.addPointer(pointer)
+
+ if !registeredMessageTypes.contains(where: { watchSyncableType -> Bool in
+ if watchSyncableType == T.self {
+ return true
+ }
+ return false
+ }) {
+ registeredMessageTypes.append(ofType)
+ }
+
+ return SubscriptionToken(object: subscription)
+ }
+
+ /// Observe messages for all data that is not a `WatchSyncable` message
+ ///
+ /// - Parameters:
+ /// - queue: Queue to call the callback on. Defaults to `.main`
+ /// - callback: Closure to be called when receiving a message
+ /// - Returns: `SubscriptionToken` store this for as long as you would like to receive messages
+ public func subscribeToMessages(on queue: DispatchQueue = DispatchQueue.main, callback: @escaping MessageListener) -> SubscriptionToken {
+ let rawSubscription = MessageSubscription(callback: callback, dispatchQueue: queue)
+
+ let pointer = Unmanaged.passUnretained(rawSubscription).toOpaque()
+ messageSubscriptions.addPointer(pointer)
+
+ return SubscriptionToken(object: rawSubscription)
+ }
+
+ /// Observer application context, also called immediately with the most recently received context
+ ///
+ /// - Parameters:
+ /// - queue: Queue to call the callback on. Defaults to `.main`
+ /// - callback: Closure to be called when receiving an application context
+ /// - Returns: `SubscriptionToken` store this for as long as you would like to application contexts
+ public func subscribeToApplicationContext(on queue: DispatchQueue = DispatchQueue.main, callback: @escaping ApplicationContextListener) -> SubscriptionToken {
+ let rawSubscription = ApplicationContextSubscription(callback: callback, dispatchQueue: queue)
+
+ let pointer = Unmanaged.passUnretained(rawSubscription).toOpaque()
+ applicationContextSubscriptions.addPointer(pointer)
+
+ // Call immediately on the most recently received app context
+ if let session = session {
+ callback(session.receivedApplicationContext)
+ }
+
+ return SubscriptionToken(object: rawSubscription)
+ }
+
+ public func subscribeToFileTransfers(on queue: DispatchQueue = DispatchQueue.main, callback: @escaping FileTransferListener) -> SubscriptionToken {
+ let rawSubscription = FileTransferSubscription(callback: callback, dispatchQueue: queue)
+
+ let pointer = Unmanaged.passUnretained(rawSubscription).toOpaque()
+ fileTransferSubscriptions.addPointer(pointer)
+
+ return SubscriptionToken(object: rawSubscription)
+ }
+
+ /// Send a `WatchSyncable` message to the paired device (Recommended)
+ ///
+ /// The data is JSON serialized to reduce the size of the payload.
+ /// If the device is reachable it will send it in realtime.
+ /// If the device is not reachable, it will store it in a queue to be received later.
+ ///
+ /// ```
+ /// WatchSync.shared.sendMessage(myMessage) { result in
+ /// // switch on result
+ /// }
+ /// ```
+ ///
+ /// - Parameters:
+ /// - message: object that conforms to `WatchSyncable`
+ /// - completion: Closure that provides a `SendResult` describing the status of the message
+ public func sendMessage(_ message: SyncableMessage, completion: SendResultCallback?) {
+ // Package message for sending
+ let messageJSON: String
+ do {
+ messageJSON = try message.toJSONString()
+ } catch let error {
+ completion?(.failure(.unableToSerializeMessageAsJSON(error)))
+ return
+ }
+ let data: [String: String] = [
+ type(of: message).messageKey: messageJSON
+ ]
+ sendMessage(data, completion: completion)
+ }
+
+ private func transferUserInfo(_ message: [String: Any], in session: WCSession, completion: SendResultCallback?) {
+ let transfer = session.transferUserInfo(message)
+ userInfoCallbacks[transfer] = completion
+ completion?(.sent)
+ }
+
+ /// Send a dictionary message to the paired device
+ ///
+ /// If the device is reachable it will send it in realtime.
+ /// If the device is not reachable, it will store it in a queue to be received later.
+ ///
+ /// ```
+ /// WatchSync.shared.sendMessage(["test": "hello"]) { result in
+ /// // switch on result
+ /// }
+ /// ```
+ ///
+ /// - Parameters:
+ /// - message: object that conforms to `WatchSyncable`
+ /// - completion: Closure that provides a `SendResult` describing the status of the message
+ public func sendMessage(_ message: [String: Any], completion: SendResultCallback?) {
+ guard let session = session else {
+ logMessage("Watch connectivity not available")
+ completion?(.failure(.watchConnectivityNotAvailable))
+ return
+ }
+ guard session.activationState == .activated else {
+ logMessage("Session not activated")
+ completion?(.failure(.sessionNotActivated))
+ return
+ }
+
+ #if os(iOS)
+ guard session.isPaired else {
+ logMessage("Watch app not paired")
+ completion?(.failure(.watchAppNotPaired))
+ return
+ }
+ guard session.isWatchAppInstalled else {
+ logMessage("Watch app not installed")
+ completion?(.failure(.watchAppNotInstalled))
+ return
+ }
+ #endif
+
+ guard session.isReachable else {
+ logMessage("Watch app not reachable, transfer user info")
+
+ transferUserInfo(message, in: session, completion: completion)
+ return
+ }
+
+ logMessage("Reachable, trying to send message")
+ session.sendMessage(message, replyHandler: { _ in
+ self.logMessage("Delivered realtime message successfully")
+ completion?(.delivered)
+ }) { error in
+ guard let watchError = error as? WCError else {
+ completion?(.failure(.unhandledError(error)))
+ return
+ }
+
+ switch watchError.code {
+ case .sessionNotSupported, .sessionMissingDelegate, .sessionNotActivated,
+ .sessionInactive, .deviceNotPaired, .watchAppNotInstalled, .notReachable:
+ // Shouldn't reach this state since we handle these above
+ completion?(.failure(.unhandledError(watchError)))
+
+ case .fileAccessDenied, .insufficientSpace:
+ // Only relevant for file transfers
+ completion?(.failure(.unhandledError(watchError)))
+
+ case .genericError:
+ // Not sure what can throw these
+ completion?(.failure(.unhandledError(watchError)))
+
+ case .invalidParameter, .payloadTooLarge, .payloadUnsupportedTypes:
+ // Should be handled before sending again.
+ completion?(.failure(.badPayloadError(watchError)))
+
+ case .deliveryFailed, .transferTimedOut, .messageReplyTimedOut, .messageReplyFailed:
+ // Retry sending in the background
+ self.logMessage("Error sending message: \(error.localizedDescription), transfering user info")
+ self.transferUserInfo(message, in: session, completion: completion)
+ }
+ }
+ }
+
+ /// Update the application context on the paired device.
+ ///
+ /// The paired device doesn't need to be reachable but the session must be activated
+ ///
+ /// - Parameters:
+ /// - applicationContext: Dictionary for the paired device
+ /// - completion: Closure that provides a `UpdateContextResult` describing the status of the update
+ public func update(applicationContext: [String: Any], completion: UpdateContextCallback?) {
+ guard let session = session else {
+ logMessage("Watch connectivity not available")
+ completion?(.failure(.watchConnectivityNotAvailable))
+ return
+ }
+ guard session.activationState == .activated else {
+ logMessage("Session not activated")
+ completion?(.failure(.sessionNotActivated))
+ return
+ }
+
+ #if os(iOS)
+ guard session.isPaired else {
+ logMessage("Watch app not paired")
+ completion?(.failure(.watchAppNotPaired))
+ return
+ }
+ guard session.isWatchAppInstalled else {
+ logMessage("Watch app not installed")
+ completion?(.failure(.watchAppNotInstalled))
+ return
+ }
+ #endif
+
+ do {
+ try session.updateApplicationContext(applicationContext)
+ } catch let error {
+ guard let watchError = error as? WCError else {
+ completion?(.failure(.unhandledError(error)))
+ return
+ }
+
+ switch watchError.code {
+ case .sessionNotSupported, .sessionMissingDelegate, .sessionNotActivated,
+ .sessionInactive, .deviceNotPaired, .watchAppNotInstalled, .notReachable:
+ // Shouldn't reach this state since we handle these above
+ completion?(.failure(.unhandledError(watchError)))
+
+ case .fileAccessDenied, .insufficientSpace:
+ // Only relevant for file transfers
+ completion?(.failure(.unhandledError(watchError)))
+
+ case .deliveryFailed, .transferTimedOut, .messageReplyTimedOut, .messageReplyFailed:
+ // Only relevant for messages and transfers
+ completion?(.failure(.unhandledError(watchError)))
+
+ case .genericError:
+ // Not sure what can throw these
+ completion?(.failure(.unhandledError(watchError)))
+
+ case .invalidParameter, .payloadTooLarge, .payloadUnsupportedTypes:
+ // Should be handled before sending again.
+ completion?(.failure(.badPayloadError(watchError)))
+ }
+ }
+ }
+
+ public func transferFile(file: URL, metadata: [String: Any]?, completion: FileTransferCallback?) {
+ guard let session = session else {
+ logMessage("Watch connectivity not available")
+ completion?(.failure(.watchConnectivityNotAvailable))
+ return
+ }
+ guard session.activationState == .activated else {
+ logMessage("Session not activated")
+ completion?(.failure(.sessionNotActivated))
+ return
+ }
+ let transfer = session.transferFile(file, metadata: metadata)
+ fileTransferCallbacks[transfer] = completion
+ completion?(.sent)
+ }
+
+ /// Entrypoint for all received messages from the paired device.
+ ///
+ /// - Parameter message: Paired device message
+ private func receivedMessage(_ message: [String: Any]) {
+ var foundMessage = false
+ // Call all observers based on message types
+ for messageType in registeredMessageTypes {
+ guard let messageJSONString = message[messageType.messageKey] as? String else {
+ continue
+ }
+
+ let watchSyncableMessage: SyncableMessage
+ do {
+ watchSyncableMessage = try messageType.fromJSONString(messageJSONString)
+ foundMessage = true
+ } catch let error {
+ logMessage("Unable to parse JSON \(error.localizedDescription)")
+ continue
+ }
+
+ // Cleanup the subscriptions from time to time
+ syncableMessageSubscriptions.compact()
+
+ syncableMessageSubscriptions.allObjects.forEach { subscription in
+ guard let subscription = subscription as? SubscriptionCallable else {
+ return
+ }
+ subscription.callCallback(watchSyncableMessage)
+ }
+ }
+ // If there are no message types found, just give the raw payload back
+ if !foundMessage {
+ messageSubscriptions.compact()
+ messageSubscriptions.allObjects.forEach { subscription in
+ guard let subscription = subscription as? MessageSubscription else {
+ return
+ }
+ subscription.callCallback(message)
+ }
+ }
+ }
+
+ /// Override this function to log messages using your own tooling
+ open func logMessage(_ message: String) {
+ print(message)
+ }
+}
+
+extension WatchSync: WCSessionDelegate {
+ // MARK: Watch Activation, multiple devices can be paired and swapped with the phone
+ public func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {
+ logMessage("Session completed activation: \(activationState)")
+ var error = error
+ if error == nil && activationState != .activated {
+ // We should hopefully never end up in this state, if activationState
+ // isn't activated there should be an error with reason from Apple
+ error = CouldNotActivateError()
+ }
+ activationCallback?(error)
+ }
+
+ #if os(iOS)
+ public func sessionDidBecomeInactive(_ session: WCSession) {
+ logMessage("Session became inactive")
+ }
+
+ // Apple recommends trying to reactivate if the session has switched between devices
+ public func sessionDidDeactivate(_ session: WCSession) {
+ logMessage("Session deactivated, trying to setup for new device")
+ session.activate()
+ }
+ #endif
+
+ // MARK: Reachability
+ public func sessionReachabilityDidChange(_ session: WCSession) {
+ logMessage("Reachability changed: \(session.isReachable)")
+ }
+
+ // MARK: Realtime messaging (must be reachable)
+ public func session(_ session: WCSession, didReceiveMessage message: [String: Any]) {
+ // All session delegate methods are called on a background thread.
+ receivedMessage(message)
+ }
+
+ public func session(_ session: WCSession, didReceiveMessage message: [String: Any], replyHandler: @escaping ([String: Any]) -> Void) {
+ // All session delegate methods are called on a background thread.
+ receivedMessage(message)
+ // Reply handler is always called so the other device get's a confirmation the message was delivered in realtime
+ replyHandler([:])
+ }
+
+ // MARK: FIFO messaging (queue's with delivery guarantees)
+ public func session(_ session: WCSession, didReceiveUserInfo userInfo: [String: Any] = [:]) {
+ // All session delegate methods are called on a background thread.
+ receivedMessage(userInfo)
+ }
+
+ public func session(_ session: WCSession, didFinish userInfoTransfer: WCSessionUserInfoTransfer, error: Error?) {
+ if let completion = userInfoCallbacks[userInfoTransfer] {
+ if let error = error {
+ guard let watchError = error as? WCError else {
+ completion?(.failure(.unhandledError(error)))
+ return
+ }
+
+ switch watchError.code {
+ case .sessionNotSupported, .sessionMissingDelegate, .sessionNotActivated,
+ .sessionInactive, .deviceNotPaired, .watchAppNotInstalled, .notReachable,
+ .messageReplyTimedOut, .messageReplyFailed, .fileAccessDenied, .insufficientSpace:
+ // Not applicable for transfers
+ completion?(.failure(.unhandledError(watchError)))
+
+ case .deliveryFailed, .transferTimedOut:
+ completion?(.failure(.failedToDeliver(watchError)))
+
+ case .genericError:
+ // Not sure what can throw these
+ completion?(.failure(.unhandledError(watchError)))
+
+ case .invalidParameter, .payloadTooLarge, .payloadUnsupportedTypes:
+ // Should be handled before sending again.
+ completion?(.failure(.badPayloadError(watchError)))
+ }
+ } else {
+ completion?(.delivered)
+ }
+ }
+ }
+
+ /// Entrypoint for application contexts, use `subscribeToApplicationContext` to receive this data
+ public func session(_ session: WCSession, didReceiveApplicationContext applicationContext: [String: Any]) {
+ applicationContextSubscriptions.compact()
+ applicationContextSubscriptions.allObjects.forEach { subscription in
+ guard let subscription = subscription as? ApplicationContextSubscription else {
+ return
+ }
+ subscription.callCallback(applicationContext)
+ }
+ }
+
+ /// Entrypoint for received file transfers, use `subscribeToFileTransfer` to receive these
+ public func session(_ session: WCSession, didReceive file: WCSessionFile) {
+ fileTransferSubscriptions.compact()
+ fileTransferSubscriptions.allObjects.forEach { subscription in
+ guard let subscription = subscription as? FileTransferSubscription else {
+ return
+ }
+ subscription.callCallback(file)
+ }
+ }
+
+ public func session(_ session: WCSession, didFinish fileTransfer: WCSessionFileTransfer, error: Error?) {
+ if let callback = fileTransferCallbacks[fileTransfer] {
+ if let error = error {
+ callback?(.failure(.failedToSend(error)))
+ } else {
+ callback?(.delivered)
+ }
+ }
+ }
+}
diff --git a/WatchSync Example/WatchSync Example WatchKit App/Assets.xcassets/AppIcon.appiconset/Contents.json b/WatchSync Example/WatchSync Example WatchKit App/Assets.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 0000000..dd221ba
--- /dev/null
+++ b/WatchSync Example/WatchSync Example WatchKit App/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,55 @@
+{
+ "images" : [
+ {
+ "size" : "24x24",
+ "idiom" : "watch",
+ "scale" : "2x",
+ "role" : "notificationCenter",
+ "subtype" : "38mm"
+ },
+ {
+ "size" : "27.5x27.5",
+ "idiom" : "watch",
+ "scale" : "2x",
+ "role" : "notificationCenter",
+ "subtype" : "42mm"
+ },
+ {
+ "size" : "29x29",
+ "idiom" : "watch",
+ "role" : "companionSettings",
+ "scale" : "2x"
+ },
+ {
+ "size" : "29x29",
+ "idiom" : "watch",
+ "role" : "companionSettings",
+ "scale" : "3x"
+ },
+ {
+ "size" : "40x40",
+ "idiom" : "watch",
+ "scale" : "2x",
+ "role" : "appLauncher",
+ "subtype" : "38mm"
+ },
+ {
+ "size" : "86x86",
+ "idiom" : "watch",
+ "scale" : "2x",
+ "role" : "quickLook",
+ "subtype" : "38mm"
+ },
+ {
+ "size" : "98x98",
+ "idiom" : "watch",
+ "scale" : "2x",
+ "role" : "quickLook",
+ "subtype" : "42mm"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
diff --git a/WatchSync Example/WatchSync Example WatchKit App/Base.lproj/Interface.storyboard b/WatchSync Example/WatchSync Example WatchKit App/Base.lproj/Interface.storyboard
new file mode 100644
index 0000000..48ca0b6
--- /dev/null
+++ b/WatchSync Example/WatchSync Example WatchKit App/Base.lproj/Interface.storyboard
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/WatchSync Example/WatchSync Example WatchKit App/Info.plist b/WatchSync Example/WatchSync Example WatchKit App/Info.plist
new file mode 100644
index 0000000..e379722
--- /dev/null
+++ b/WatchSync Example/WatchSync Example WatchKit App/Info.plist
@@ -0,0 +1,33 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleDisplayName
+ WatchSync Example WatchKit App
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ 1.0
+ CFBundleVersion
+ 1
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationPortraitUpsideDown
+
+ WKCompanionAppBundleIdentifier
+ com.tenminutewait.WatchSync-Example
+ WKWatchKitApp
+
+
+
diff --git a/WatchSync Example/WatchSync Example WatchKit Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Contents.json b/WatchSync Example/WatchSync Example WatchKit Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Contents.json
new file mode 100644
index 0000000..9be9adb
--- /dev/null
+++ b/WatchSync Example/WatchSync Example WatchKit Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Contents.json
@@ -0,0 +1,18 @@
+{
+ "images" : [
+ {
+ "idiom" : "watch",
+ "screenWidth" : "{130,145}",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "watch",
+ "screenWidth" : "{146,165}",
+ "scale" : "2x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
\ No newline at end of file
diff --git a/WatchSync Example/WatchSync Example WatchKit Extension/Assets.xcassets/Complication.complicationset/Contents.json b/WatchSync Example/WatchSync Example WatchKit Extension/Assets.xcassets/Complication.complicationset/Contents.json
new file mode 100644
index 0000000..2eca9a1
--- /dev/null
+++ b/WatchSync Example/WatchSync Example WatchKit Extension/Assets.xcassets/Complication.complicationset/Contents.json
@@ -0,0 +1,28 @@
+{
+ "assets" : [
+ {
+ "idiom" : "watch",
+ "filename" : "Circular.imageset",
+ "role" : "circular"
+ },
+ {
+ "idiom" : "watch",
+ "filename" : "Extra Large.imageset",
+ "role" : "extra-large"
+ },
+ {
+ "idiom" : "watch",
+ "filename" : "Modular.imageset",
+ "role" : "modular"
+ },
+ {
+ "idiom" : "watch",
+ "filename" : "Utilitarian.imageset",
+ "role" : "utilitarian"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
diff --git a/WatchSync Example/WatchSync Example WatchKit Extension/Assets.xcassets/Complication.complicationset/Extra Large.imageset/Contents.json b/WatchSync Example/WatchSync Example WatchKit Extension/Assets.xcassets/Complication.complicationset/Extra Large.imageset/Contents.json
new file mode 100644
index 0000000..9be9adb
--- /dev/null
+++ b/WatchSync Example/WatchSync Example WatchKit Extension/Assets.xcassets/Complication.complicationset/Extra Large.imageset/Contents.json
@@ -0,0 +1,18 @@
+{
+ "images" : [
+ {
+ "idiom" : "watch",
+ "screenWidth" : "{130,145}",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "watch",
+ "screenWidth" : "{146,165}",
+ "scale" : "2x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
\ No newline at end of file
diff --git a/WatchSync Example/WatchSync Example WatchKit Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Contents.json b/WatchSync Example/WatchSync Example WatchKit Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Contents.json
new file mode 100644
index 0000000..9be9adb
--- /dev/null
+++ b/WatchSync Example/WatchSync Example WatchKit Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Contents.json
@@ -0,0 +1,18 @@
+{
+ "images" : [
+ {
+ "idiom" : "watch",
+ "screenWidth" : "{130,145}",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "watch",
+ "screenWidth" : "{146,165}",
+ "scale" : "2x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
\ No newline at end of file
diff --git a/WatchSync Example/WatchSync Example WatchKit Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Contents.json b/WatchSync Example/WatchSync Example WatchKit Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Contents.json
new file mode 100644
index 0000000..9be9adb
--- /dev/null
+++ b/WatchSync Example/WatchSync Example WatchKit Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Contents.json
@@ -0,0 +1,18 @@
+{
+ "images" : [
+ {
+ "idiom" : "watch",
+ "screenWidth" : "{130,145}",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "watch",
+ "screenWidth" : "{146,165}",
+ "scale" : "2x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
\ No newline at end of file
diff --git a/WatchSync Example/WatchSync Example WatchKit Extension/ExtensionDelegate.swift b/WatchSync Example/WatchSync Example WatchKit Extension/ExtensionDelegate.swift
new file mode 100644
index 0000000..9dbb8c1
--- /dev/null
+++ b/WatchSync Example/WatchSync Example WatchKit Extension/ExtensionDelegate.swift
@@ -0,0 +1,30 @@
+//
+// ExtensionDelegate.swift
+// WatchSync Example WatchKit Extension
+//
+// Created by Nicholas Romano on 3/15/18.
+// Copyright © 2018 Ten Minute Wait. All rights reserved.
+//
+
+import WatchKit
+import WatchSync
+
+class ExtensionDelegate: NSObject, WKExtensionDelegate {
+
+ var subscriptionToken: SubscriptionToken?
+
+ func applicationDidFinishLaunching() {
+
+ WatchSync.shared.activateSession { error in
+ if let error = error {
+ print("Error activating session \(error.localizedDescription)")
+ return
+ }
+ print("Activated")
+ }
+
+ subscriptionToken = WatchSync.shared.subscribeToMessages(ofType: MyMessage.self) { myMessage in
+ print(myMessage)
+ }
+ }
+}
diff --git a/WatchSync Example/WatchSync Example WatchKit Extension/Info.plist b/WatchSync Example/WatchSync Example WatchKit Extension/Info.plist
new file mode 100644
index 0000000..bdbc373
--- /dev/null
+++ b/WatchSync Example/WatchSync Example WatchKit Extension/Info.plist
@@ -0,0 +1,36 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleDisplayName
+ WatchSync Example WatchKit Extension
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ XPC!
+ CFBundleShortVersionString
+ 1.0
+ CFBundleVersion
+ 1
+ NSExtension
+
+ NSExtensionAttributes
+
+ WKAppBundleIdentifier
+ com.tenminutewait.WatchSync-Example.watchkitapp
+
+ NSExtensionPointIdentifier
+ com.apple.watchkit
+
+ WKExtensionDelegateClassName
+ $(PRODUCT_MODULE_NAME).ExtensionDelegate
+
+
diff --git a/WatchSync Example/WatchSync Example WatchKit Extension/InterfaceController.swift b/WatchSync Example/WatchSync Example WatchKit Extension/InterfaceController.swift
new file mode 100644
index 0000000..3d85dc9
--- /dev/null
+++ b/WatchSync Example/WatchSync Example WatchKit Extension/InterfaceController.swift
@@ -0,0 +1,45 @@
+//
+// InterfaceController.swift
+// WatchSync Example WatchKit Extension
+//
+// Created by Nicholas Romano on 3/15/18.
+// Copyright © 2018 Ten Minute Wait. All rights reserved.
+//
+
+import WatchKit
+import Foundation
+
+import WatchSync
+
+class InterfaceController: WKInterfaceController {
+
+ var subscriptionToken: SubscriptionToken?
+
+ @IBOutlet var receivedLabel: WKInterfaceLabel!
+
+ override func awake(withContext context: Any?) {
+ super.awake(withContext: context)
+
+ receivedLabel.setHidden(true)
+
+ subscriptionToken = WatchSync.shared.subscribeToMessages(ofType: MyMessage.self) { [weak self] myMessage in
+ self?.receivedLabel.setHidden(false)
+
+ DispatchQueue.main.asyncAfter(deadline: .now() + 5.0, execute: {
+ self?.receivedLabel.setHidden(true)
+ })
+
+ print(String(describing: myMessage.myString), String(describing: myMessage.myDate))
+ }
+ }
+
+ override func willActivate() {
+ // This method is called when watch view controller is about to be visible to user
+ super.willActivate()
+ }
+
+ override func didDeactivate() {
+ // This method is called when watch view controller is no longer visible
+ super.didDeactivate()
+ }
+}
diff --git a/WatchSync Example/WatchSync Example WatchKit Extension/NotificationController.swift b/WatchSync Example/WatchSync Example WatchKit Extension/NotificationController.swift
new file mode 100644
index 0000000..0582b75
--- /dev/null
+++ b/WatchSync Example/WatchSync Example WatchKit Extension/NotificationController.swift
@@ -0,0 +1,35 @@
+//
+// NotificationController.swift
+// WatchSync Example WatchKit Extension
+//
+// Created by Nicholas Romano on 3/15/18.
+// Copyright © 2018 Ten Minute Wait. All rights reserved.
+//
+
+import WatchKit
+import Foundation
+import UserNotifications
+
+class NotificationController: WKUserNotificationInterfaceController {
+
+ override func willActivate() {
+ // This method is called when watch view controller is about to be visible to user
+ super.willActivate()
+ }
+
+ override func didDeactivate() {
+ // This method is called when watch view controller is no longer visible
+ super.didDeactivate()
+ }
+
+ /*
+ override func didReceive(_ notification: UNNotification, withCompletion completionHandler: @escaping (WKUserNotificationInterfaceType) -> Swift.Void) {
+ // This method is called when a notification needs to be presented.
+ // Implement it if you use a dynamic notification interface.
+ // Populate your dynamic notification interface as quickly as possible.
+ //
+ // After populating your dynamic notification interface call the completion block.
+ completionHandler(.custom)
+ }
+ */
+}
diff --git a/WatchSync Example/WatchSync Example WatchKit Extension/PushNotificationPayload.apns b/WatchSync Example/WatchSync Example WatchKit Extension/PushNotificationPayload.apns
new file mode 100644
index 0000000..c81dadf
--- /dev/null
+++ b/WatchSync Example/WatchSync Example WatchKit Extension/PushNotificationPayload.apns
@@ -0,0 +1,19 @@
+{
+ "aps": {
+ "alert": {
+ "body": "Test message",
+ "title": "Optional title"
+ },
+ "category": "myCategory",
+ "thread-id":"5280"
+ },
+
+ "WatchKit Simulator Actions": [
+ {
+ "title": "First Button",
+ "identifier": "firstButtonAction"
+ }
+ ],
+
+ "customKey": "Use this file to define a testing payload for your notifications. The aps dictionary specifies the category, alert text and title. The WatchKit Simulator Actions array can provide info for one or more action buttons in addition to the standard Dismiss button. Any other top level keys are custom payload. If you have multiple such JSON files in your project, you'll be able to select them when choosing to debug the notification interface of your Watch App."
+}
diff --git a/WatchSync Example/WatchSync Example.xcodeproj/project.pbxproj b/WatchSync Example/WatchSync Example.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..f28b600
--- /dev/null
+++ b/WatchSync Example/WatchSync Example.xcodeproj/project.pbxproj
@@ -0,0 +1,788 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 48;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ CDE701FC205B6F0000C40127 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDE701FB205B6F0000C40127 /* AppDelegate.swift */; };
+ CDE701FE205B6F0000C40127 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDE701FD205B6F0000C40127 /* ViewController.swift */; };
+ CDE70201205B6F0000C40127 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = CDE701FF205B6F0000C40127 /* Main.storyboard */; };
+ CDE70203205B6F0000C40127 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CDE70202205B6F0000C40127 /* Assets.xcassets */; };
+ CDE70206205B6F0000C40127 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = CDE70204205B6F0000C40127 /* LaunchScreen.storyboard */; };
+ CDE70211205B6F0100C40127 /* WatchSync_ExampleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDE70210205B6F0100C40127 /* WatchSync_ExampleTests.swift */; };
+ CDE70216205B6F0100C40127 /* WatchSync Example WatchKit App.app in Embed Watch Content */ = {isa = PBXBuildFile; fileRef = CDE70215205B6F0100C40127 /* WatchSync Example WatchKit App.app */; };
+ CDE7021C205B6F0100C40127 /* Interface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = CDE7021A205B6F0100C40127 /* Interface.storyboard */; };
+ CDE7021E205B6F0100C40127 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CDE7021D205B6F0100C40127 /* Assets.xcassets */; };
+ CDE70225205B6F0100C40127 /* WatchSync Example WatchKit Extension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = CDE70224205B6F0100C40127 /* WatchSync Example WatchKit Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
+ CDE7022A205B6F0100C40127 /* InterfaceController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDE70229205B6F0100C40127 /* InterfaceController.swift */; };
+ CDE7022C205B6F0100C40127 /* ExtensionDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDE7022B205B6F0100C40127 /* ExtensionDelegate.swift */; };
+ CDE7022E205B6F0100C40127 /* NotificationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDE7022D205B6F0100C40127 /* NotificationController.swift */; };
+ CDE70230205B6F0100C40127 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CDE7022F205B6F0100C40127 /* Assets.xcassets */; };
+ CDE70247205B6F3C00C40127 /* WatchSync.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CDE70246205B6F3C00C40127 /* WatchSync.framework */; };
+ CDE70248205B6F3C00C40127 /* WatchSync.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = CDE70246205B6F3C00C40127 /* WatchSync.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
+ CDE7024C205B6F8200C40127 /* WatchSync.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CDE7024B205B6F8200C40127 /* WatchSync.framework */; };
+ CDE7024D205B6F8200C40127 /* WatchSync.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = CDE7024B205B6F8200C40127 /* WatchSync.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
+ CDE70250205B707B00C40127 /* MyMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDE7024F205B707B00C40127 /* MyMessage.swift */; };
+ CDE70252205B708600C40127 /* MyMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDE70251205B708600C40127 /* MyMessage.swift */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ CDE7020D205B6F0100C40127 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = CDE701F0205B6F0000C40127 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = CDE701F7205B6F0000C40127;
+ remoteInfo = "WatchSync Example";
+ };
+ CDE70217205B6F0100C40127 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = CDE701F0205B6F0000C40127 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = CDE70214205B6F0100C40127;
+ remoteInfo = "WatchSync Example WatchKit App";
+ };
+ CDE70226205B6F0100C40127 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = CDE701F0205B6F0000C40127 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = CDE70223205B6F0100C40127;
+ remoteInfo = "WatchSync Example WatchKit Extension";
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+ CDE70238205B6F0100C40127 /* Embed App Extensions */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "";
+ dstSubfolderSpec = 13;
+ files = (
+ CDE70225205B6F0100C40127 /* WatchSync Example WatchKit Extension.appex in Embed App Extensions */,
+ );
+ name = "Embed App Extensions";
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ CDE7023C205B6F0100C40127 /* Embed Watch Content */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "$(CONTENTS_FOLDER_PATH)/Watch";
+ dstSubfolderSpec = 16;
+ files = (
+ CDE70216205B6F0100C40127 /* WatchSync Example WatchKit App.app in Embed Watch Content */,
+ );
+ name = "Embed Watch Content";
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ CDE7024A205B6F3C00C40127 /* Embed Frameworks */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "";
+ dstSubfolderSpec = 10;
+ files = (
+ CDE70248205B6F3C00C40127 /* WatchSync.framework in Embed Frameworks */,
+ );
+ name = "Embed Frameworks";
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ CDE7024E205B6F8200C40127 /* Embed Frameworks */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "";
+ dstSubfolderSpec = 10;
+ files = (
+ CDE7024D205B6F8200C40127 /* WatchSync.framework in Embed Frameworks */,
+ );
+ name = "Embed Frameworks";
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+ CDE701F8205B6F0000C40127 /* WatchSync Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "WatchSync Example.app"; sourceTree = BUILT_PRODUCTS_DIR; };
+ CDE701FB205B6F0000C40127 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
+ CDE701FD205B6F0000C40127 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
+ CDE70200205B6F0000C40127 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
+ CDE70202205B6F0000C40127 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
+ CDE70205205B6F0000C40127 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
+ CDE70207205B6F0000C40127 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+ CDE7020C205B6F0100C40127 /* WatchSync ExampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "WatchSync ExampleTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
+ CDE70210205B6F0100C40127 /* WatchSync_ExampleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchSync_ExampleTests.swift; sourceTree = ""; };
+ CDE70212205B6F0100C40127 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+ CDE70215205B6F0100C40127 /* WatchSync Example WatchKit App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "WatchSync Example WatchKit App.app"; sourceTree = BUILT_PRODUCTS_DIR; };
+ CDE7021B205B6F0100C40127 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Interface.storyboard; sourceTree = ""; };
+ CDE7021D205B6F0100C40127 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
+ CDE7021F205B6F0100C40127 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+ CDE70224205B6F0100C40127 /* WatchSync Example WatchKit Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "WatchSync Example WatchKit Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
+ CDE70229205B6F0100C40127 /* InterfaceController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InterfaceController.swift; sourceTree = ""; };
+ CDE7022B205B6F0100C40127 /* ExtensionDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExtensionDelegate.swift; sourceTree = ""; };
+ CDE7022D205B6F0100C40127 /* NotificationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationController.swift; sourceTree = ""; };
+ CDE7022F205B6F0100C40127 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
+ CDE70231205B6F0100C40127 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+ CDE70232205B6F0100C40127 /* PushNotificationPayload.apns */ = {isa = PBXFileReference; lastKnownFileType = text; path = PushNotificationPayload.apns; sourceTree = ""; };
+ CDE70246205B6F3C00C40127 /* WatchSync.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = WatchSync.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ CDE7024B205B6F8200C40127 /* WatchSync.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = WatchSync.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ CDE7024F205B707B00C40127 /* MyMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyMessage.swift; sourceTree = ""; };
+ CDE70251205B708600C40127 /* MyMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MyMessage.swift; path = "WatchSync Example/MyMessage.swift"; sourceTree = SOURCE_ROOT; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ CDE701F5205B6F0000C40127 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ CDE7024C205B6F8200C40127 /* WatchSync.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ CDE70209205B6F0100C40127 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ CDE70221205B6F0100C40127 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ CDE70249205B6F3C00C40127 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ CDE70247205B6F3C00C40127 /* WatchSync.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ CDE701EF205B6F0000C40127 = {
+ isa = PBXGroup;
+ children = (
+ CDE701FA205B6F0000C40127 /* WatchSync Example */,
+ CDE7020F205B6F0100C40127 /* WatchSync ExampleTests */,
+ CDE70219205B6F0100C40127 /* WatchSync Example WatchKit App */,
+ CDE70228205B6F0100C40127 /* WatchSync Example WatchKit Extension */,
+ CDE701F9205B6F0000C40127 /* Products */,
+ CDE70243205B6F3100C40127 /* Frameworks */,
+ );
+ sourceTree = "";
+ };
+ CDE701F9205B6F0000C40127 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ CDE701F8205B6F0000C40127 /* WatchSync Example.app */,
+ CDE7020C205B6F0100C40127 /* WatchSync ExampleTests.xctest */,
+ CDE70215205B6F0100C40127 /* WatchSync Example WatchKit App.app */,
+ CDE70224205B6F0100C40127 /* WatchSync Example WatchKit Extension.appex */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ CDE701FA205B6F0000C40127 /* WatchSync Example */ = {
+ isa = PBXGroup;
+ children = (
+ CDE701FB205B6F0000C40127 /* AppDelegate.swift */,
+ CDE70202205B6F0000C40127 /* Assets.xcassets */,
+ CDE70207205B6F0000C40127 /* Info.plist */,
+ CDE70204205B6F0000C40127 /* LaunchScreen.storyboard */,
+ CDE701FF205B6F0000C40127 /* Main.storyboard */,
+ CDE7024F205B707B00C40127 /* MyMessage.swift */,
+ CDE701FD205B6F0000C40127 /* ViewController.swift */,
+ );
+ path = "WatchSync Example";
+ sourceTree = "";
+ };
+ CDE7020F205B6F0100C40127 /* WatchSync ExampleTests */ = {
+ isa = PBXGroup;
+ children = (
+ CDE70210205B6F0100C40127 /* WatchSync_ExampleTests.swift */,
+ CDE70212205B6F0100C40127 /* Info.plist */,
+ );
+ path = "WatchSync ExampleTests";
+ sourceTree = "";
+ };
+ CDE70219205B6F0100C40127 /* WatchSync Example WatchKit App */ = {
+ isa = PBXGroup;
+ children = (
+ CDE7021A205B6F0100C40127 /* Interface.storyboard */,
+ CDE7021D205B6F0100C40127 /* Assets.xcassets */,
+ CDE7021F205B6F0100C40127 /* Info.plist */,
+ );
+ path = "WatchSync Example WatchKit App";
+ sourceTree = "";
+ };
+ CDE70228205B6F0100C40127 /* WatchSync Example WatchKit Extension */ = {
+ isa = PBXGroup;
+ children = (
+ CDE7022F205B6F0100C40127 /* Assets.xcassets */,
+ CDE7022B205B6F0100C40127 /* ExtensionDelegate.swift */,
+ CDE70231205B6F0100C40127 /* Info.plist */,
+ CDE70229205B6F0100C40127 /* InterfaceController.swift */,
+ CDE70251205B708600C40127 /* MyMessage.swift */,
+ CDE7022D205B6F0100C40127 /* NotificationController.swift */,
+ CDE70232205B6F0100C40127 /* PushNotificationPayload.apns */,
+ );
+ path = "WatchSync Example WatchKit Extension";
+ sourceTree = "";
+ };
+ CDE70243205B6F3100C40127 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ CDE7024B205B6F8200C40127 /* WatchSync.framework */,
+ CDE70246205B6F3C00C40127 /* WatchSync.framework */,
+ );
+ name = Frameworks;
+ sourceTree = "";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ CDE701F7205B6F0000C40127 /* WatchSync Example */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = CDE7023D205B6F0100C40127 /* Build configuration list for PBXNativeTarget "WatchSync Example" */;
+ buildPhases = (
+ CDE701F4205B6F0000C40127 /* Sources */,
+ CDE701F5205B6F0000C40127 /* Frameworks */,
+ CDE701F6205B6F0000C40127 /* Resources */,
+ CDE7023C205B6F0100C40127 /* Embed Watch Content */,
+ CDE7024E205B6F8200C40127 /* Embed Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ CDE70218205B6F0100C40127 /* PBXTargetDependency */,
+ );
+ name = "WatchSync Example";
+ productName = "WatchSync Example";
+ productReference = CDE701F8205B6F0000C40127 /* WatchSync Example.app */;
+ productType = "com.apple.product-type.application";
+ };
+ CDE7020B205B6F0100C40127 /* WatchSync ExampleTests */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = CDE70240205B6F0100C40127 /* Build configuration list for PBXNativeTarget "WatchSync ExampleTests" */;
+ buildPhases = (
+ CDE70208205B6F0100C40127 /* Sources */,
+ CDE70209205B6F0100C40127 /* Frameworks */,
+ CDE7020A205B6F0100C40127 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ CDE7020E205B6F0100C40127 /* PBXTargetDependency */,
+ );
+ name = "WatchSync ExampleTests";
+ productName = "WatchSync ExampleTests";
+ productReference = CDE7020C205B6F0100C40127 /* WatchSync ExampleTests.xctest */;
+ productType = "com.apple.product-type.bundle.unit-test";
+ };
+ CDE70214205B6F0100C40127 /* WatchSync Example WatchKit App */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = CDE70239205B6F0100C40127 /* Build configuration list for PBXNativeTarget "WatchSync Example WatchKit App" */;
+ buildPhases = (
+ CDE70213205B6F0100C40127 /* Resources */,
+ CDE70238205B6F0100C40127 /* Embed App Extensions */,
+ CDE70249205B6F3C00C40127 /* Frameworks */,
+ CDE7024A205B6F3C00C40127 /* Embed Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ CDE70227205B6F0100C40127 /* PBXTargetDependency */,
+ );
+ name = "WatchSync Example WatchKit App";
+ productName = "WatchSync Example WatchKit App";
+ productReference = CDE70215205B6F0100C40127 /* WatchSync Example WatchKit App.app */;
+ productType = "com.apple.product-type.application.watchapp2";
+ };
+ CDE70223205B6F0100C40127 /* WatchSync Example WatchKit Extension */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = CDE70235205B6F0100C40127 /* Build configuration list for PBXNativeTarget "WatchSync Example WatchKit Extension" */;
+ buildPhases = (
+ CDE70220205B6F0100C40127 /* Sources */,
+ CDE70221205B6F0100C40127 /* Frameworks */,
+ CDE70222205B6F0100C40127 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "WatchSync Example WatchKit Extension";
+ productName = "WatchSync Example WatchKit Extension";
+ productReference = CDE70224205B6F0100C40127 /* WatchSync Example WatchKit Extension.appex */;
+ productType = "com.apple.product-type.watchkit2-extension";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ CDE701F0205B6F0000C40127 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastSwiftUpdateCheck = 0920;
+ LastUpgradeCheck = 0930;
+ ORGANIZATIONNAME = "Ten Minute Wait";
+ TargetAttributes = {
+ CDE701F7205B6F0000C40127 = {
+ CreatedOnToolsVersion = 9.2;
+ ProvisioningStyle = Automatic;
+ };
+ CDE7020B205B6F0100C40127 = {
+ CreatedOnToolsVersion = 9.2;
+ ProvisioningStyle = Automatic;
+ TestTargetID = CDE701F7205B6F0000C40127;
+ };
+ CDE70214205B6F0100C40127 = {
+ CreatedOnToolsVersion = 9.2;
+ ProvisioningStyle = Automatic;
+ };
+ CDE70223205B6F0100C40127 = {
+ CreatedOnToolsVersion = 9.2;
+ ProvisioningStyle = Automatic;
+ };
+ };
+ };
+ buildConfigurationList = CDE701F3205B6F0000C40127 /* Build configuration list for PBXProject "WatchSync Example" */;
+ compatibilityVersion = "Xcode 8.0";
+ developmentRegion = en;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ Base,
+ );
+ mainGroup = CDE701EF205B6F0000C40127;
+ productRefGroup = CDE701F9205B6F0000C40127 /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ CDE701F7205B6F0000C40127 /* WatchSync Example */,
+ CDE7020B205B6F0100C40127 /* WatchSync ExampleTests */,
+ CDE70214205B6F0100C40127 /* WatchSync Example WatchKit App */,
+ CDE70223205B6F0100C40127 /* WatchSync Example WatchKit Extension */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ CDE701F6205B6F0000C40127 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ CDE70206205B6F0000C40127 /* LaunchScreen.storyboard in Resources */,
+ CDE70203205B6F0000C40127 /* Assets.xcassets in Resources */,
+ CDE70201205B6F0000C40127 /* Main.storyboard in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ CDE7020A205B6F0100C40127 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ CDE70213205B6F0100C40127 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ CDE7021E205B6F0100C40127 /* Assets.xcassets in Resources */,
+ CDE7021C205B6F0100C40127 /* Interface.storyboard in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ CDE70222205B6F0100C40127 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ CDE70230205B6F0100C40127 /* Assets.xcassets in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ CDE701F4205B6F0000C40127 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ CDE701FE205B6F0000C40127 /* ViewController.swift in Sources */,
+ CDE701FC205B6F0000C40127 /* AppDelegate.swift in Sources */,
+ CDE70250205B707B00C40127 /* MyMessage.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ CDE70208205B6F0100C40127 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ CDE70211205B6F0100C40127 /* WatchSync_ExampleTests.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ CDE70220205B6F0100C40127 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ CDE7022E205B6F0100C40127 /* NotificationController.swift in Sources */,
+ CDE70252205B708600C40127 /* MyMessage.swift in Sources */,
+ CDE7022C205B6F0100C40127 /* ExtensionDelegate.swift in Sources */,
+ CDE7022A205B6F0100C40127 /* InterfaceController.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+ CDE7020E205B6F0100C40127 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = CDE701F7205B6F0000C40127 /* WatchSync Example */;
+ targetProxy = CDE7020D205B6F0100C40127 /* PBXContainerItemProxy */;
+ };
+ CDE70218205B6F0100C40127 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = CDE70214205B6F0100C40127 /* WatchSync Example WatchKit App */;
+ targetProxy = CDE70217205B6F0100C40127 /* PBXContainerItemProxy */;
+ };
+ CDE70227205B6F0100C40127 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = CDE70223205B6F0100C40127 /* WatchSync Example WatchKit Extension */;
+ targetProxy = CDE70226205B6F0100C40127 /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
+/* Begin PBXVariantGroup section */
+ CDE701FF205B6F0000C40127 /* Main.storyboard */ = {
+ isa = PBXVariantGroup;
+ children = (
+ CDE70200205B6F0000C40127 /* Base */,
+ );
+ name = Main.storyboard;
+ sourceTree = "";
+ };
+ CDE70204205B6F0000C40127 /* LaunchScreen.storyboard */ = {
+ isa = PBXVariantGroup;
+ children = (
+ CDE70205205B6F0000C40127 /* Base */,
+ );
+ name = LaunchScreen.storyboard;
+ sourceTree = "";
+ };
+ CDE7021A205B6F0100C40127 /* Interface.storyboard */ = {
+ isa = PBXVariantGroup;
+ children = (
+ CDE7021B205B6F0100C40127 /* Base */,
+ );
+ name = Interface.storyboard;
+ sourceTree = "";
+ };
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+ CDE70233205B6F0100C40127 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = 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_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_DOCUMENTATION_COMMENTS = 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_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ 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;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.2;
+ MTL_ENABLE_DEBUG_INFO = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = iphoneos;
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ };
+ name = Debug;
+ };
+ CDE70234205B6F0100C40127 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = 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_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_DOCUMENTATION_COMMENTS = 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_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ 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;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.2;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ SDKROOT = iphoneos;
+ SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Release;
+ };
+ CDE70236205B6F0100C40127 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_COMPLICATION_NAME = Complication;
+ CODE_SIGN_STYLE = Automatic;
+ DEVELOPMENT_TEAM = 4337ZFV4M9;
+ INFOPLIST_FILE = "WatchSync Example WatchKit Extension/Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = "com.tenminutewait.WatchSync-Example.watchkitapp.watchkitextension";
+ PRODUCT_NAME = "${TARGET_NAME}";
+ SDKROOT = watchos;
+ SKIP_INSTALL = YES;
+ SWIFT_VERSION = 4.0;
+ TARGETED_DEVICE_FAMILY = 4;
+ WATCHOS_DEPLOYMENT_TARGET = 4.2;
+ };
+ name = Debug;
+ };
+ CDE70237205B6F0100C40127 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_COMPLICATION_NAME = Complication;
+ CODE_SIGN_STYLE = Automatic;
+ DEVELOPMENT_TEAM = 4337ZFV4M9;
+ INFOPLIST_FILE = "WatchSync Example WatchKit Extension/Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = "com.tenminutewait.WatchSync-Example.watchkitapp.watchkitextension";
+ PRODUCT_NAME = "${TARGET_NAME}";
+ SDKROOT = watchos;
+ SKIP_INSTALL = YES;
+ SWIFT_VERSION = 4.0;
+ TARGETED_DEVICE_FAMILY = 4;
+ WATCHOS_DEPLOYMENT_TARGET = 4.2;
+ };
+ name = Release;
+ };
+ CDE7023A205B6F0100C40127 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CODE_SIGN_STYLE = Automatic;
+ DEVELOPMENT_TEAM = 4337ZFV4M9;
+ IBSC_MODULE = WatchSync_Example_WatchKit_Extension;
+ INFOPLIST_FILE = "WatchSync Example WatchKit App/Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = "com.tenminutewait.WatchSync-Example.watchkitapp";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = watchos;
+ SKIP_INSTALL = YES;
+ SWIFT_VERSION = 4.0;
+ TARGETED_DEVICE_FAMILY = 4;
+ WATCHOS_DEPLOYMENT_TARGET = 4.2;
+ };
+ name = Debug;
+ };
+ CDE7023B205B6F0100C40127 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CODE_SIGN_STYLE = Automatic;
+ DEVELOPMENT_TEAM = 4337ZFV4M9;
+ IBSC_MODULE = WatchSync_Example_WatchKit_Extension;
+ INFOPLIST_FILE = "WatchSync Example WatchKit App/Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = "com.tenminutewait.WatchSync-Example.watchkitapp";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = watchos;
+ SKIP_INSTALL = YES;
+ SWIFT_VERSION = 4.0;
+ TARGETED_DEVICE_FAMILY = 4;
+ WATCHOS_DEPLOYMENT_TARGET = 4.2;
+ };
+ name = Release;
+ };
+ CDE7023E205B6F0100C40127 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CODE_SIGN_STYLE = Automatic;
+ DEVELOPMENT_TEAM = 4337ZFV4M9;
+ INFOPLIST_FILE = "WatchSync Example/Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = "com.tenminutewait.WatchSync-Example";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_VERSION = 4.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ CDE7023F205B6F0100C40127 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CODE_SIGN_STYLE = Automatic;
+ DEVELOPMENT_TEAM = 4337ZFV4M9;
+ INFOPLIST_FILE = "WatchSync Example/Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = "com.tenminutewait.WatchSync-Example";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_VERSION = 4.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Release;
+ };
+ CDE70241205B6F0100C40127 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
+ BUNDLE_LOADER = "$(TEST_HOST)";
+ CODE_SIGN_STYLE = Automatic;
+ DEVELOPMENT_TEAM = 4337ZFV4M9;
+ INFOPLIST_FILE = "WatchSync ExampleTests/Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = "com.tenminutewait.WatchSync-ExampleTests";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_VERSION = 4.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/WatchSync Example.app/WatchSync Example";
+ };
+ name = Debug;
+ };
+ CDE70242205B6F0100C40127 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
+ BUNDLE_LOADER = "$(TEST_HOST)";
+ CODE_SIGN_STYLE = Automatic;
+ DEVELOPMENT_TEAM = 4337ZFV4M9;
+ INFOPLIST_FILE = "WatchSync ExampleTests/Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = "com.tenminutewait.WatchSync-ExampleTests";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_VERSION = 4.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/WatchSync Example.app/WatchSync Example";
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ CDE701F3205B6F0000C40127 /* Build configuration list for PBXProject "WatchSync Example" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ CDE70233205B6F0100C40127 /* Debug */,
+ CDE70234205B6F0100C40127 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ CDE70235205B6F0100C40127 /* Build configuration list for PBXNativeTarget "WatchSync Example WatchKit Extension" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ CDE70236205B6F0100C40127 /* Debug */,
+ CDE70237205B6F0100C40127 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ CDE70239205B6F0100C40127 /* Build configuration list for PBXNativeTarget "WatchSync Example WatchKit App" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ CDE7023A205B6F0100C40127 /* Debug */,
+ CDE7023B205B6F0100C40127 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ CDE7023D205B6F0100C40127 /* Build configuration list for PBXNativeTarget "WatchSync Example" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ CDE7023E205B6F0100C40127 /* Debug */,
+ CDE7023F205B6F0100C40127 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ CDE70240205B6F0100C40127 /* Build configuration list for PBXNativeTarget "WatchSync ExampleTests" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ CDE70241205B6F0100C40127 /* Debug */,
+ CDE70242205B6F0100C40127 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = CDE701F0205B6F0000C40127 /* Project object */;
+}
diff --git a/WatchSync Example/WatchSync Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/WatchSync Example/WatchSync Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 0000000..3ec959d
--- /dev/null
+++ b/WatchSync Example/WatchSync Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/WatchSync Example/WatchSync Example/AppDelegate.swift b/WatchSync Example/WatchSync Example/AppDelegate.swift
new file mode 100644
index 0000000..63386e0
--- /dev/null
+++ b/WatchSync Example/WatchSync Example/AppDelegate.swift
@@ -0,0 +1,29 @@
+//
+// AppDelegate.swift
+// WatchSync Example
+//
+// Created by Nicholas Romano on 3/15/18.
+// Copyright © 2018 Ten Minute Wait. All rights reserved.
+//
+
+import UIKit
+import WatchSync
+
+@UIApplicationMain
+class AppDelegate: UIResponder, UIApplicationDelegate {
+
+ var window: UIWindow?
+
+ func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
+
+ WatchSync.shared.activateSession { error in
+ if let error = error {
+ print("Error activating session \(error.localizedDescription)")
+ return
+ }
+ print("Activated")
+ }
+
+ return true
+ }
+}
diff --git a/WatchSync Example/WatchSync Example/Assets.xcassets/AppIcon.appiconset/Contents.json b/WatchSync Example/WatchSync Example/Assets.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 0000000..1d060ed
--- /dev/null
+++ b/WatchSync Example/WatchSync Example/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,93 @@
+{
+ "images" : [
+ {
+ "idiom" : "iphone",
+ "size" : "20x20",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "20x20",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "29x29",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "29x29",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "40x40",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "40x40",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "60x60",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "60x60",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "20x20",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "20x20",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "29x29",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "29x29",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "40x40",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "40x40",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "76x76",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "76x76",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "83.5x83.5",
+ "scale" : "2x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
\ No newline at end of file
diff --git a/WatchSync Example/WatchSync Example/Base.lproj/LaunchScreen.storyboard b/WatchSync Example/WatchSync Example/Base.lproj/LaunchScreen.storyboard
new file mode 100644
index 0000000..f83f6fd
--- /dev/null
+++ b/WatchSync Example/WatchSync Example/Base.lproj/LaunchScreen.storyboard
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/WatchSync Example/WatchSync Example/Base.lproj/Main.storyboard b/WatchSync Example/WatchSync Example/Base.lproj/Main.storyboard
new file mode 100644
index 0000000..5329366
--- /dev/null
+++ b/WatchSync Example/WatchSync Example/Base.lproj/Main.storyboard
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/WatchSync Example/WatchSync Example/Info.plist b/WatchSync Example/WatchSync Example/Info.plist
new file mode 100644
index 0000000..16be3b6
--- /dev/null
+++ b/WatchSync Example/WatchSync Example/Info.plist
@@ -0,0 +1,45 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ 1.0
+ CFBundleVersion
+ 1
+ LSRequiresIPhoneOS
+
+ UILaunchStoryboardName
+ LaunchScreen
+ UIMainStoryboardFile
+ Main
+ UIRequiredDeviceCapabilities
+
+ armv7
+
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UISupportedInterfaceOrientations~ipad
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationPortraitUpsideDown
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+
+
diff --git a/WatchSync Example/WatchSync Example/MyMessage.swift b/WatchSync Example/WatchSync Example/MyMessage.swift
new file mode 100644
index 0000000..7d1cb7f
--- /dev/null
+++ b/WatchSync Example/WatchSync Example/MyMessage.swift
@@ -0,0 +1,18 @@
+//
+// MyMessage.swift
+// WatchSync Example
+//
+// Created by Nicholas Romano on 3/15/18.
+// Copyright © 2018 Ten Minute Wait. All rights reserved.
+//
+
+import Foundation
+import WatchSync
+
+/**
+ Example message
+ */
+struct MyMessage: SyncableMessage {
+ var myString: String?
+ var myDate: Date?
+}
diff --git a/WatchSync Example/WatchSync Example/ViewController.swift b/WatchSync Example/WatchSync Example/ViewController.swift
new file mode 100644
index 0000000..2aea93d
--- /dev/null
+++ b/WatchSync Example/WatchSync Example/ViewController.swift
@@ -0,0 +1,61 @@
+//
+// ViewController.swift
+// WatchSync Example
+//
+// Created by Nicholas Romano on 3/15/18.
+// Copyright © 2018 Ten Minute Wait. All rights reserved.
+//
+
+import UIKit
+import WatchSync
+
+class ViewController: UIViewController {
+
+ var subscriptionToken: SubscriptionToken?
+
+ override func viewDidLoad() {
+ super.viewDidLoad()
+
+ subscriptionToken = WatchSync.shared.subscribeToMessages(ofType: MyMessage.self) { myMessage in
+ print(String(describing: myMessage.myString), String(describing: myMessage.myDate))
+ }
+ }
+
+ @IBAction func sendMessageButtonPressed(_ sender: Any) {
+ let myMessage = MyMessage(myString: "Test", myDate: Date())
+
+ WatchSync.shared.sendMessage(myMessage) { result in
+ switch result {
+ case .failure(let failure):
+ switch failure {
+ case .sessionNotActivated:
+ break
+ case .watchConnectivityNotAvailable:
+ break
+ case .unableToSerializeMessageAsJSON(let error):
+ break
+ case .watchAppNotPaired:
+ break
+ case .watchAppNotInstalled:
+ break
+ case .unhandledError(let error):
+ break
+ case .badPayloadError(let error):
+ break
+ case .failedToDeliver(let error):
+ let alertController = UIAlertController(title: "✅", message: "Failed to Deliver \(error.localizedDescription)", preferredStyle: .alert)
+ alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
+ self.present(alertController, animated: true, completion: nil)
+ }
+ case .sent:
+ let alertController = UIAlertController(title: "✅", message: "Sent!", preferredStyle: .alert)
+ alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
+ self.present(alertController, animated: true, completion: nil)
+ case .delivered:
+ let alertController = UIAlertController(title: "✅", message: "Delivery Confirmed", preferredStyle: .alert)
+ alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
+ self.present(alertController, animated: true, completion: nil)
+ }
+ }
+ }
+}
diff --git a/WatchSync Example/WatchSync ExampleTests/Info.plist b/WatchSync Example/WatchSync ExampleTests/Info.plist
new file mode 100644
index 0000000..6c40a6c
--- /dev/null
+++ b/WatchSync Example/WatchSync ExampleTests/Info.plist
@@ -0,0 +1,22 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ BNDL
+ CFBundleShortVersionString
+ 1.0
+ CFBundleVersion
+ 1
+
+
diff --git a/WatchSync Example/WatchSync ExampleTests/WatchSync_ExampleTests.swift b/WatchSync Example/WatchSync ExampleTests/WatchSync_ExampleTests.swift
new file mode 100644
index 0000000..9fb876d
--- /dev/null
+++ b/WatchSync Example/WatchSync ExampleTests/WatchSync_ExampleTests.swift
@@ -0,0 +1,34 @@
+//
+// WatchSync_ExampleTests.swift
+// WatchSync ExampleTests
+//
+// Created by Nicholas Romano on 3/15/18.
+// Copyright © 2018 Ten Minute Wait. All rights reserved.
+//
+
+import XCTest
+@testable import WatchSync_Example
+
+class WatchSyncExampleTests: XCTestCase {
+ override func setUp() {
+ super.setUp()
+ // Put setup code here. This method is called before the invocation of each test method in the class.
+ }
+
+ override func tearDown() {
+ // Put teardown code here. This method is called after the invocation of each test method in the class.
+ super.tearDown()
+ }
+
+ func testExample() {
+ // This is an example of a functional test case.
+ // Use XCTAssert and related functions to verify your tests produce the correct results.
+ }
+
+ func testPerformanceExample() {
+ // This is an example of a performance test case.
+ self.measure {
+ // Put the code you want to measure the time of here.
+ }
+ }
+}
diff --git a/WatchSync iOSTests/WatchSync_iOSTests.swift b/WatchSync iOSTests/WatchSync_iOSTests.swift
new file mode 100644
index 0000000..288bb48
--- /dev/null
+++ b/WatchSync iOSTests/WatchSync_iOSTests.swift
@@ -0,0 +1,21 @@
+//
+// WatchSync_iOSTests.swift
+// WatchSync iOSTests
+//
+// Created by Nicholas Romano on 3/15/18.
+//
+
+import XCTest
+@testable import WatchSync
+
+class WatchSyncTests: XCTestCase {
+ override func setUp() {
+ super.setUp()
+ // Put setup code here. This method is called before the invocation of each test method in the class.
+ }
+
+ override func tearDown() {
+ // Put teardown code here. This method is called after the invocation of each test method in the class.
+ super.tearDown()
+ }
+}
diff --git a/WatchSync.podspec b/WatchSync.podspec
new file mode 100644
index 0000000..2efeb70
--- /dev/null
+++ b/WatchSync.podspec
@@ -0,0 +1,25 @@
+Pod::Spec.new do |s|
+ s.name = "WatchSync"
+ s.version = "1.0.0"
+ s.summary = "WatchConnectivity wrapper with typed messages, better error handling, and simplified subscription APIs."
+
+ s.description = <<-DESC
+ Use WatchSync as the WatchConnectivity delegate for your application. It allows you to send typed messages (using `Codable`),
+ receive messages using closures anywhere in your application, and provides better error handling when connectivity isn't working.
+ DESC
+
+ s.homepage = "https://github.com/nickromano/WatchSync"
+ s.license = { :type => "MIT", :file => "LICENSE" }
+
+ s.author = { "Nick Romano" => "nick.r.romano@gmail.com" }
+
+ s.ios.deployment_target = '9.3'
+ s.watchos.deployment_target = '3.0'
+
+ s.source = { :git => "https://github.com/nickromano/WatchSync.git", :tag => "#{s.version}" }
+
+ s.source_files = "Sources/**/*.{h,swift}"
+ s.swift_version = "4.1"
+
+ s.framework = "WatchConnectivity"
+end
diff --git a/WatchSync.xcodeproj/project.pbxproj b/WatchSync.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..567d26c
--- /dev/null
+++ b/WatchSync.xcodeproj/project.pbxproj
@@ -0,0 +1,914 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 48;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 741E19C32068D95300D8C82B /* FileTransferSubscription.swift in Sources */ = {isa = PBXBuildFile; fileRef = 741E19C22068D95300D8C82B /* FileTransferSubscription.swift */; };
+ 741E19C42068D95800D8C82B /* FileTransferSubscription.swift in Sources */ = {isa = PBXBuildFile; fileRef = 741E19C22068D95300D8C82B /* FileTransferSubscription.swift */; };
+ 741E19C62068DA8300D8C82B /* FileTransferResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 741E19C52068DA8300D8C82B /* FileTransferResult.swift */; };
+ 741E19C72068DA9C00D8C82B /* FileTransferResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 741E19C52068DA8300D8C82B /* FileTransferResult.swift */; };
+ 742E93B3206374AF00419EBC /* ApplicationContextSubscription.swift in Sources */ = {isa = PBXBuildFile; fileRef = 742E93B2206374AF00419EBC /* ApplicationContextSubscription.swift */; };
+ 742E93B5206379B300419EBC /* UpdateContextResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 742E93B4206379B300419EBC /* UpdateContextResult.swift */; };
+ 742E93B62063843700419EBC /* UpdateContextResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 742E93B4206379B300419EBC /* UpdateContextResult.swift */; };
+ 742E93B72063845900419EBC /* ApplicationContextSubscription.swift in Sources */ = {isa = PBXBuildFile; fileRef = 742E93B2206374AF00419EBC /* ApplicationContextSubscription.swift */; };
+ CDC29652205B645400305A82 /* WatchSync.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CDC29648205B645400305A82 /* WatchSync.framework */; };
+ CDC29657205B645400305A82 /* WatchSync_iOSTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDC29656205B645400305A82 /* WatchSync_iOSTests.swift */; };
+ CDC29680205B656B00305A82 /* WatchSync.h in Headers */ = {isa = PBXBuildFile; fileRef = CDC2967F205B656B00305A82 /* WatchSync.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ CDC29681205B656B00305A82 /* WatchSync.h in Headers */ = {isa = PBXBuildFile; fileRef = CDC2967F205B656B00305A82 /* WatchSync.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ CDC29688205B679000305A82 /* WatchSync.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDC29687205B678F00305A82 /* WatchSync.swift */; };
+ CDC29689205B679000305A82 /* WatchSync.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDC29687205B678F00305A82 /* WatchSync.swift */; };
+ CDC2968B205B679600305A82 /* SyncableMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDC2968A205B679500305A82 /* SyncableMessage.swift */; };
+ CDC2968C205B679600305A82 /* SyncableMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDC2968A205B679500305A82 /* SyncableMessage.swift */; };
+ CDC2968E205B679C00305A82 /* Codable+JSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDC2968D205B679C00305A82 /* Codable+JSON.swift */; };
+ CDC2968F205B679C00305A82 /* Codable+JSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDC2968D205B679C00305A82 /* Codable+JSON.swift */; };
+ CDC29691205B680B00305A82 /* SendResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDC29690205B680B00305A82 /* SendResult.swift */; };
+ CDC29692205B680B00305A82 /* SendResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDC29690205B680B00305A82 /* SendResult.swift */; };
+ CDE70257205B777800C40127 /* SyncableMessageSubscription.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDE70256205B777800C40127 /* SyncableMessageSubscription.swift */; };
+ CDE70259205B77A700C40127 /* MessageSubscription.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDE70258205B77A700C40127 /* MessageSubscription.swift */; };
+ CDE7025B205B77C200C40127 /* SubscriptionToken.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDE7025A205B77C200C40127 /* SubscriptionToken.swift */; };
+ CDE7025C205B78C800C40127 /* SubscriptionToken.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDE7025A205B77C200C40127 /* SubscriptionToken.swift */; };
+ CDE7025D205B78CA00C40127 /* SyncableMessageSubscription.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDE70256205B777800C40127 /* SyncableMessageSubscription.swift */; };
+ CDE7025E205B78CD00C40127 /* MessageSubscription.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDE70258205B77A700C40127 /* MessageSubscription.swift */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ CDC29653205B645400305A82 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = CDC2963D205B644A00305A82 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = CDC29647205B645400305A82;
+ remoteInfo = "WatchSync iOS";
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXFileReference section */
+ 741E19C22068D95300D8C82B /* FileTransferSubscription.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileTransferSubscription.swift; sourceTree = ""; };
+ 741E19C52068DA8300D8C82B /* FileTransferResult.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileTransferResult.swift; sourceTree = ""; };
+ 742E93B2206374AF00419EBC /* ApplicationContextSubscription.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApplicationContextSubscription.swift; sourceTree = ""; };
+ 742E93B4206379B300419EBC /* UpdateContextResult.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UpdateContextResult.swift; sourceTree = ""; };
+ CDC29648205B645400305A82 /* WatchSync.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = WatchSync.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ CDC29651205B645400305A82 /* WatchSync iOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "WatchSync iOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
+ CDC29656205B645400305A82 /* WatchSync_iOSTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchSync_iOSTests.swift; sourceTree = ""; };
+ CDC29672205B647E00305A82 /* WatchSync.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = WatchSync.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ CDC2967B205B64CB00305A82 /* Info-watchOS.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Info-watchOS.plist"; sourceTree = ""; };
+ CDC2967C205B64CB00305A82 /* Info-iOS.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Info-iOS.plist"; sourceTree = ""; };
+ CDC2967F205B656B00305A82 /* WatchSync.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WatchSync.h; sourceTree = ""; };
+ CDC29682205B657C00305A82 /* Info-iOSTests.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Info-iOSTests.plist"; sourceTree = ""; };
+ CDC29687205B678F00305A82 /* WatchSync.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WatchSync.swift; sourceTree = ""; };
+ CDC2968A205B679500305A82 /* SyncableMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SyncableMessage.swift; sourceTree = ""; };
+ CDC2968D205B679C00305A82 /* Codable+JSON.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Codable+JSON.swift"; sourceTree = ""; };
+ CDC29690205B680B00305A82 /* SendResult.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SendResult.swift; sourceTree = ""; };
+ CDE70256205B777800C40127 /* SyncableMessageSubscription.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SyncableMessageSubscription.swift; sourceTree = ""; };
+ CDE70258205B77A700C40127 /* MessageSubscription.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageSubscription.swift; sourceTree = ""; };
+ CDE7025A205B77C200C40127 /* SubscriptionToken.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubscriptionToken.swift; sourceTree = ""; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ CDC29644205B645400305A82 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ CDC2964E205B645400305A82 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ CDC29652205B645400305A82 /* WatchSync.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ CDC2966E205B647E00305A82 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 740915E82069767A00F14BE3 /* Results */ = {
+ isa = PBXGroup;
+ children = (
+ 741E19C52068DA8300D8C82B /* FileTransferResult.swift */,
+ CDC29690205B680B00305A82 /* SendResult.swift */,
+ 742E93B4206379B300419EBC /* UpdateContextResult.swift */,
+ );
+ path = Results;
+ sourceTree = "";
+ };
+ CDC2963C205B644A00305A82 = {
+ isa = PBXGroup;
+ children = (
+ CDC2967A205B648A00305A82 /* Sources */,
+ CDC29655205B645400305A82 /* WatchSync iOSTests */,
+ CDC29649205B645400305A82 /* Products */,
+ );
+ sourceTree = "";
+ };
+ CDC29649205B645400305A82 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ CDC29648205B645400305A82 /* WatchSync.framework */,
+ CDC29651205B645400305A82 /* WatchSync iOSTests.xctest */,
+ CDC29672205B647E00305A82 /* WatchSync.framework */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ CDC29655205B645400305A82 /* WatchSync iOSTests */ = {
+ isa = PBXGroup;
+ children = (
+ CDC29656205B645400305A82 /* WatchSync_iOSTests.swift */,
+ );
+ path = "WatchSync iOSTests";
+ sourceTree = "";
+ };
+ CDC2967A205B648A00305A82 /* Sources */ = {
+ isa = PBXGroup;
+ children = (
+ CDC2967C205B64CB00305A82 /* Info-iOS.plist */,
+ CDC29682205B657C00305A82 /* Info-iOSTests.plist */,
+ CDC2967B205B64CB00305A82 /* Info-watchOS.plist */,
+ CDE70265205B8F3500C40127 /* WatchSync */,
+ CDC2967F205B656B00305A82 /* WatchSync.h */,
+ );
+ path = Sources;
+ sourceTree = "";
+ };
+ CDE701EE205B6DED00C40127 /* Extensions */ = {
+ isa = PBXGroup;
+ children = (
+ CDC2968D205B679C00305A82 /* Codable+JSON.swift */,
+ );
+ path = Extensions;
+ sourceTree = "";
+ };
+ CDE70253205B772300C40127 /* Subscriptions */ = {
+ isa = PBXGroup;
+ children = (
+ CDE70258205B77A700C40127 /* MessageSubscription.swift */,
+ CDE7025A205B77C200C40127 /* SubscriptionToken.swift */,
+ CDE70256205B777800C40127 /* SyncableMessageSubscription.swift */,
+ 742E93B2206374AF00419EBC /* ApplicationContextSubscription.swift */,
+ 741E19C22068D95300D8C82B /* FileTransferSubscription.swift */,
+ );
+ path = Subscriptions;
+ sourceTree = "";
+ };
+ CDE70265205B8F3500C40127 /* WatchSync */ = {
+ isa = PBXGroup;
+ children = (
+ 740915E82069767A00F14BE3 /* Results */,
+ CDE701EE205B6DED00C40127 /* Extensions */,
+ CDE70253205B772300C40127 /* Subscriptions */,
+ CDC2968A205B679500305A82 /* SyncableMessage.swift */,
+ CDC29687205B678F00305A82 /* WatchSync.swift */,
+ );
+ path = WatchSync;
+ sourceTree = "";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+ CDC29645205B645400305A82 /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ CDC29680205B656B00305A82 /* WatchSync.h in Headers */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ CDC2966F205B647E00305A82 /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ CDC29681205B656B00305A82 /* WatchSync.h in Headers */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+ CDC29647205B645400305A82 /* WatchSync iOS */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = CDC2965A205B645400305A82 /* Build configuration list for PBXNativeTarget "WatchSync iOS" */;
+ buildPhases = (
+ CDC29643205B645400305A82 /* Sources */,
+ CDC29644205B645400305A82 /* Frameworks */,
+ CDC29645205B645400305A82 /* Headers */,
+ CDC29646205B645400305A82 /* Resources */,
+ CD8C9089205F1B2B0010649C /* swiftlint */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "WatchSync iOS";
+ productName = "WatchSync iOS";
+ productReference = CDC29648205B645400305A82 /* WatchSync.framework */;
+ productType = "com.apple.product-type.framework";
+ };
+ CDC29650205B645400305A82 /* WatchSync iOSTests */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = CDC2965D205B645400305A82 /* Build configuration list for PBXNativeTarget "WatchSync iOSTests" */;
+ buildPhases = (
+ CDC2964D205B645400305A82 /* Sources */,
+ CDC2964E205B645400305A82 /* Frameworks */,
+ CDC2964F205B645400305A82 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ CDC29654205B645400305A82 /* PBXTargetDependency */,
+ );
+ name = "WatchSync iOSTests";
+ productName = "WatchSync iOSTests";
+ productReference = CDC29651205B645400305A82 /* WatchSync iOSTests.xctest */;
+ productType = "com.apple.product-type.bundle.unit-test";
+ };
+ CDC29671205B647E00305A82 /* WatchSync watchOS */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = CDC29677205B647E00305A82 /* Build configuration list for PBXNativeTarget "WatchSync watchOS" */;
+ buildPhases = (
+ CDC2966D205B647E00305A82 /* Sources */,
+ CDC2966E205B647E00305A82 /* Frameworks */,
+ CDC2966F205B647E00305A82 /* Headers */,
+ CDC29670205B647E00305A82 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "WatchSync watchOS";
+ productName = "WatchSync watchOS";
+ productReference = CDC29672205B647E00305A82 /* WatchSync.framework */;
+ productType = "com.apple.product-type.framework";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ CDC2963D205B644A00305A82 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastSwiftUpdateCheck = 0920;
+ LastUpgradeCheck = 0930;
+ TargetAttributes = {
+ CDC29647205B645400305A82 = {
+ CreatedOnToolsVersion = 9.2;
+ LastSwiftMigration = 0920;
+ ProvisioningStyle = Manual;
+ };
+ CDC29650205B645400305A82 = {
+ CreatedOnToolsVersion = 9.2;
+ ProvisioningStyle = Automatic;
+ };
+ CDC29671205B647E00305A82 = {
+ CreatedOnToolsVersion = 9.2;
+ LastSwiftMigration = 0920;
+ ProvisioningStyle = Manual;
+ };
+ };
+ };
+ buildConfigurationList = CDC29640205B644A00305A82 /* Build configuration list for PBXProject "WatchSync" */;
+ compatibilityVersion = "Xcode 8.0";
+ developmentRegion = en;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ );
+ mainGroup = CDC2963C205B644A00305A82;
+ productRefGroup = CDC29649205B645400305A82 /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ CDC29647205B645400305A82 /* WatchSync iOS */,
+ CDC29650205B645400305A82 /* WatchSync iOSTests */,
+ CDC29671205B647E00305A82 /* WatchSync watchOS */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ CDC29646205B645400305A82 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ CDC2964F205B645400305A82 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ CDC29670205B647E00305A82 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+ CD8C9089205F1B2B0010649C /* swiftlint */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ );
+ name = swiftlint;
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "if which swiftlint >/dev/null; then\nswiftlint\nelse\necho \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi";
+ };
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ CDC29643205B645400305A82 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ CDE70259205B77A700C40127 /* MessageSubscription.swift in Sources */,
+ 741E19C62068DA8300D8C82B /* FileTransferResult.swift in Sources */,
+ CDC2968E205B679C00305A82 /* Codable+JSON.swift in Sources */,
+ CDC29688205B679000305A82 /* WatchSync.swift in Sources */,
+ CDC2968B205B679600305A82 /* SyncableMessage.swift in Sources */,
+ CDE7025B205B77C200C40127 /* SubscriptionToken.swift in Sources */,
+ 742E93B5206379B300419EBC /* UpdateContextResult.swift in Sources */,
+ 742E93B3206374AF00419EBC /* ApplicationContextSubscription.swift in Sources */,
+ 741E19C32068D95300D8C82B /* FileTransferSubscription.swift in Sources */,
+ CDE70257205B777800C40127 /* SyncableMessageSubscription.swift in Sources */,
+ CDC29691205B680B00305A82 /* SendResult.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ CDC2964D205B645400305A82 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ CDC29657205B645400305A82 /* WatchSync_iOSTests.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ CDC2966D205B647E00305A82 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ CDC2968F205B679C00305A82 /* Codable+JSON.swift in Sources */,
+ 741E19C72068DA9C00D8C82B /* FileTransferResult.swift in Sources */,
+ CDC29689205B679000305A82 /* WatchSync.swift in Sources */,
+ 742E93B72063845900419EBC /* ApplicationContextSubscription.swift in Sources */,
+ CDE7025C205B78C800C40127 /* SubscriptionToken.swift in Sources */,
+ 742E93B62063843700419EBC /* UpdateContextResult.swift in Sources */,
+ CDC2968C205B679600305A82 /* SyncableMessage.swift in Sources */,
+ CDC29692205B680B00305A82 /* SendResult.swift in Sources */,
+ 741E19C42068D95800D8C82B /* FileTransferSubscription.swift in Sources */,
+ CDE7025E205B78CD00C40127 /* MessageSubscription.swift in Sources */,
+ CDE7025D205B78CA00C40127 /* SyncableMessageSubscription.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+ CDC29654205B645400305A82 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = CDC29647205B645400305A82 /* WatchSync iOS */;
+ targetProxy = CDC29653205B645400305A82 /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
+/* Begin XCBuildConfiguration section */
+ CDC29641205B644A00305A82 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ 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.3;
+ ONLY_ACTIVE_ARCH = YES;
+ };
+ name = Debug;
+ };
+ CDC29642205B644A00305A82 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ 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.3;
+ };
+ name = Release;
+ };
+ CDC2965B205B645400305A82 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = 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_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = 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_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_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ CODE_SIGN_IDENTITY = "";
+ CODE_SIGN_STYLE = Manual;
+ COPY_PHASE_STRIP = NO;
+ CURRENT_PROJECT_VERSION = 1;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ DEFINES_MODULE = YES;
+ DEVELOPMENT_TEAM = "";
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ DYLIB_INSTALL_NAME_BASE = "@rpath";
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ 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;
+ INFOPLIST_FILE = "Sources/Info-iOS.plist";
+ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ MTL_ENABLE_DEBUG_INFO = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ PRODUCT_BUNDLE_IDENTIFIER = "com.tenminutewait.WatchSync-iOS";
+ PRODUCT_NAME = WatchSync;
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ SDKROOT = iphoneos;
+ SKIP_INSTALL = YES;
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_VERSION = 4.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VERSIONING_SYSTEM = "apple-generic";
+ VERSION_INFO_PREFIX = "";
+ };
+ name = Debug;
+ };
+ CDC2965C205B645400305A82 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = 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_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = 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_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_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ CODE_SIGN_IDENTITY = "";
+ CODE_SIGN_STYLE = Manual;
+ COPY_PHASE_STRIP = NO;
+ CURRENT_PROJECT_VERSION = 1;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ DEFINES_MODULE = YES;
+ DEVELOPMENT_TEAM = "";
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ DYLIB_INSTALL_NAME_BASE = "@rpath";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ INFOPLIST_FILE = "Sources/Info-iOS.plist";
+ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ MTL_ENABLE_DEBUG_INFO = NO;
+ PRODUCT_BUNDLE_IDENTIFIER = "com.tenminutewait.WatchSync-iOS";
+ PRODUCT_NAME = WatchSync;
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ SDKROOT = iphoneos;
+ SKIP_INSTALL = YES;
+ SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
+ SWIFT_VERSION = 4.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VALIDATE_PRODUCT = YES;
+ VERSIONING_SYSTEM = "apple-generic";
+ VERSION_INFO_PREFIX = "";
+ };
+ name = Release;
+ };
+ CDC2965E205B645400305A82 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
+ ALWAYS_SEARCH_USER_PATHS = 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_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = 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_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_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ CODE_SIGN_STYLE = Automatic;
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ DEVELOPMENT_TEAM = 4337ZFV4M9;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ 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;
+ INFOPLIST_FILE = "Sources/Info-iOSTests.plist";
+ IPHONEOS_DEPLOYMENT_TARGET = 11.2;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ MTL_ENABLE_DEBUG_INFO = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ PRODUCT_BUNDLE_IDENTIFIER = "com.tenminutewait.WatchSync-iOSTests";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = iphoneos;
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_VERSION = 4.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ CDC2965F205B645400305A82 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
+ ALWAYS_SEARCH_USER_PATHS = 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_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = 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_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_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ CODE_SIGN_STYLE = Automatic;
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ DEVELOPMENT_TEAM = 4337ZFV4M9;
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ INFOPLIST_FILE = "Sources/Info-iOSTests.plist";
+ IPHONEOS_DEPLOYMENT_TARGET = 11.2;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ MTL_ENABLE_DEBUG_INFO = NO;
+ PRODUCT_BUNDLE_IDENTIFIER = "com.tenminutewait.WatchSync-iOSTests";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = iphoneos;
+ SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
+ SWIFT_VERSION = 4.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Release;
+ };
+ CDC29678205B647E00305A82 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ APPLICATION_EXTENSION_API_ONLY = YES;
+ 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_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = 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_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_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ CODE_SIGN_IDENTITY = "";
+ CODE_SIGN_STYLE = Manual;
+ COPY_PHASE_STRIP = NO;
+ CURRENT_PROJECT_VERSION = 1;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ DEFINES_MODULE = YES;
+ DEVELOPMENT_TEAM = "";
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ DYLIB_INSTALL_NAME_BASE = "@rpath";
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ 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;
+ INFOPLIST_FILE = "Sources/Info-watchOS.plist";
+ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ MTL_ENABLE_DEBUG_INFO = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ PRODUCT_BUNDLE_IDENTIFIER = "com.tenminutewait.WatchSync-watchOS";
+ PRODUCT_NAME = WatchSync;
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ SDKROOT = watchos;
+ SKIP_INSTALL = YES;
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_VERSION = 4.0;
+ TARGETED_DEVICE_FAMILY = 4;
+ VERSIONING_SYSTEM = "apple-generic";
+ VERSION_INFO_PREFIX = "";
+ WATCHOS_DEPLOYMENT_TARGET = 3.0;
+ };
+ name = Debug;
+ };
+ CDC29679205B647E00305A82 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ APPLICATION_EXTENSION_API_ONLY = YES;
+ 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_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = 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_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_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ CODE_SIGN_IDENTITY = "";
+ CODE_SIGN_STYLE = Manual;
+ COPY_PHASE_STRIP = NO;
+ CURRENT_PROJECT_VERSION = 1;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ DEFINES_MODULE = YES;
+ DEVELOPMENT_TEAM = "";
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ DYLIB_INSTALL_NAME_BASE = "@rpath";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ INFOPLIST_FILE = "Sources/Info-watchOS.plist";
+ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ MTL_ENABLE_DEBUG_INFO = NO;
+ PRODUCT_BUNDLE_IDENTIFIER = "com.tenminutewait.WatchSync-watchOS";
+ PRODUCT_NAME = WatchSync;
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ SDKROOT = watchos;
+ SKIP_INSTALL = YES;
+ SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
+ SWIFT_VERSION = 4.0;
+ TARGETED_DEVICE_FAMILY = 4;
+ VALIDATE_PRODUCT = YES;
+ VERSIONING_SYSTEM = "apple-generic";
+ VERSION_INFO_PREFIX = "";
+ WATCHOS_DEPLOYMENT_TARGET = 3.0;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ CDC29640205B644A00305A82 /* Build configuration list for PBXProject "WatchSync" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ CDC29641205B644A00305A82 /* Debug */,
+ CDC29642205B644A00305A82 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ CDC2965A205B645400305A82 /* Build configuration list for PBXNativeTarget "WatchSync iOS" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ CDC2965B205B645400305A82 /* Debug */,
+ CDC2965C205B645400305A82 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ CDC2965D205B645400305A82 /* Build configuration list for PBXNativeTarget "WatchSync iOSTests" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ CDC2965E205B645400305A82 /* Debug */,
+ CDC2965F205B645400305A82 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ CDC29677205B647E00305A82 /* Build configuration list for PBXNativeTarget "WatchSync watchOS" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ CDC29678205B647E00305A82 /* Debug */,
+ CDC29679205B647E00305A82 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = CDC2963D205B644A00305A82 /* Project object */;
+}
diff --git a/WatchSync.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/WatchSync.xcodeproj/project.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 0000000..9340671
--- /dev/null
+++ b/WatchSync.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/WatchSync.xcodeproj/xcshareddata/xcschemes/WatchSync iOS.xcscheme b/WatchSync.xcodeproj/xcshareddata/xcschemes/WatchSync iOS.xcscheme
new file mode 100644
index 0000000..5f5636f
--- /dev/null
+++ b/WatchSync.xcodeproj/xcshareddata/xcschemes/WatchSync iOS.xcscheme
@@ -0,0 +1,99 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/WatchSync.xcodeproj/xcshareddata/xcschemes/WatchSync watchOS.xcscheme b/WatchSync.xcodeproj/xcshareddata/xcschemes/WatchSync watchOS.xcscheme
new file mode 100644
index 0000000..7edd746
--- /dev/null
+++ b/WatchSync.xcodeproj/xcshareddata/xcschemes/WatchSync watchOS.xcscheme
@@ -0,0 +1,80 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/WatchSync.xcworkspace/contents.xcworkspacedata b/WatchSync.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 0000000..c445b43
--- /dev/null
+++ b/WatchSync.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
diff --git a/WatchSync.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/WatchSync.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 0000000..18d9810
--- /dev/null
+++ b/WatchSync.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+
+
+
+
+ IDEDidComputeMac32BitWarning
+
+
+