WCSession.sendMessage работает 50/50

В последнее время я снова работаю над проектом, связанным с Watch/iPhone. Но мой код иногда работает, а иногда нет, что для меня немного странно, потому что я думаю, что код должен либо работать, либо нет. Не может быть 50/50. Поэтому я понятия не имею, что пошло не так.

настройка WCSession на iPhone:

class WatchCommunicationController: NSObject, WCSessionDelegate {

    var session : WCSession?

    override init(){

        //  super class init
        super.init()

        //  if WCSession is supported
        if WCSession.isSupported() {    //  it is supported

            //  get default session
            session = WCSession.defaultSession()

            //  set delegate
            session!.delegate = self

            //  activate session
            session!.activateSession()

        } else {

            print("iPhone does not support WCSession")
        }
    }

    ... ...
}

аналогичная настройка WCSession на Смотреть:

class PhoneCommunicationController: NSObject, WCSessionDelegate {

    var session : WCSession?

    override init(){

        //  super class init
        super.init()

        //  if WCSession is supported
        if WCSession.isSupported() {    //  it is supported

            //  get default session
            session = WCSession.defaultSession()

            //  set delegate
            session!.delegate = self

            //  activate session
            session!.activateSession()
        } else {

            print("Watch does not support WCSession")
        }
    }

    ... ...
}

отправить сообщение на Смотреть:

func sendGesture (жест: GKGesture) {

//  if WCSession is reachable
if session!.reachable {     //  it is reachable

    //  create the interactive message with gesture
    let message : [String : AnyObject]
    message = [
                "Type":"Gesture",
                "Content":gesture.rawValue
              ]

    //  send message
    session!.sendMessage(message, replyHandler: nil, errorHandler: nil)
    print("Watch send gesture \(gesture)")

} else{                     //  it is not reachable

    print("WCSession is not reachable")
}

}

связанное перечисление:

enum GKGesture: Int {
    case Push = 0, Left, Right, Up, Down
}

получить сообщение на iPhone:

func session(session: WCSession, didReceiveMessage message: [String : AnyObject]) {

        //retrieve info
        let type = message["Type"] as! String
        let content = message["Content"]

        switch type {

        case "Gesture":
            handleGesture(GKGesture(rawValue: content as! Int)!)
        default:
            print("Received message \(message) is invalid with type of \(type)")
        }

    }

    func handleGesture(gesture : GKGesture){

        print("iPhone receives gesture \(gesture)")

        var notificationName = ""

        switch gesture {

        case .Up:
            notificationName = "GestureUp"
        case .Down:
            notificationName = "GestureDown"
        case .Left:
            notificationName = "GestureLeft"
        case .Right:
            notificationName = "GestureRight"
        case .Push:
            notificationName = "GesturePush"
        }

        NSNotificationCenter.defaultCenter().postNotificationName(notificationName, object: nil)

    }

почему-то я не могу отладить приложение Watch в Xcode, сеанс отладки просто не подключается. Я не знаю почему. Поэтому отлаживаю однобоко только с айфоном.

иногда я получал распечатку «получает жест», а иногда нет. И то же самое для получения уведомления.


person Jieyi Hu    schedule 08.07.2015    source источник
comment
Пробовали ли вы сбросить содержимое и настройки и перезапустить симуляторы часов/iPhone и Xcode? Это советы по подключению сеанса отладки. Расскажите мне, как это происходит, и тогда я смогу помочь вам с проблемами WatchConnectivity.   -  person Philip    schedule 08.07.2015
comment
Я отлаживаю с помощью своего iPhone и Apple Watch.   -  person Jieyi Hu    schedule 08.07.2015
comment
Вы должны были сделать что-то особенное для достижимости? Мой код во многом идентичен, но моя проверка всегда возвращает false при проверке достижимости   -  person prawn    schedule 09.07.2015
comment
Я так не думаю. Я думаю, пока iPhone подключен к Wi-Fi, открыт Bluetooth и сопряжен с Apple Watch. Они должны быть доступны.   -  person Jieyi Hu    schedule 10.07.2015


