Machineboy空

CoreLocation speed를 이용해 현재 정지해 있는 상태인지 파악해보자! 본문

언어/iOS

CoreLocation speed를 이용해 현재 정지해 있는 상태인지 파악해보자!

안녕도라 2024. 10. 31. 12:11

현재 걷고 있는지, 정지해있는지를 파악하고 싶다.

귀여운 피크민

 

피크민 꽃 심기 모드 중에 운전을 하거나, 버스를 타면 운전중은 아닌지 물어보는 알림이 뜨는데,

캡쳐를 해두지 못해 햄버거 피크민을 첨부한다.

아무튼 기기의 움직임을 감지하는 기능을 구현하고자 한다.


시도한 방법 1: CoreMotion - CMMotionActivity를 이용

 

CoreMotion 라이브러리 안에 CMMotionActivity라는 타입이 있는데, 기기의 움직임 분류해 주는 듯하다.

 

테스트코드

import CoreMotion
import SwiftUI

struct CoreMotionView: View {
    @StateObject private var motionManager = CoreMotionManager()
    
    var body: some View {
        Text(motionManager.status)
    }
}

class CoreMotionManager: NSObject, ObservableObject {
    let motionManager = CMMotionActivityManager()
    @Published var status: String = "Status Unknown"
    
    override init() {
            super.init()
            startActivityUpdates()
        }
    
    func startActivityUpdates() {
        guard CMMotionActivityManager.isActivityAvailable() else {
            status = "Motion data not available"
            return
        }
        
        motionManager.startActivityUpdates(to: .main) { [weak self] activity in
            guard let self = self, let activity = activity else { return }
            DispatchQueue.main.async {
                if activity.running {
                    self.status = "Running"
                } else if activity.walking {
                    self.status = "Walking"
                } else if activity.automotive {
                    self.status = "In a vehicle"
                } else if activity.cycling {
                    self.status = "Cycling"
                } else if activity.stationary {
                    self.status = "Stationary"
                } else {
                    self.status = "Unknown activity"
                }
            }
        }
    }
}

 

결과 :

정말 책상이나 정지한 곳에 기기를 놓아두지 두지 않는 이상 stationary가 뜨지 않는다.

조금이라도 움직임이 감지되면 unknown으로 분류되어버린다. 

작은 움직임정도는 허용해야 하는데, 너무 정밀하게 판단하는 듯 하여 지금 구현하고자 하는 기능에는 적합하지 않다고 생각했다.

더불어 Running 과 Walking 등은 어떤 상황에 반환되는지도 궁금하다.


시도한 방법 2: CoreLocation - speed를 이용

 

 

 

 

테스트코드

import CoreLocation
import SwiftUI

class LocationManager: NSObject, CLLocationManagerDelegate, ObservableObject {
    var locationManager = CLLocationManager()
    @Published var location: CLLocation?
    @Published var speed: Double = 0.0
    
    
    override init() {
        super.init()
        locationManager.delegate = self
        locationManager.startUpdatingLocation()
    }
    
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        if let latestLocation = locations.last {
            location = latestLocation
            speed = latestLocation.speed
        }
    }
}


struct CoreLocationView: View {
    @ObservedObject var locationManager = LocationManager()
    @State private var showAlert = false
    
    var body: some View {
        VStack {
            Text("Location: \(locationManager.locationManager.location?.coordinate ?? CLLocationCoordinate2D())")
            Text("Speed: \(locationManager.locationManager.location?.speed ?? -100 )")
                .font(.largeTitle)
                .padding()
                .onChange(of: locationManager.speed) {
                    if locationManager.speed > 0.5 {
                        showAlert = true
                    }
                }
        }
        .alert(isPresented: $showAlert) {
            Alert(title: Text("Speed Alert!"), message: Text("Your speed is above 0.5 m/s!"), dismissButton: .default(Text("OK")))
        }
    }
    
}

 

결과 :

CMMotionActivity처럼 enum형의 케이스가 아닌

기기의 speed수치를 받아와 원하는 조건 범위를 설정할 수 있다.

가만히 앉아 팔을 휘두르는 것 만으로 0.5 이상이 나오기도 하는데, 이 정도면 정지한 상태라고 파악해도 되지 않을까 싶어

임의로 0.5로 정지 상태를 판단하기로 했다.

 

speed를 내부적으로 어떻게 계산하는지는 좀 더 찾아봐야 할 듯하다!

 

테스트 시  마주했던 변수들 :

Core Location은 GPS신호를 기반으로 하는 것으로 알고 있는데,

이 신호가 약할 수 있는 조건(예를 들어 깊은 실내 등)에서 speed값이 잘 감지가 되지 않는 경우들이 있었다.

감지가 불가능할 때 -1 값이 뜨는 듯하다.

 

그리고, locationManager가 초기화될 때 즉, 앱을 켰을 때

한번씩 speed값이 튄다. 그래서 키자마자 alert가 뜨는 경우가 종종 발생했다.

이건 차차 고쳐 나가야 겠다.

 


 

참고한 블로그

https://coledennis.medium.com/tutorial-connecting-core-location-to-a-swiftui-app-dc62563bd1de

 

Tutorial: Connecting Core Location to a SwiftUI App

How to connect Apple’s Core Location service to a SwiftUI App

coledennis.medium.com

 

https://medium.com/@ios_guru/core-location-and-cllocationspeed-for-getting-speed-of-the-device-14fd95e6e77c

 

Core Location and CLLocationSpeed for getting speed of the device

Core Location is a powerful framework used in iOS development to get the user’s location data. It is used to determine the user’s current location, altitude, and course. It also provides the ability…

medium.com