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 в Watch:

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")
        }
    }

    ... ...
}

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

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, сеанс отладки просто не подключается. Я не знаю, почему. Поэтому я отлаживаю одностороннее только iPhone.

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

Ответ 1

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

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

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

Смотреть заметку о выпуске OS 2 Beta 4

Ответ 2

Я предполагаю, что ваш вызов 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)")

Ответ 3

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

Отладочные часы:

  • Запустите цель iPhone, и когда она будет сделана, нажмите кнопку "Стоп".
  • Откройте приложение iOS внутри симулятора (запустите его вручную из симулятора, а не из Xcode) и пусть он там висит.
  • Переключитесь на цель Watch (приложение WatchAit приложения yourAppName), поместите соответствующую точку останова и запустите ее.
  • Приложение iOS будет автоматически помещено в фоновом режиме, а затем вы сможете использовать метод sendMessage (в целевой часах), чтобы отправить все, что вам нужно, и если у вас есть replayHandler в приложении iOS, вы даже получите соответствующий сообщения внутри sendMessage в вашей целевой части Watch (т.е. InterfaceController)

Пример Small 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 имеет важное значение.