WatchConnectivity отправка сообщения часов с запуском таймера на iphone

Я создал приложение таймера, которое работает на iphone. Я бы хотел, чтобы мы могли управлять им iPhone и Watch

Снимок экрана проекта

Элементы управления (Play, Stop, Restart) с iPhone работают нормально, мой счетчик отображается на часах.

Часы на Стоп работают хорошо, на фоне Старта не работают, счетчик не включает ни Айфон, ни Часы.

Перезапустите работы тоже.

Моя метка на iPhone очень медленно меняется, если информация поступает с часов, но хорошо работает в другом направлении, к часам iPhone.

Вы заметили эту проблему? Это проблема, связанная с WatchConnectivity.

Спасибо за вашу помощь

Ниже мой код:

ViewController.swift

import UIKit
import WatchConnectivity

class ViewController: UIViewController, WCSessionDelegate {

@IBOutlet weak var timerLabel: UILabel!
@IBOutlet weak var watchLabel: UILabel!

var session: WCSession!
var timerCount = 0
var timerRunning = false
var timer = NSTimer()

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    if (WCSession.isSupported()) {
        let session = WCSession.defaultSession()
        session.delegate = self
        session.activateSession()

        if session.paired != true {
            print("Apple Watch is not paired")
        }

        if session.watchAppInstalled != true {
            print("WatchKit app is not installed")
        }
    } else {
        print("WatchConnectivity is not supported on this device")
    }

}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}    


@IBAction func startButton(sender: UIButton) {
    startPlay()
}

@IBAction func stopButton(sender: UIButton) {
    stopPlay()
}


@IBAction func restartButton(sender: UIButton) {
   restartPlay()
}

//Receive messages from watch
func session(session: WCSession, didReceiveMessage message: [String : AnyObject], replyHandler: ([String : AnyObject]) -> Void) {
    var replyValues = Dictionary<String, AnyObject>()

    //let viewController = self.window!.rootViewController as! ViewController      
    switch message["command"] as! String {
    case "start" :
        startPlay()
        replyValues["status"] = "Playing"
    case "stop" :
        stopPlay()
        replyValues["status"] = "Stopped"
    case "restart" :
        restartPlay()
        replyValues["status"] = "Stopped"
    default:
        break
    }
    replyHandler(replyValues)
}

//Counter Timer
func counting(timer:NSTimer) {
    self.timerCount++
    self.timerLabel.text = String(timerCount)

    let requestValues = ["timer" : String(timerCount)]
    let session = WCSession.defaultSession()
    session.sendMessage(requestValues, replyHandler: nil, errorHandler: { error in print("error: \(error)")})
}

//Fonction Play
func startPlay() {
    if timerRunning == false {
        self.timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: Selector("counting:"), userInfo: nil, repeats: true)
        self.timerRunning = true
        self.watchLabel.text = "START"
    }
}

//Fonction Stop
func stopPlay() {
    if timerRunning == true {
        self.timer.invalidate()
        self.timerRunning = false
        self.watchLabel.text = "STOP"
    }
}

//Fonction Restart
func restartPlay() {
    self.timerCount = 0
    self.timerLabel.text = "0";

    let requestValues = ["timer" : "0"]
    let session = WCSession.defaultSession()
    session.sendMessage(requestValues, replyHandler: nil, errorHandler: { error in print("error: \(error)")})
}
}

InterfaceController.swift

import WatchKit
import Foundation
import WatchConnectivity


class InterfaceController: WKInterfaceController, WCSessionDelegate {

@IBOutlet var watchLabel: WKInterfaceLabel!
@IBOutlet var statusLabel: WKInterfaceLabel!

//Receiving message from iphone
func session(session: WCSession, didReceiveMessage message: [String : AnyObject]) {
    self.watchLabel.setText(message["timer"]! as? String)
    // self.statusLabel.setText(message["command"]! as? String)
}


override func awakeWithContext(context: AnyObject?) {
    super.awakeWithContext(context)
    // Configure interface objects here.
}

override func willActivate() {
    // This method is called when watch view controller is about to be visible to user
    super.willActivate()
    if (WCSession.isSupported()) {
        let session = WCSession.defaultSession()
        session.delegate = self
        session.activateSession()
    }
}

override func didDeactivate() {
    // This method is called when watch view controller is no longer visible
    super.didDeactivate()
}


@IBAction func startButtonWatch() {
    if WCSession.defaultSession().reachable == true {
        let requestValues = ["command" : "start"]
        let session = WCSession.defaultSession()
        session.sendMessage(requestValues, replyHandler: { reply in
            self.statusLabel.setText(reply["status"] as? String)
            }, errorHandler: { error in
                print("error: \(error)")
        })

    }

}


@IBAction func stopButtonWatch() {
    if WCSession.defaultSession().reachable == true {
        let requestValues = ["command" : "stop"]
        let session = WCSession.defaultSession()
        session.sendMessage(requestValues, replyHandler: { reply in
            self.statusLabel.setText(reply["status"] as? String)
            }, errorHandler: { error in
                print("error: \(error)")
        })

    }
}

@IBAction func restartButtonWatch() {
    if WCSession.defaultSession().reachable == true {
        let requestValues = ["command" : "restart"]
        let session = WCSession.defaultSession()
        session.sendMessage(requestValues, replyHandler: { reply in
            self.statusLabel.setText(reply["status"] as? String)
            }, errorHandler: { error in
                print("error: \(error)")
        })

    }

}

}

person Arno.R    schedule 22.10.2015    source источник


Ответы (2)



Вы должны использовать это:

   func startPlay() {
    if timerRunning == false {
        //self.timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: Selector("counting:"), userInfo: nil, repeats: true)
        self.timer = NSTimer(timeInterval: 1, target: self, selector: "counting:", userInfo: nil, repeats: true)
        NSRunLoop.mainRunLoop().addTimer(self.timer, forMode: NSRunLoopCommonModes)
        self.timerRunning = true
        self.watchLabel.text = "Start"
    }
}


Я не могу объяснить вам, почему нам нужно явно использовать NSRunLoop. Я застрял с той же проблемой таймера при разработке приложения с передачей данных. Некоторые ответы можно найти в гугле по запросу "ntimer run loop" или здесь.
И я предпочитаю использовать это для перезапуска:

    func restartPlay() {
    self.timerCount = 0
    self.timerLabel.text = "0";
    stopPlay()
    startPlay()
    self.watchLabel.text = "Restarted"
}


Удачи.

person user3820674    schedule 22.10.2015

Этот функциональный и оптимизированный код:

//Fonction Play
func startPlay() {
    if timerRunning == false {
        self.mytimer = NSTimer(timeInterval: 1, target: self, selector: "counting:", userInfo: nil, repeats: true)
        NSRunLoop.mainRunLoop().addTimer(self.mytimer, forMode: NSRunLoopCommonModes)
        timerRunning = true
        dispatch_async(dispatch_get_main_queue()) {
            self.watchLabel.text = "PLAYING"
        }
    }
}
person Arno.R    schedule 23.10.2015