Создание базового высотомера с помощью SwiftUI для Apple Watch

#xcode #swiftui #watchos #core-motion

#xcode #swiftui #watchos #ядро-движение

Вопрос:

Я пытаюсь создать MVP с помощью SwiftUI, который просто показывает мне изменения высоты на моих Apple Watch. Оттуда я выясню, куда идти дальше (я хочу использовать его для парапланеризма и других авиационных вещей).

У меня есть предыдущий опыт работы с python, но ничего в Swift, поэтому даже после тонны руководств я очень неуверен в том, как и где объявлять, а затем использовать функциональные возможности.

Вот мой код на данный момент:

 //
//  ContentView.swift
//  Altimeter WatchKit Extension
//
//  Created by Luke Crouch on 29.09.20.
//

import SwiftUI
import CoreMotion


//class func isRelativeAltitudeAvailable() -> Bool


struct ContentView: View {
    let motionManager = CMMotionManager()
    let queue = OperationQueue()
    let altimeter = CMAltimeter()
    let altitude = 0
    var relativeAltitude: NSNumber = 0
    
    var body: some View {
        
        if motionManager.isRelativeAltitudeAvailable() {
         switch CMAltimeter.authorizationStatus() {
         case .notDetermined: // Handle state before user prompt
             fatalError("Awaiting user prompt...")
         case .restricted: // Handle system-wide restriction
            fatalError("Authorization restricted!")
         case .denied: // Handle user denied state
            fatalError("Auhtorization denied!")
         case .authorized: // Ready to go!
             print("Authorized!")
         @unknown default:
            fatalError("Unknown Authorization Status")
         }
            altimeter.startRelativeAltitudeUpdates(to: queue, withHandler: CMAltitudeHandler)
        }

// something like relative Altitude = queue[..]
        
        Text("(relativeAltitude)")
            .font(.largeTitle)
            .fontWeight(.bold)
            .foregroundColor(Color.green)
    }
}


struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
  

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

  • Тип ‘Void’ не может соответствовать ‘View’, только типы struct / enum / class могут соответствовать протоколам.
  • Значение типа CMMotionManager не имеет члена ‘isRelativeAltitudeAvailable’
  • Тип ‘()’ не может соответствовать представлению…
  • Не удается преобразовать значение типа ‘CMAltitudeHandler.Введите ‘ (он же ‘((Необязательно, необязательно) -> ()).Type’) в ожидаемый аргумент типа ‘CMAltitudeHandler’ (он же ‘(необязательно, необязательно) -> ()’)

Не могли бы вы дать мне несколько советов?

Большое вам спасибо! Люк

Комментарии:

1. Вы упоминаете, что получаете несколько ошибок, вы должны включить эти ошибки в свой вопрос.

2. Вы правы, я отредактировал свой вопрос!

Ответ №1:

Я понял это после долгих попыток:

 //
//  ContentView.swift
//  Altimeter WatchKit Extension
//
//  Created by Lukas Wheldon on 29.09.20.
//

import SwiftUI
import CoreMotion

struct ContentView: View {
    @State var relativeAltitude: NSNumber = 0
    @State var altitude = 0
    let altimeter = CMAltimeter()
    
    func update(d: CMAltitudeData?, e: Error?){
        print("altitude (altitude)")
        print("CMAltimeter (altimeter)")
        print("relative Altitude (relativeAltitude))")
        
    }
    
    
    var body: some View {
        VStack {
            Text("(altimeter)")
                .fontWeight(.bold)
                .foregroundColor(Color.green)
            Button(action: {
                print("START")
                self.startAltimeter()
            }, label: {
                Text("Start Altimeter")
                    .bold()
                    .foregroundColor(.green)
            })
        }
    }
    
    func startAltimeter() {
        if CMAltimeter.isRelativeAltitudeAvailable() {
            switch CMAltimeter.authorizationStatus() {
             case .notDetermined: // Handle state before user prompt
             print("bb")
             //fatalError("Awaiting user prompt...")
             case .restricted: // Handle system-wide restriction
             fatalError("Authorization restricted!")
             case .denied: // Handle user denied state
             fatalError("Authorization denied!")
             case .authorized: // Ready to go!
             let _ = print("Authorized!")
             @unknown default:
             fatalError("Unknown Authorization Status")
             }
            self.altimeter.startRelativeAltitudeUpdates(to: OperationQueue.main) {(data,error) in DispatchQueue.main.async {
                print("(altitude)")
                print("(relativeAltitude)")
            }
            
            }
        }
    }
    
}



struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
    
}
  

Следующими шагами будет проверка, могу ли я получить доступ к необработанным данным барометра и рассчитать высоты по ним.

Комментарии:

1. Похоже, что CMAltimer для измерения высоты используется датчик iPhone, а не датчик часов. Удалось ли получить выходные данные датчика часов?

2. Я использую CMAltimeter в приложении «Мои часы», а также в приложении «Телефон», и оба работают независимо друг от друга. Почему вы так думаете?

3. В частности, значение relativeAltitude поступает с iPhone, даже если код выполняется на часах. Абсолютная высота определяется часами. Чтобы протестировать его, поднимитесь наверх с часами, но оставьте iPhone внизу и обратите внимание, что относительная высота не меняется.