Подтвердить что ты не робот

"Сообщение ответ занял слишком много времени". - Наблюдайте за связью с Watch OS 3

В моем проекте я использую Watch Connectivity для отправки сообщений в Watch и iPhone и обратно. Я могу отправить сообщение на телефон и получить массив строк при запуске приложения, однако при использовании действий я получаю следующую ошибку;

Ошибка домена = код WCErrorDomain = 7012 "Сообщение ответа заняло слишком много времени".

Здесь, как вещи настроены,

Сначала часы отправляют сообщение на телефон, а затем телефон отправляет массив строк для отображения в WKInterfaceTable. Это иногда срабатывает при загрузке приложения. (Я извлекаю все NSManagedObjects под названием Items и использую их строковые свойства title для хранения в array, называемом watchItems.

Однако у меня есть действие на часах, чтобы удалить все элементы в массиве и обновить таблицу новыми данными.

Действие на часах использует функцию sendMessage для отправки item на телефон для удаления из массива, затем телефон отправляет новый обновленный массив на часы, а часы обновляют таблицу. Однако я либо получаю тот же массив, либо ошибку.

Довольно простое право, поэтому все действительно отлично работало до Swift 3 и Watch OS3/iOS 10; все приложение использовалось для работы.

Вот как у меня все настроено;

Диспетчер приложений для телефона

import WatchConnectivity

class AppDelegate: UIResponder, UIApplicationDelegate, WCSessionDelegate {

var session : WCSession!

var items = [Items]()

func loadData() {
    let moc = (UIApplication.shared.delegate as! AppDelegate).managedObjectContext
    let request = NSFetchRequest<Items>(entityName: "Items")

    request.sortDescriptors = [NSSortDescriptor(key: "date", ascending: true)]
    request.predicate = NSPredicate(format: "remove == 0", "remove")

    do {
        try
            self.items = moc!.fetch(request)
        // success ...
    } catch {
        // failure
        print("Fetch failed")
    }
}

//WATCH EXTENSION FUNCTIONS
//IOS 9.3 
/** Called when the session has completed activation. If session state is WCSessionActivationStateNotActivated there will be an error with more details. */


//HAVE TO INCLUDE
@available(iOS 9.3, *)
func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?){
   print("iPhone WCSession activation did complete")
}


@available(iOS 9.3, *)
func sessionDidDeactivate(_ session: WCSession) {}

func sessionWatchStateDidChange(_ session: WCSession) {}

func sessionDidBecomeInactive(_ session: WCSession) {

}

//APP DELEGATE FUNCTIONS

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {

    //Check if session is supported and Activate
    if (WCSession.isSupported()) {
        session = WCSession.default()
        session.delegate = self;
        session.activate()
    }
    return true
}


}

//DID RECIEVE MESSAGE
func session(_ session: WCSession, didReceiveMessage message: [String : Any], replyHandler: @escaping ([String : Any]) -> Swift.Void) {


    loadData()

    func loadItems() {
        watchItems.removeAll()

        for a in self.items {
            watchItems.append(a.title)
        }
    }

    var watchItems = ["1","2","3","4","5"]

    let value = message["Value"] as? String

    //This is called when user loads app, and takes some time when using refresh action, sometimes times out 

    if value == "HELLOiPhone/[email protected]=" {

        print("Hello Message Recieved")

        loadItems() 

        //send a reply
        replyHandler( [ "Items" : Items ] )

    }

    //Not sure if receiving but does not delete array and send back to watch
    if value == "[email protected]+=-/" {                        
        for index in self.items {
            index.remove = 1
            //Saves MOC
        }

        loadData()
        loadTasksData()

        //send a reply
        replyHandler( [ "Items" : Items ] )

    }
    else {
        for index in self.items {
            if index.title == value {
            index.remove = 1
            //Saves MOC
            }
        }

        loadData()
        loadTasksData()

        //send a reply
        replyHandler( [ "Items" : Items ] )
    }
}

ЧАСЫ

import WatchConnectivity

class SimplelistInterfaceController: WKInterfaceController, WCSessionDelegate  {


/** Called when the session has completed activation. If session state is WCSessionActivationStateNotActivated there will be an error with more details. */
@available(watchOS 2.2, *)
public func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {

   //Fetch data is a function which sends a "HELLOiPhone/[email protected]=" message to receive the array and displays in the table. This works 
   fetchData()
}


var session : WCSession!
var items = ["Refresh Items"]

override func didAppear() {
    fetchData()
}

override func willActivate() {
    // This method is called when watch view controller is about to be visible to user
    super.willActivate()
    //Check if session is supported and Activate
    if (WCSession.isSupported()) {
        session = WCSession.default()
        session.delegate = self
        session.activate()
    }
    fetchData()
}

override func awake(withContext context: Any?) {
    super.awake(withContext: context)
    fetchData()
}

@IBAction func refresh() {
    print("Refresh")
    //Works but sometimes message is delayed
    fetchData()
}

@IBAction func removeAll() {
    print("Remove All Items is called")
    if WCSession.default().isReachable {
        let messageToSend = ["Value":"[email protected]+=-/"]
        print("\(messageToSend)")
        session.sendMessage(messageToSend, replyHandler: { replyMessage in
            if let value = replyMessage["Items"] {
                self.items = value as! [String]

                Not receiving message
                print("Did Recieve Message, items = \(self.items)")
            }

            }, errorHandler: {error in
                // catch any errors here
                print(error)
        })
    }
    fetchData()
}

}
4b9b3361

Ответ 1

Я только что обратился к моему приложению WatchOS. И была ситуация, когда я получил сообщение "Message reply was too long".

Затем я добавил обработчик фонового задания в мое приложение iOS и начал отправлять сообщения каждую секунду в приложение WatchOS. Сообщение содержало UIApplication.shared.backgroundTimeRemaining. Так что я получаю: 45 сек, 44 сек,..., 6 сек, 5 сек,... Если таймер работает менее 5 секунд, в приложение iOS/из приложения iOS не будет отправлено сообщений, и мы получим "Сообщение ответа заняло слишком много времени". Самое легкое решение заключалось в том, чтобы отправлять пустые сообщения от часов к телефону каждый раз, когда таймер идет ниже 15 секунд. backgroundTimeRemaining будет обновляться до 45 секунд: 45, 44, 43,..., 17, 16, 15, (пустое сообщение), 45, 44, 43,...

Надеюсь, что это поможет кому-то