Machineboy空
CoreLocation speed를 이용해 현재 정지해 있는 상태인지 파악해보자! 본문
현재 걷고 있는지, 정지해있는지를 파악하고 싶다.

피크민 꽃 심기 모드 중에 운전을 하거나, 버스를 타면 운전중은 아닌지 물어보는 알림이 뜨는데,
캡쳐를 해두지 못해 햄버거 피크민을 첨부한다.
아무튼 기기의 움직임을 감지하는 기능을 구현하고자 한다.
시도한 방법 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
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
'언어 > iOS' 카테고리의 다른 글
비컨별로 다른 화면 띄우기! (0) | 2024.11.01 |
---|---|
아이폰 2대 간 거리 탐지하기, iBeacon (6) | 2024.10.31 |
iBeacon이란? beacon과 iOS 디바이스 간 거리 감지! (3) | 2024.10.29 |
RealityKit 입문 - 한국에선 불가한 ARGeoAnchor (2) | 2024.10.15 |
Realitykit 입문 - Persistence (0) | 2024.10.15 |