Synchronizing Apple Watch and iPhone using Swift 3

2019-07-15 02:35发布

问题:

I need to Display and modify my data structure from both Apple Watch and iPhone.

The Database:

I am currently using a simple Realm Structure where I have an Object A and an Object B which can hold lots of A's.

So on iPhone the user can create a B and add A's and view of course all A's and B's.

I want the Apple watch to show all A's of the current B and give the users the chance to add new A's to their current B.

The way I have tried to do it:

I wanted to move the hole Realm file from iPhone to the watch or the other way. (That was a tip from the Internet)

iPhone Code:

    override func viewDidLoad() {
    super.viewDidLoad()


    if WCSession.isSupported() { //makes sure it's not an iPad or iPod
        let watchSession = WCSession.default()
        watchSession.delegate = self
        watchSession.activate()

        transferRealmFile()

        if  watchSession.isWatchAppInstalled {
            do {
                try watchSession.updateApplicationContext(["foo": "bar"])
            } catch let error as NSError {
                print(error.description)
            }
        }
    }
}
func transferRealmFile(){
    if let path = Realm.Configuration().fileURL {
        WCSession.default().transferFile(path, metadata: nil)
    }
}

WathcKit Extension:

  func session(_ session: WCSession, didReceive file: WCSessionFile) {

    //set the recieved file to default Realm file
    var config = Realm.Configuration()
    let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
    let documentsDirectory = paths[0]
    let realmURL = documentsDirectory.appendingPathComponent("data.realm")
    if FileManager.default.fileExists(atPath: realmURL.path){
        try! FileManager.default.removeItem(at: realmURL)
    }
    try! FileManager.default.copyItem(at: file.fileURL, to: realmURL)
    config.fileURL = realmURL
    Realm.Configuration.defaultConfiguration = config
}

Then I call transferRealmFile() every time I write to Realm. This works but I can't solve this Problems:

Problems:

  1. It doesn't work if only watchKit App is started.
  2. Apple Watch to iPhone doesn't work the same way. (I think I need to change the didRecived code, but I don't know what)

Question:

Do you know who to solve this 2 Problems or do you maybe know a better way to handle the situation or will the way we interact between iPhone an Watch change in WathcOS 3?

回答1:

With watchOS1 it was possible to use AppGroups to share resources (even your Realm database) between an iOS app and its Watch extension. However, Apple removed this in watchOS 2, so now the only way to share data between your iOS and watchOS apps is via WatchConnectivity. Have a look at this answer.

Sadly the WatchConnectivity framework requires the WCSession to be active on both devices for transferring data, so you can't really get around problem 1.

In my opinion it is a better solution to only communicate the changes between the two apps and not send the whole Realm file, since your Realm file can get quite big and hence sending it forward and backward can take a lot of time and resources, while just sending the changes should be way faster.