Ответы (3)


Я не знаю, будет ли Int перенесен на NSNumber при передаче в WCSession. Если это так, то должно быть поэтому, когда я использую Int в качестве базового класса перечисления, он не будет работать и работает, когда базовым классом является String.

Известная проблема с подключением Приложение может аварийно завершить работу при использовании объектов NSNumber и NSDate с API WCSession.

Обходной путь: Преобразуйте объект NSNumber или NSDate в строку перед вызовом API-интерфейсов WCSession. Сделайте обратное преобразование на принимающей стороне.

Примечание к выпуску Watch OS 2 Beta 4

person sharpBaga    schedule 17.08.2015

Я предполагаю, что ваш вызов sendMessage возвращает ошибку в тех случаях, когда он терпит неудачу, но вы не реализовали обработчик ошибок!! На данный момент, пока вы встаете и работаете, вы можете просто распечатать ошибку, но если это код поставки, вам действительно следует обрабатывать соответствующие ошибки:

//  send message
session.sendMessage(message, replyHandler: nil, errorHandler: { (error) -> Void in
    print("Watch send gesture \(gesture) failed with error \(error)")
})
print("Watch send gesture \(gesture)")
person ccjensen    schedule 08.07.2015
comment
Я исправил это, изменив перечисление с Int на String. И я работаю теперь каждый раз. Не могли бы вы подумать, почему? Дополнительная информация: меняя каждую вещь, я нажимаю кнопку на часах, чтобы вызвать это sendMessage, он показывает крошечный индикатор прогресса в строке состояния. Но уже не после замены. - person Jieyi Hu; 08.07.2015
comment
нет, это не имеет для меня никакого смысла :) Мне, вероятно, нужно посмотреть на фактический код и иметь возможность запустить его самостоятельно, чтобы получить больше ответов для вас. - person ccjensen; 08.07.2015

Ваш поток правильный, но сложность состоит в том, чтобы понять, как отлаживать:

Наблюдение за отладкой:

  1. Запустите цель iPhone, и когда это будет сделано, нажмите кнопку «Стоп».
  2. Откройте приложение iOS внутри симулятора (запустите его вручную из симулятора, а не из Xcode) и дайте ему повиснуть там.
  3. Переключитесь на цель Watch (приложение yourAppName WatchKit), поставьте соответствующую точку останова и запустите ее.
  4. Приложение iOS будет автоматически переведено в фоновый режим, а затем вы сможете использовать метод sendMessage (в цели Watch), чтобы отправлять все, что вам нужно, и если у вас есть replayHandler в вашем приложении iOS, вы даже будете получать соответствующие сообщения внутри sendMessage в вашей цели Watch (т.е. InterfaceController)

Пример маленького Swift:

Отправка словаря из Watch в приложение iOS:

    if WCSession.defaultSession().reachable == true {
        let requestValues = ["Send" : "From iWatch to iPhone"]
        let session = WCSession.defaultSession()

        session.sendMessage(requestValues,
            replyHandler: { (replayDic: [String : AnyObject]) -> Void in
                print(replayDic["Send"])

            }, errorHandler: { (error: NSError) -> Void in
                print(error.description)
        })
    }
    else
    {
        print("WCSession isn't reachable from iWatch to iPhone")
    }

Получение сообщения от часов и отправка повтора из приложения iOS:

    func session(session: WCSession, didReceiveMessage message: [String : AnyObject], replyHandler: ([String : AnyObject]) -> Void) {

      print(message.values)

      var replyValues = Dictionary<String, AnyObject>()

      replyValues["Send"] = "Received from iphone"
      // Using the block to send back a message to the Watch
      replyHandler(replyValues)
     }

Отладка iPhone:

Полная противоположность отладочным часам

Кроме того, ответ @sharpBaga имеет важное значение.

person OhadM    schedule 21.01.2016