맵 뷰로 지도 나타내기

서희찬·2022년 2월 23일
0

swift

목록 보기
1/17
post-thumbnail

맵뷰 어플리케이션을 만들어 보자

스토리보드를 작성하고 아웃렛변수와 액션함수를 짜줬다.

import UIKit
import MapKit

class ViewController: UIViewController {

    @IBOutlet var lblLocationInfo1: UILabel!
    @IBOutlet var lblLocationInfo2: UILabel!
    @IBOutlet var myMap: MKMapView!
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }


    @IBAction func sgChangeLocation(_ sender: UISegmentedControl) {
    }
}

이제 코드를 짜러가자..

지도 보여주기

지도를 보여주기 위해 변수와 델리게이트를 추가하고
앱을 실행하면 지도가 나타나도록 viewDidLoad 함수에 코드를 추가하자

import UIKit
import MapKit

class ViewController: UIViewController, CLLocationManagerDelegate{

    @IBOutlet var lblLocationInfo1: UILabel!
    @IBOutlet var lblLocationInfo2: UILabel!
    @IBOutlet var myMap: MKMapView!
    
    let locationManager = CLLocationManager()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // 우선 위치정보는 공백으로 둔다.
        lblLocationInfo1.text=""
        lblLocationInfo2.text=""
        
        // 델리게이트 셀프로
        locationManager.delegate = self
        
        // 정확도 최고치
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        
        // 위치 데이터 추적을 위해 사용자에게 승인 요구
        locationManager.requestWhenInUseAuthorization()
        
        // 위치 업데이트 시작
        locationManager.startUpdatingLocation()
        
        // 위치 보기 값 true로 설정
        myMap.showsUserLocation = true
    }
    @IBAction func sgChangeLocation(_ sender: UISegmentedControl) {
    }
}

앱이 사용자 위치에 접근하도록 허용하기

info.plist로 들어가 Privacy키를 추가하고 Value를 다음과 같이 준다

위도와 경도로 원하는 위치 표시하기

goLocation 함수

    func goLocation(latitudeValue : CLLocationDegrees, longitudeValue : CLLocationDegrees, delta span :Double){
    
        //CLLocationCoordinate2DMake : 위도와 경도를 매개변수로 하여 함수 호출 후 pLocation값을 return 받는다.
        let pLocation = CLLocationCoordinate2DMake(latitudeValue, longitudeValue)
        
        // 범위값을 매개 변수로 하여 return spanValue
        let spanValue = MKCoordinateSpan(latitudeDelta: span, longitudeDelta: span)
        
        // pLcoation, spanValue -> return pRegion
        let pRegion = MKCoordinateRegion(center: pLocation, span: spanValue)
        
        //pRegion -> call myMap.setRegion function
        myMap.setRegion(pRegion, animated: true)
    }

을 작성 한 후 위치가 업데이트 되었을 시 지도에 위치 나타내기 위한 함수를 통해 위에 짠 함수를 불러주자

    // 위치가 업데이트되었을 때 지도에 위치 나타내는 함수
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        let pLocation = locations.last //마지막 위치 찾기
        
        //마지막 위치의 위도와 경도값을 통해 goLocation호출 delta값은 작을 수록 지도 확대 1->0.01은 100배 확대
        goLocation(latitudeValue: (pLocation?.coordinate.latitude)!, longitudeValue:  (pLocation?.coordinate.longitude)!, delta: 0.01)
    }

그러면

    func goLocation(latitudeValue : CLLocationDegrees, longitudeValue : CLLocationDegrees, delta span :Double){
        //CLLocationCoordinate2DMake : 위도와 경도를 매개변수로 하여 함수 호출 후 pLocation값을 return 받는다.
        let pLocation = CLLocationCoordinate2DMake(latitudeValue, longitudeValue)
        // 범위값을 매개 변수로 하여 return spanValue
        let spanValue = MKCoordinateSpan(latitudeDelta: span, longitudeDelta: span)
        // pLcoation, spanValue -> return pRegion
        let pRegion = MKCoordinateRegion(center: pLocation, span: spanValue)
        //pRegion -> call myMap.setRegion function
        myMap.setRegion(pRegion, animated: true)
    }
    
    // 위치가 업데이트되었을 때 지도에 위치 나타내는 함수
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        let pLocation = locations.last //마지막 위치 찾기
        
        //마지막 위치의 위도와 경도값을 통해 goLocation호출 delta값은 작을 수록 지도 확대 1->0.01은 100배 확대
        goLocation(latitudeValue: (pLocation?.coordinate.latitude)!, longitudeValue:  (pLocation?.coordinate.longitude)!, delta: 0.01)
    }

