Day 75 - Core Location, CLBeaconRegion

sun02·2021년 12월 10일
0

100 days of Swift 

목록 보기
38/40

CLBeaconRegion이란?
iBeacon 기기의 존재를 감지하는 데 사용되는 영역입니다.

자세히 - Apple document

사용자의 위치정보는 민감한 정보이므로 Apple은 다음을 지정해놓았습니다.

  • Always access를 요청하였더라도, 사용자는 When In Use를 선택할 수 있다.
  • 사용자가 Always access를 선택하였더라도, 몇일 후 iOS는 자동으로 여전히 Always access 상태를 유지하고 싶은지 사용자에게 물어본다.
  • 앱이 위치데이터를 백그라운드에서 사용하는 경우 iOS UI는 사용자가 이것을 알 수 있도록 업데이트 한다.
  • 사용자는 언제든지 Always access에서 When In Use로 변경할 수 있다.

앱이 비콘을 백그라운드에서 감지할 수 있도록 Always access를 요청할 것이지만, 위의 규칙들 때문에 info.plist에 아래의 두 가지를 모두 추가해 줍니다.

  • Privacy - Location Always and When In Use Usage Description
  • Privacy - Location When In Use Usage Description

1. CoreLocation settings

import CoreLocation
  • 위치 정보를 받아오기 위해 가장 먼저 CoreLocation framwork를 추가해 줍니다.
var locationManager : CLLocationManager?
  • CLLocationManager : 위치 정보를 받을 방법과 위치 정보를 업데이트하는 CoreLocation의 핵심 클래스

위와 같은 과정이 실제로 locationManager를 생성하지는 않습니다.

class ViewController: UIViewController, CLLocationManagerDelegate {

}
  • 다음과 같이 CLLocationManagerDelegate 프로토콜을 ViewController가 준수하도록 하고
override func viewDidLoad() {
	super.viewDidLoad()
    
    locationManager = CLLocationManager()
    locationManager?.delegate = self
    locationManager?.requestAlwaysAuthorization()
 }   
  • CLLocationManager 객체를 생성해주고, locationManager의 delegate를 self(viewController)로 지정해 줍니다.
  • requestAlwaysAuthorization()을 호출하여 사용자에게 위치 권한을 요청합니다.
    • 만약 info.plist에서 when In use를 사용하였다면, requestWhenInUseAuthorization()을 호출해야합니다.

CLLocationManager() 객체에 대한 대리자로 뷰컨트롤러를 설정했기 때문에, 사용자의 응답을 뷰컨트롤러가 알 수 있고 아래의 메서드가 호출됩니다.

func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
    if status == .authorizedAlways {
        if CLLocationManager.isMonitoringAvailable(for: CLBeaconRegion.self) {
            if CLLocationManager.isRangingAvailable() {
                // do stuff
            }
        }
    }
}
  • status == .authorizedAlways : 사용자에게 허가를 받았는가?
  • isMonitoringAvailable : 기기가 iBeacon을 모니터링할 수 있는가?
  • isRangingAvailable: 범위(기기에서 대략적으로 얼마나 떨어져 있는지)를 사용할 수 있는가?

2. CLBeaconRegion

Core Location 세팅이 끝났다면, 다음을 사용하여 비콘의 범위를 지정할 수 있습니다.
CLBeaconRegion의 실행을 위해서는 시뮬레이터가 아닌 실제 기기를 사용해야하고, 기기에 locate beacon 앱을 설치해야합니다.

  • CLBeaconRegion : 비컨을 고유하게 식별하는데 사용되는 클래스
  • startMonitoring(for:) & startRangingBeacons(in:)
    • CLLocationManager 개체에 전달함

비콘은 아래의 세 가지 정보를 사용하여 식별됩니다.

  • UUID (ex 슈퍼마켓)
  • major number : UUID 내에서 세분화하는데 사용 (ex 슈퍼마켓의 12층)
  • minor number : major number내에서 세분화하는데 사용 (ex 슈퍼마켓의 12층의 각 상점)
func startScanning() {
	let uuid = UUID(uuidString: "5A4BCFCE-174E-4BAC-A814-092E77F6B7E5")!
    let beaconRegion = CLBeaconRegion(proximityUUID: uuid, major: 123, minor: 456, identifier: "MyBeacon")
    
    locationManager?.startMonitoring(for: beaconRegion)
    locationManager?.startRangingBeacons(in: beaconRegion)
}
  • locate beacon 앱의 "Apple AirLocate 5A4BCFCE" 에서 major와 minor 번호를 입력해줍니다.
  • uuid, major, minor를 입력한 CLBeaconRegion 클래스를 locationManager에 전송하여
    • startMonitoring :해당 지역의 존재를 모니터링하고
    • startRangingBeacons: 기기와 비콘 사이의 거리 측정을 하도록 요청합니다.

위의 didChangeAuthorization //do stuff아래에 startScanning()메서드를 추가하여
사용자가 허가하고, 기기가 비콘을 모니터링 할 수 있는 경우 실행하도록 합니다.

3. Update UI

비콘과의 근접성을 반영하여 UI가 변경될 수 있도록 해줍니다.

func locationManager(_ manager: CLLocationManager, didRangeBeacons beacons: [CLBeacon], in region: CLBeaconRegion) {
    if let beacon = beacons.first {
        update(distance: beacon.proximity)
    } else {
        update(distance: .unknown)
    }
}
  • 위 메서드에서 비콘 배열을 받아 첫 번째 비콘을 꺼내고, proximity 프로퍼티를 사용하여 update 메서드를 호출합니다.
func update(distance: CLProximity) {
	UIVIew.animate(withDuration: 0.8) {
    	switch distance {
        case .far:
        	self.view.backgroundColor = UIColor.gray
            self.distanceReading.text = "FAR"
        case .near:
        	self.view.backgroundColor = UIColor.blue
            self.distanceReading.text = "NEAR"
        case .immediate:
        	self.view.backgroundColor = UIColor.orange
            self.distanceReading.text = "RIGHT HERE"
        default:
        	self.view.backgroundColor = UIColor.gray
            self.distanceReading.text = "UNKNOWN"
        }
    }
}
  • 전달받은 proximity 를 사용해서 근접한 거리에 따라 view의 배경색과 distanceReading label의 텍스트를 변경해줍니다.

0개의 댓글