카카오맵 공식문서 그대로 복붙하면 맵이 생성이 안돼서 생성된 기본 코드를 공유/저장...
label이나 다른 레이어 처리할거면 addViewSucceeded 메서드 뒤에 넣으면 된다.
import CoreLocation
import UIKit
import KakaoMapsSDK
import SnapKit
class ViewController: UIViewController, MapControllerDelegate {
var mapContainer: KMViewContainer?
var mapController: KMController?
override func viewDidLoad() {
super.viewDidLoad()
mapContainer = KMViewContainer()
view.addSubview(mapContainer!)
mapContainer?.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
mapController = KMController(viewContainer: mapContainer!)
mapController?.delegate = self
}
deinit {
mapController?.pauseEngine()
mapController?.resetEngine()
print("deinit")
}
override func viewWillAppear(_ animated: Bool) {
addObservers()
if mapController?.isEnginePrepared == false {
mapController?.prepareEngine()
}
if mapController?.isEngineActive == false {
mapController?.activateEngine()
}
}
override func viewWillDisappear(_ animated: Bool) {
mapController?.pauseEngine() //렌더링 중지.
}
override func viewDidDisappear(_ animated: Bool) {
removeObservers()
mapController?.resetEngine() //엔진 정지. 추가되었던 ViewBase들이 삭제된다.
}
func authenticationSucceeded() {
mapController?.activateEngine()
}
// 인증 실패시 호출.
func authenticationFailed(_ errorCode: Int, desc: String) {
print("error code: \(errorCode)")
print("desc: \(desc)")
switch errorCode {
case 400:
showToast(self.view, message: "지도 종료(API인증 파라미터 오류)")
break;
case 401:
showToast(self.view, message: "지도 종료(API인증 키 오류)")
break;
case 403:
showToast(self.view, message: "지도 종료(API인증 권한 오류)")
break;
case 429:
showToast(self.view, message: "지도 종료(API 사용쿼터 초과)")
break;
case 499:
showToast(self.view, message: "지도 종료(네트워크 오류) 5초 후 재시도..")
// 인증 실패 delegate 호출 이후 5초뒤에 재인증 시도..
DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
print("retry auth...")
self.mapController?.prepareEngine()
}
break;
default:
break;
}
}
func addViews() {
//여기에서 그릴 View(KakaoMap, Roadview)들을 추가한다.
let defaultPosition: MapPoint = MapPoint(longitude: 127.108678, latitude: 37.402001)
//지도(KakaoMap)를 그리기 위한 viewInfo를 생성
let mapviewInfo: MapviewInfo = MapviewInfo(viewName: "mapview", viewInfoName: "map", defaultPosition: defaultPosition, defaultLevel: 7)
//KakaoMap 추가.
mapController?.addView(mapviewInfo)
}
func addViewSucceeded(_ viewName: String, viewInfoName: String) {
print("OK")
let view = mapController?.getView("mapview") as! KakaoMap
view.viewRect = mapContainer!.bounds
}
//addView 실패 이벤트 delegate. 실패에 대한 오류 처리를 진행한다.
func addViewFailed(_ viewName: String, viewInfoName: String) {
print("Failed")
}
//Container 뷰가 리사이즈 되었을때 호출된다. 변경된 크기에 맞게 ViewBase들의 크기를 조절할 필요가 있는 경우 여기에서 수행한다.
func containerDidResized(_ size: CGSize) {
let mapView: KakaoMap? = mapController?.getView("mapview") as? KakaoMap
mapView?.viewRect = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: size) //지도뷰의 크기를 리사이즈된 크기로 지정한다.
}
func addObservers(){
NotificationCenter.default.addObserver(self, selector: #selector(willResignActive), name: UIApplication.willResignActiveNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(didBecomeActive), name: UIApplication.didBecomeActiveNotification, object: nil)
}
func removeObservers(){
NotificationCenter.default.removeObserver(self, name: UIApplication.willResignActiveNotification, object: nil)
NotificationCenter.default.removeObserver(self, name: UIApplication.didBecomeActiveNotification, object: nil)
}
@objc func willResignActive(){
mapController?.pauseEngine() //뷰가 inactive 상태로 전환되는 경우 렌더링 중인 경우 렌더링을 중단.
}
@objc func didBecomeActive(){
mapController?.activateEngine()//뷰가 active 상태가 되면 렌더링 시작. 엔진은 미리 시작된 상태여야 함.
}
func showToast(_ view: UIView, message: String, duration: TimeInterval = 2.0) {
let toastLabel = UILabel(frame: CGRect(x: view.frame.size.width/2 - 150, y: view.frame.size.height-100, width: 300, height: 35))
toastLabel.backgroundColor = UIColor.black
toastLabel.textColor = UIColor.white
toastLabel.textAlignment = NSTextAlignment.center;
view.addSubview(toastLabel)
toastLabel.text = message
toastLabel.alpha = 1.0
toastLabel.layer.cornerRadius = 10;
toastLabel.clipsToBounds = true
UIView.animate(withDuration: 0.4,
delay: duration - 0.4,
options: UIView.AnimationOptions.curveEaseOut,
animations: {
toastLabel.alpha = 0.0
},
completion: { (finished) in
toastLabel.removeFromSuperview()
})
}
}
공식문서에서 addViewSucceeded 메서드 안에 view.viewRect 설정하는 부분이 없었는데, 저거 설정해주니까 기본 맵이 떴음
지피티한테 물어보니까,view.viewRect
는 지도 뷰(KakaoMap
)의 렌더링 영역을 설정하는 속성으로, 지도가 화면에서 어느 영역에 그려질지를 결정하는 사각형(Rect)을 정의한다고 한다.
이하는 지피티의 답변 복붙한 내용
viewRect
의 역할viewRect
는 KakaoMap
객체가 화면에 표시될 좌표(x, y)와 크기(width, height)를 설정하는 속성으로, 지도의 렌더링 영역을 정밀하게 제어할 수 있어.
예를 들어:
viewRect = CGRect(x: 0, y: 0, width: 300, height: 400)
→ 지도는 화면의 왼쪽 위에서 시작하여 너비 300, 높이 400만큼만 표시.viewRect = mapContainer!.bounds
→ mapContainer
의 크기와 위치를 기준으로 지도 영역을 설정.초기 설정 문제 해결:
addViews()
호출 이후, 맵 뷰의 렌더링 영역이 명시되지 않으면 지도가 화면에 표시되지 않을 수 있음.viewRect
를 설정해줘야 Kakao Maps SDK가 지도 타일을 올바르게 로드하고 화면에 그리도록 작동.뷰의 크기 조정:
mapContainer
의 크기와 위치가 변경되면, 지도 영역도 이에 맞게 업데이트해야 함.viewRect
를 mapContainer.bounds
로 설정하여 자동으로 크기와 위치를 동기화.다중 뷰 지원:
viewRect
를 설정하여 원하는 영역에 표시할 수 있음.viewRect
가 설정되지 않으면 지도는 기본적으로 (0, 0)에서 크기 (0, 0)으로 초기화되어, 화면에 아무것도 그려지지 않을 수 있어.mapContainer.bounds
를 기반으로 viewRect
를 설정하면, mapContainer
의 크기와 동일한 지도 렌더링 영역이 설정되어 맵이 제대로 보이게 된 거야.containerDidResized
에서 viewRect
를 재설정하도록 처리:func containerDidResized(_ size: CGSize) {
let mapView = mapController?.getView("mapview") as? KakaoMap
mapView?.viewRect = CGRect(origin: .zero, size: size)
}
이렇게 하면 화면 회전이나 크기 변경에도 지도 크기가 올바르게 조정돼.
기가막히네요