이러면 원하는 위치를 위도와 경도로 표시할 수 있다.

위치 정보 추출 후 텍스트 표시

위도,경도 값을 가지고
위치정보를 찾아보자 !

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        let pLocation = locations.last //마지막 위치 찾기
        
        //마지막 위치의 위도와 경도값을 통해 goLocation호출 delta값은 작을 수록 지도 확대 1->0.01은 100배 확대
        goLocation(latitudeValue: (pLocation?.coordinate.latitude)!, longitudeValue:  (pLocation?.coordinate.longitude)!, delta: 0.01)
        
        //위도와 경도 값을 가지고 위치정보 찾기
        CLGeocoder().reverseGeocodeLocation(pLocation!, completionHandler: {
            (placemarks,error)->Void in
            let pm = placemarks!.first
            let country = pm!.country
            var adress:String = country!
            
            // pm상수에서 지역 값이 존재한다면 adress 문자열에 추가
            if pm!.locality != nil {
                adress += " "
                adress += pm!.locality!
            }
            
            // pm상수에서 도로 값이 존재한다면 adress문자열에 추가
            if pm!.thoroughfare != nil{
                adress += " "
                adress += pm!.thoroughfare!
            }
            
            self.lblLocationInfo1.text = "현재 위치"
            self.lblLocationInfo2.text = adress
        })
        //마지막 위치 업데이트 중단 
        locationManager.stopUpdatingLocation()
    }

핸들러의 추가함수에 adress는 나라값만 받고
지역,도로가 있다면 추가로 붙여주는 코드이다.

그러고 보면 현재 위치가 샌프라시스코로 되어 있다.

그러면 이제 현재위치를 바꿔보자

시뮬레이터에서 현재 위치 바꾸기

'
이런식으로 features에 들어가서 위도경도를 수정하면된다.

위도와 경도로 원하는 핀 설치하기

핀 설치를 위한 초기화

setAnnotation함수를 만들어준다

    // 핀 설치를 위한 함수
    func setAnnotation(latitudeValue : CLLocationDegrees,longitudeValue : CLLocationDegrees, delta span :Double, title strTitle:String, subtitle strSubtitle:String){
        
        //핀 설치 위해 함수 호출 후 return 값을 annotation에 저장
        let annotation = MKPointAnnotation()
        
        //annotation의 조정값을 goLocation함수로부터 2D형태로 받아야하는데 이를 위해 goLocation함수를 수정해야한다.
        annotation.coordinate = goLocation(latitudeValue: latitudeValue, longitudeValue: longitudeValue, delta: span)
    }
    

그런데 goLocation으로부터 2D값을 받아야하니
goLocation함수를 수정해주자

    func goLocation(latitudeValue : CLLocationDegrees, longitudeValue : CLLocationDegrees, delta span :Double)->CLLocationCoordinate2D{
        //CLLocationCoordinate2DMake : 위도와 경도를 매개변수로 하여 함수 호출 후 pLocation값을 return 받는다.
        let pLocation = CLLocationCoordinate2DMake(latitudeValue, longitudeValue)
        // 범위값을 매개 변수로 하여 return spanValue
        let spanValue = MKCoordinateSpan(latitudeDelta: span, longitudeDelta: span)
        // pLcoation, spanValue -> return pRegion
        let pRegion = MKCoordinateRegion(center: pLocation, span: spanValue)
        //pRegion -> call myMap.setRegion function
        myMap.setRegion(pRegion, animated: true)
        
        //반환
        return pLocation
    }

