Отправить сообщение на Apple Watch с помощью WCSession в SwiftUI - PullRequest
4 голосов
/ 18 января 2020

Я сделал очень долго go, как отправить простое сообщение с iPhone на Apple Watch с помощью Swift:

import UIKit
import WatchConnectivity

class ViewController: UIViewController, WCSessionDelegate {

    // MARK: Outlets

    @IBOutlet weak var textField: UITextField!

    // MARK: Variables

    var wcSession : WCSession! = nil

    // MARK: Overrides

    override func viewDidLoad() {
        super.viewDidLoad()

        wcSession = WCSession.default
        wcSession.delegate = self
        wcSession.activate()

    }

    // MARK: Button Actions

    @IBAction func sendText(_ sender: Any) {

        let txt = textField.text!
        let message = ["message":txt]

        wcSession.sendMessage(message, replyHandler: nil) { (error) in

            print(error.localizedDescription)

        }

    }

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

        // Code

    }

    func sessionDidBecomeInactive(_ session: WCSession) {

        // Code

    }

    func sessionDidDeactivate(_ session: WCSession) {

        // Code

    }

}

Теперь я пытаюсь сделать то же самое, используя SwiftUI, но пока безуспешно. Кто-нибудь может помочь с этой проблемой?

Мне просто нужно знать, как использовать класс WCSession и WCSessionDelegate с SwiftUI.

Спасибо

1 Ответ

0 голосов
/ 08 апреля 2020

У меня был тот же вопрос, что и у вас, и я понял:

Сначала вам нужно реализовать класс, соответствующий WCSessionDelegate. Мне нравится использовать для этого отдельный класс:

import WatchConnectivity

class ConnectivityProvider: NSObject, WCSessionDelegate {

    private let session: WCSession

    init(session: WCSession = .default) {
        self.session = session
        super.init()
        self.session.delegate = self
    }

    func send(message: [String:Any]) -> Void {
        session.sendMessage(message, replyHandler: nil) { (error) in
            print(error.localizedDescription)
        }
    }

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

    func sessionDidBecomeInactive(_ session: WCSession) {
        // code
    }

    func sessionDidDeactivate(_ session: WCSession) {
        // code
    }
}

Теперь вам нужен ViewModel, который принимает ваш ConnectivityProvider в качестве аргумента. ViewModel будет нести ответственность за соединение вашего View и ConnectivityProvider. Он также содержит значение для текстового поля, которое позже будет определено в вашем представлении.

import SwiftUI  

final class ViewModel: ObservableObject {

    private(set) var connectivityProvider: ConnectivityProvider
    var textFieldValue: String = ""

    init(connectivityProvider: ConnectivityProvider) {
        self.connectivityProvider = connectivityProvider
    }

    func sendMessage() -> Void {
        let txt = textFieldValue
        let message = ["message":txt]
        connectivityProvider.send(message: message)
    }
}

Теперь вы можете создать простое представление, состоящее из текстового поля и кнопки. Ваш View будет зависеть от вашей ViewModel, которую вы только что определили.

import SwiftUI

struct ContentView: View {

    @ObservedObject var viewModel: ViewModel

    var body: some View {
        VStack {
            TextField("Message Content", text: $viewModel.textFieldValue)

            Button(action: {
                self.viewModel.sendMessage()
            }) {
                Text("Send Message")
            }
        }
    }
}

И последнее, но не менее важное: вам нужно объединить ваш ConnectivityProvider, ViewModel и View внутри вашего SceneDelegate:

let viewModel = ViewModel(connectivityProvider: ConnectivityProvider())
let contentView = ContentView(viewModel: viewModel)

...

window.rootViewController = UIHostingController(rootView: contentView)
...