-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 67afcdc
Showing
51 changed files
with
3,749 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
*.xccheckout | ||
*.xcuserstate | ||
*.xcscmblueprint | ||
**/xcuserdata/* | ||
.DS_Store | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
disabled_rules: | ||
- line_length | ||
- cyclomatic_complexity | ||
- multiple_closures_with_trailing_closure | ||
- function_body_length | ||
- file_length |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
<plist version="1.0"> | ||
<dict> | ||
<key>CFBundleDevelopmentRegion</key> | ||
<string>$(DEVELOPMENT_LANGUAGE)</string> | ||
<key>CFBundleExecutable</key> | ||
<string>$(EXECUTABLE_NAME)</string> | ||
<key>CFBundleIdentifier</key> | ||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> | ||
<key>CFBundleInfoDictionaryVersion</key> | ||
<string>6.0</string> | ||
<key>CFBundleName</key> | ||
<string>$(PRODUCT_NAME)</string> | ||
<key>CFBundlePackageType</key> | ||
<string>FMWK</string> | ||
<key>CFBundleShortVersionString</key> | ||
<string>1.0</string> | ||
<key>CFBundleVersion</key> | ||
<string>$(CURRENT_PROJECT_VERSION)</string> | ||
<key>NSPrincipalClass</key> | ||
<string></string> | ||
</dict> | ||
</plist> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
<plist version="1.0"> | ||
<dict> | ||
<key>CFBundleDevelopmentRegion</key> | ||
<string>$(DEVELOPMENT_LANGUAGE)</string> | ||
<key>CFBundleExecutable</key> | ||
<string>$(EXECUTABLE_NAME)</string> | ||
<key>CFBundleIdentifier</key> | ||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> | ||
<key>CFBundleInfoDictionaryVersion</key> | ||
<string>6.0</string> | ||
<key>CFBundleName</key> | ||
<string>$(PRODUCT_NAME)</string> | ||
<key>CFBundlePackageType</key> | ||
<string>BNDL</string> | ||
<key>CFBundleShortVersionString</key> | ||
<string>1.0</string> | ||
<key>CFBundleVersion</key> | ||
<string>1</string> | ||
</dict> | ||
</plist> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
<plist version="1.0"> | ||
<dict> | ||
<key>CFBundleDevelopmentRegion</key> | ||
<string>$(DEVELOPMENT_LANGUAGE)</string> | ||
<key>CFBundleExecutable</key> | ||
<string>$(EXECUTABLE_NAME)</string> | ||
<key>CFBundleIdentifier</key> | ||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> | ||
<key>CFBundleInfoDictionaryVersion</key> | ||
<string>6.0</string> | ||
<key>CFBundleName</key> | ||
<string>$(PRODUCT_NAME)</string> | ||
<key>CFBundlePackageType</key> | ||
<string>FMWK</string> | ||
<key>CFBundleShortVersionString</key> | ||
<string>1.0</string> | ||
<key>CFBundleVersion</key> | ||
<string>$(CURRENT_PROJECT_VERSION)</string> | ||
<key>NSPrincipalClass</key> | ||
<string></string> | ||
</dict> | ||
</plist> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
// | ||
// WatchSync.h | ||
// WatchSync | ||
// | ||
// Created by Nicholas Romano on 3/15/18. | ||
// | ||
|
||
#import <Foundation/Foundation.h> | ||
|
||
//! 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 <WatchSync/PublicHeader.h> | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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)!) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} |
Oops, something went wrong.