반환값이 생겼다
그렇기에 locationManger함수도 수정해주자

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
...
        //마지막 위치의 위도와 경도값을 통해 goLocation호출 delta값은 작을 수록 지도 확대 1->0.01은 100배 확대
        // return 값 받는 함수로 변경됐으니 _=추가
        _=goLocation(latitudeValue: (pLocation?.coordinate.latitude)!, longitudeValue:  (pLocation?.coordinate.longitude)!, delta: 0.01)
...

함수 앞에 _=가 붙었다..!

이제 setAnnotation함수를 마무리하자
핀의 타이틀과 서브 타이틀을 입력 파라미터로 이용하여 셋팅 후 맵 뷰에 변수 annotaion값을 추가하자

    func setAnnotation(latitudeValue : CLLocationDegrees,longitudeValue : CLLocationDegrees, delta span :Double, title strTitle:String, subtitle strSubtitle:String){
        
        //핀 설치 위해 함수 호출 후 return 값을 annotation에 저장
        let annotation = MKPointAnnotation()
        
        //annotation의 조정값을 goLocation함수로부터 2D형태로 받아야하는데 이를 위해 goLocation함수를 수정해야한다.
        annotation.coordinate = goLocation(latitudeValue: latitudeValue, longitudeValue: longitudeValue, delta: span)
        
        // annotation 셋팅 후 지도에 전달
        annotation.title = strTitle
        annotation.subtitle = strSubtitle
        myMap.addAnnotation(annotation)
    }

이제 세그먼트 컨트롤의 액션을 수정하자 !
index vlaue
현재위치 : 0
동국대 : 1
DDP : 2 이다.

    @IBAction func sgChangeLocation(_ sender: UISegmentedControl) {
        if sender.selectedSegmentIndex == 0{
            
        }else if sender.selectedSegmentIndex == 1{
            setAnnotation(latitudeValue: 37.5591, longitudeValue: 126.9997, delta: 0.1, title: "동국대학교", subtitle: "서울특별시 중구 필동로1길 30")
            self.lblLocationInfo1.text = "보고 계신 위치"
            self.lblLocationInfo2.text = "동국대학교"
        }else if sender.selectedSegmentIndex == 2{
            setAnnotation(latitudeValue: 37.5676, longitudeValue: 127.0085, delta: 0.1, title: "DDP", subtitle: "서울특별시 중구 을지로7가 을지로 281")
            self.lblLocationInfo1.text = "보고 계신 위치"
            self.lblLocationInfo2.text = "DDP 동대문디자인플라자"
        }
    }

만들어준 setAnnotaion에 위치정보를 전달해주고 텍스트를 변경하는 코드이다.

이렇게 버튼을 누르면 표시가 잘된다.
그러면 이제 현재위치를 표시해보자

현재 위치 표시하기

        if sender.selectedSegmentIndex == 0{
            
            //기존에 작성되어있던 텍스트 삭제
            self.lblLocationInfo1.text = ""
            self.lblLocationInfo2.text = ""
            
            // 다시 원래 위치로
            locationManager.startUpdatingLocation()
            
        }

그러면

짜라랄ㄴ~
현재 위치가 잘 표시된다

전체코드는 아래와 같다

//
//  ViewController.swift
//  Map
//
//  Created by 서희찬 on 2022/02/23.
//

import UIKit
import MapKit

class ViewController: UIViewController, CLLocationManagerDelegate{

    @IBOutlet var lblLocationInfo1: UILabel!
    @IBOutlet var lblLocationInfo2: UILabel!
    @IBOutlet var myMap: MKMapView!
    
    let locationManager = CLLocationManager()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // 우선 위치정보는 공백으로 둔다.
        lblLocationInfo1.text=""
        lblLocationInfo2.text=""
        
        // 델리게이트 셀프로
        locationManager.delegate = self
        
        // 정확도 최고치
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        
        // 위치 데이터 추적을 위해 사용자에게 승인 요구
        locationManager.requestWhenInUseAuthorization()
        
        // 위치 업데이트 시작
        locationManager.startUpdatingLocation()
        
