순진이의 하루/study정리

15. MapKit2_2022.09.26 (1)

순진이 2022. 9. 26. 18:11

MapKit 1

※ 프로젝트 이름을 framework와 동일하게 지으면 안됨

※ 예를들어 MapKit이라고 이름 지으면 안됨

 

기본 코드 설정

더보기
import MapKit
class ViewController: UIViewController {

    private let mapView = MKMapView()
    private let mapButton = UIButton(type: .system)    

    override func viewDidLoad() {
        super.viewDidLoad()
        setUI()
    }
    
    @objc func buttonTapped(_ sender: UIButton) {
        print(#function)
    }    
}

extension ViewController {
    private func setUI() {
        mapButton.setTitle("Map Button", for: .normal)
        mapButton.addTarget(self, action: #selector(buttonTapped(_:)), for: .touchUpInside)
        
        [mapView, mapButton].forEach {
            view.addSubview($0)
            $0.translatesAutoresizingMaskIntoConstraints = false
        }
        
        NSLayoutConstraint.activate([
            mapView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            mapView.topAnchor.constraint(equalTo: view.topAnchor),
            mapView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            mapView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
            
            mapButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            mapButton.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -60)
        ])
    }
}

참고

mapView를 ViewController 전체로 설정

더보기

1. mapView의 크기를 view의 frame과 동일하게 만들기

import MapKit

class ViewController: UIViewController {

    private let mapView = MKMapView()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        mapView.frame = view.frame
    }
    
}

2. loadView할 때 view를 교체하기

import MapKit

class ViewController: UIViewController {

    private let mapView = MKMapView()
    
    override func loadView() {
        super.loadView()
        view = mapView
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        
    }
    
}

 

 


 

사용자의 위치 보기

1. CoreLocation을 import

 

2. CLLocationManager의 객체 만들기

 

3. 사용자 위치 받기 권한 처리 requestLocationAuthorization()

 

 

import UIKit
import MapKit
import CoreLocation // 1. import하기

class ViewController: UIViewController {
    
    // 2. CLLocationManager 객체 찍기
    private let locationManager = CLLocationManager()
    private let mapView = MKMapView()
    private let mapButton = UIButton(type: .system)

    override func viewDidLoad() {
        super.viewDidLoad()
        setUI()
        requestLocationAuthorization()
    }

    @objc func buttonTapped(_ sender: UIButton) {
        print(#function)
    }
}

// 3. 사용자 위치 요청하기
extension ViewController {
    private func requestLocationAuthorization() {
        let status = locationManager.authorizationStatus
        
        // 권한 요청
        switch status {
        case .notDetermined:
            locationManager.requestWhenInUseAuthorization()
        case .restricted:
            break
        case .denied:
            break
        case .authorizedAlways, .authorizedWhenInUse, .authorized:
            // 위치 권한이 허용된 경우 한꺼번에 처리
        @unknown default:
            // 추가된 새로운 케이스는 나중에 처리할게!! 나중에 추가된 케이스는 여기로 빠지게 됨
            break
        }
    }
 }
 
 //UI는 이후 생략

 

 

-requestWhenInUseAuthorization : 앱을 사용할 때만(=포그라운드) 사용자 위치 정보 사용

-requestAlwaysAuthorization : 앱을 사용하지 않을 때(=백그라운드 상태)도 사용자의 위치 정보 사용

참고 : https://dev.classmethod.jp/articles/ios-location-approval-kr/

 

 

 

4. info.plist 설정

Key : Privacy - Location When In Usage Description 

Value : 위치 허용을 받을 때 나올 메시지 작성

 

5. CLLocationManager의 delegate를 이용해 위치 받기

- delegate = self 선언

locationManager.delegate = self

- 위치 사용 권한이 허용인 경우만 locationManager에게 위치 요청 && 

extension ViewController {
    private func requestLocationAuthorization() {
        let status = locationManager.authorizationStatus
        
        switch status {
        case .notDetermined:
            locationManager.requestWhenInUseAuthorization()
        case .restricted:
            break
        case .denied:
            break
            
        case .authorizedAlways, .authorizedWhenInUse, .authorized:
            // ⭐️위치 권한이 허용된 경우 -> ⭐️ 사용자의 위치 요청
            locationManager.requestLocation()
            // ⭐️위치 권한이 허용된 경우 -> ⭐️ 사용자의 위치 보이기
            mapView.showsUserLocation = true
        @unknown default:
            // 추가된 새로운 케이스는 나중에 처리할게!! 나중에 추가된 케이스는 여기로 빠지게 됨
            break
        }
    }
 }

- delegate method 구현 (didUpdateLocations메서는 반드시 실패 부분도 구현해줘야 함)

extension ViewController: CLLocationManagerDelegate {
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        print(locations)
    }
    
    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
        print(error)
    }
    
    // 위치 권한 허용 여부가 변경됐을 때 호출되는 메서드
    func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
        requestLocationAuthorization()
    }
}

- 여기까지 하면 사용자의 위치가 뜸 (시뮬레이터라 Apple 위치로 뜸)

 

 

 

6. protocol을 이용해 위치 모델 만들기

import CoreLocation
import Foundation

protocol LocationRepresentable {
    var name: String { get set }
    var latitude: CLLocationDegrees { get set }
    var longitude: CLLocationDegrees { get set }
}

struct Stadium: LocationRepresentable {
    static let stadium = [
        Stadium(name: "Emirates Stadium", latitude: 51.5549,longitude: -0.108436),
        Stadium(name: "Stanford Bridge", latitude: 51.4816,longitude: -0.191034),
        Stadium(name: "White Hard Lane", latitude: 51.6033,longitude: -0.065684),
        Stadium(name: "Olympic Stadium", latitude: 51.5383,longitude: -0.016587),
        Stadium(name: "Old Tranfford", latitude: 53.4631,longitude: -2.29139),
        Stadium(name: "Anfield", latitude: 53.4308, longitude: -2.96096)
    ]
    
    var name: String
    var latitude: CLLocationDegrees
    var longitude: CLLocationDegrees
}