2017-12-09 18 views
0

現在、iOSアプリケーションからwatchOS拡張機能にCoreDataデータを取得しようとしています。私はWatchConnectivity Frameworkを使用して、sendMessage(_ message: [String : Any], replyHandler: (([String : Any]) -> Void)?, errorHandler: ((Error) -> Void)? = nil)関数で辞書を取得しています。基本的な接続は正常に動作しています。 iOSアプリにアクセス可能で、サンプル辞書に返信しようとするとすべてが機能しています。WatchConnectivityを使用したCore Data Fetchリクエスト

これまでのところとても良いですが、バックグラウンドでiOSアプリでフェッチリクエストを開始すると、ウォッチアプリはデータを受け取ることはありません。しばらくすると、私はちょうどこのエラーを受け取ります:Error while requesting data from iPhone: Error Domain=WCErrorDomain Code=7012 "Message reply took too long." UserInfo={NSLocalizedFailureReason=Reply timeout occurred., NSLocalizedDescription=Message reply took too long.}

私はiPhone上でiOSアプリケーションを開き、時計アプリケーションを再起動すると、応答ハンドラは結果を取得しています。しかし、ユーザーがiPhone上でiOSアプリを積極的に開くように強制することは役に立たない。

これはなぜ起こるのか誰かが説明できますか?それを行う正しい方法は何ですか? iPhoneで

import WatchConnectivity 

class HomeInterfaceController: WKInterfaceController, WCSessionDelegate { 

// (…) 

func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) { 

    session.sendMessage(["request": "persons"], 
         replyHandler: { (response) in 
          print("response: \(response)") 
         }, 
         errorHandler: { (error) in 
          print("Error while requesting data from iPhone: \(error)") 
    }) 
} 

:悲しいこと

import CoreData 
import WatchConnectivity 

class ConnectivityHandler: NSObject, WCSessionDelegate { 

var personsArray:[Person] = [] 

// (…) 

func session(_ session: WCSession, didReceiveMessage message: [String : Any], replyHandler: @escaping ([String : Any]) -> Void) { 

    // only using the next line is working! 
    // replyHandler(["data": "test"]) 

    if message["request"] as? String == "persons" { 
     fetchAllPersons() 

     var allPersons: [String] = [] 
     for person in personsArray { 
      allPersons.append(person.name!) 
     } 

     replyHandler(["names": allPersons]) 
    } 
} 

// this seems to be never executed (doesn't matter if it's in an extra function or right in the didReceiveMessage func) 
func fetchAllPersons() { 

    do { 
     // Create fetch request. 
     let fetchRequest: NSFetchRequest<Person> = Person.fetchRequest() 

     // Edit the sort key as appropriate. 
     let sortDescriptor = NSSortDescriptor(key: #keyPath(Person.name), ascending: true) 
     fetchRequest.sortDescriptors = [sortDescriptor] 

     personsArray = try DatabaseController.getContext().fetch(fetchRequest) 
    } catch { 
     fatalError("Failed to fetch: \(error)") 
    } 
} 
+0

私が間違って読んでいない限り、時計から電話にメッセージを送信しようとしているようです(あなたはiPhoneコードでdidReceiveMessageを使用しています)。 –

+0

@JohnPollard私は基本的に、CoreDataを時計に取り込もうとしています。これを行うために、私は電話にメッセージを送ります。それは、辞書の中のデータで_reply_するべきです。 – alexkaessner

答えて

0

この問題を調べた後、自分で解決策を見つけました。問題は私がsendMessage(_:replyHandler:errorHandler:)プロトコルを使用していることでした。これは、両方のアプリがアクティブなときにデータを転送するためにのみ使用されます。

Use the sendMessage(_:replyHandler:errorHandler:) or sendMessageData(_:replyHandler:errorHandler:) method to transfer data to a reachable counterpart. These methods are intended for immediate communication between your iOS app and WatchKit extension. The isReachable property must currently be true for these methods to succeed.

あなたがバックグラウンドでデータを転送したい場合は、あなたのニーズに応じて、updateApplicationContext(_:)またはtransferUserInfo(_:)を使用する必要があります。それがまさに私が必要なものです!

Use the updateApplicationContext(_:) method to communicate recent state information to the counterpart. When the counterpart wakes, it can use this information to update its own state. For example, an iOS app that supports Background App Refresh can use part of its background execution time to update the corresponding Watch app. This method overwrites the previous data dictionary, so use this method when your app needs only the most recent data values.

Use the transferUserInfo(_:) method to transfer a dictionary of data in the background. The dictionaries you send are queued for delivery to the counterpart and transfers continue when the current app is suspended or terminated.

iPhoneアプリの対応は、ApplicationContextのかのUserInfoキューがトラフを渡され、私は私のコアデータライブラリにデータを追加することができます開いた場合。

0

、最もWatchConnectivity方法のAppグループはwatchOS以来2.私はところでスウィフト4を使用してい
...アップルの時計に

時代遅れであるように見えます(エラーによってあなたに言われたように)時間制限があります。あなたのCoreDataリクエストに時間がかかり過ぎるため、制限時間を超えています。 this Q&Aによると、バックグラウンドでCoreDataクエリを実行するための具体的な予防措置を講じる必要があるため、問題の原因になる可能性があります。

CoreDataWatchConnectivityフレームワークの使用を中止することをお勧めします。後者の場合、iOSアプリが少なくともバックグラウンドで実行されている必要があります。そのためwatchOSアプリケーションは、 iOSアプリで、watchOSのユーザーエクスペリエンスが低下します。 RealmはwatchOSを完全にサポートしているため、watchOSアプリケーションをiOSアプリケーションから完全に独立させることができ、ユーザーはiOSアプリケーションを起動して待つ必要がなくなるため、より多くの体感が得られるため、Realmに切り替えることをおすすめします。 WatchConnectivityフレームワークを使用したBLEによるデータ伝送。

+0

私のiPhoneでiOSアプリを開くと機能しているということです。したがって、CoreDataリクエストは十分に速いと思われます。問題はそれがバックグラウンドで決して実行されないということです。 「Realm」のヒントをありがとうございますが、これは単なるアップデートであり、Realmに切り替えるために私の全アプリを再加工したくありません。 – alexkaessner

+0

リンクされたQ&Aで説明されているように、CoreDataフェッチはバックグラウンドでも機能するはずですが、その動作はフォアグラウンドで実行されているときと同じではない可能性があります。 –

関連する問題