        // 위치 보기 값 true로 설정
        myMap.showsUserLocation = true
    }
    
    func goLocation(latitudeValue : CLLocationDegrees, longitudeValue : CLLocationDegrees, delta span :Double)->CLLocationCoordinate2D{
        //CLLocationCoordinate2DMake : 위도와 경도를 매개변수로 하여 함수 호출 후 pLocation값을 return 받는다.
        let pLocation = CLLocationCoordinate2DMake(latitudeValue, longitudeValue)
        // 범위값을 매개 변수로 하여 return spanValue
        let spanValue = MKCoordinateSpan(latitudeDelta: span, longitudeDelta: span)
        // pLcoation, spanValue -> return pRegion
        let pRegion = MKCoordinateRegion(center: pLocation, span: spanValue)
        //pRegion -> call myMap.setRegion function
        myMap.setRegion(pRegion, animated: true)
        
        //반환
        return pLocation
    }
    
    // 핀 설치를 위한 함수
    func setAnnotation(latitudeValue : CLLocationDegrees,longitudeValue : CLLocationDegrees, delta span :Double, title strTitle:String, subtitle strSubtitle:String){
        
        //핀 설치 위해 함수 호출 후 return 값을 annotation에 저장
        let annotation = MKPointAnnotation()
        
        //annotation의 조정값을 goLocation함수로부터 2D형태로 받아야하는데 이를 위해 goLocation함수를 수정해야한다.
        annotation.coordinate = goLocation(latitudeValue: latitudeValue, longitudeValue: longitudeValue, delta: span)
        
        // annotation 셋팅 후 지도에 전달
        annotation.title = strTitle
        annotation.subtitle = strSubtitle
        myMap.addAnnotation(annotation)
    }
    
    // 위치가 업데이트되었을 때 지도에 위치 나타내는 함수
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        let pLocation = locations.last //마지막 위치 찾기
        
        //마지막 위치의 위도와 경도값을 통해 goLocation호출 delta값은 작을 수록 지도 확대 1->0.01은 100배 확대
        // return 값 받는 함수로 변경됐으니 _=추가
        _=goLocation(latitudeValue: (pLocation?.coordinate.latitude)!, longitudeValue:  (pLocation?.coordinate.longitude)!, delta: 0.01)
        
        //위도와 경도 값을 가지고 위치정보 찾기
        CLGeocoder().reverseGeocodeLocation(pLocation!, completionHandler: {
            (placemarks,error)->Void in
            let pm = placemarks!.first
            let country = pm!.country
            var adress:String = country!
            
            // pm상수에서 지역 값이 존재한다면 adress 문자열에 추가
            if pm!.locality != nil {
                adress += " "
                adress += pm!.locality!
            }
            
            // pm상수에서 도로 값이 존재한다면 adress문자열에 추가
            if pm!.thoroughfare != nil{
                adress += " "
                adress += pm!.thoroughfare!
            }
            
            self.lblLocationInfo1.text = "현재 위치"
            self.lblLocationInfo2.text = adress
        })
        //마지막 위치 업데이트 중단
        locationManager.stopUpdatingLocation()
    }
    
    @IBAction func sgChangeLocation(_ sender: UISegmentedControl) {
        if sender.selectedSegmentIndex == 0{
            
            //기존에 작성되어있던 텍스트 삭제
            self.lblLocationInfo1.text = ""
            self.lblLocationInfo2.text = ""
            
            // 다시 원래 위치로
            locationManager.startUpdatingLocation()
            
        }else if sender.selectedSegmentIndex == 1{
            setAnnotation(latitudeValue: 37.5591, longitudeValue: 126.9997, delta: 0.1, title: "동국대학교", subtitle: "서울특별시 중구 필동로1길 30")
            self.lblLocationInfo1.text = "보고 계신 위치"
            self.lblLocationInfo2.text = "동국대학교"
        }else if sender.selectedSegmentIndex == 2{
            setAnnotation(latitudeValue: 37.5676, longitudeValue: 127.0085, delta: 0.1, title: "DDP", subtitle: "서울특별시 중구 을지로7가 을지로 281")
            self.lblLocationInfo1.text = "보고 계신 위치"
            self.lblLocationInfo2.text = "DDP 동대문디자인플라자"
        }
    }
}
profile
부족한 실력을 엉덩이 힘으로 채워나가는 개발자 서희찬입니다 :)

0개의 댓글