ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [iOS] API 통신 및 지도 Marker 분리
    ToyProject 2023. 9. 28. 16:00

    <결과물 먼저 보여주면, 아래와 같이 위치에 맞게 마커를 뿌려주고, 마커를 클릭하면 해당 음식점에 대한 정보가 보이도록 구현했다!>

    음식점 종류에 맞게 Marker 이미지를 분리해서 지도에 표시해보았다! 

    1. 내위치 Marker

    : 내 위치 마커는 현재 위치를 보여주는 마커로, 상단에 "내 위치 재검색" 버튼을 누르면 현재 위치로 돌아가서 마커가 보일 수 있도록 해주었다!

    // 내 위치 마커
            let my_marker = NMFMarker()
            
            // 마커 위치
            my_marker.position = NMGLatLng(lat:latitude,lng: longitude)
            
            // 마커 이미지
            my_marker.iconImage = NMFOverlayImage(name: "me")
    
            // 마커 크기
            my_marker.width = 60
            my_marker.height = 60
            
            // 타입 이미지
            self.typeImage.image = UIImage(named: "me")
            
            // 이름 텍스트
            self.nameText.text = "현재 위치"
    
            // 마커 캡션
            my_marker.captionText = "내 위치"
            my_marker.captionOffset = 5
            my_marker.captionColor = UIColor.black
    
            my_marker.touchHandler = { (overlay: NMFOverlay) -> Bool in
                if self.addressView.isHidden {
                    my_marker.width = 60
                    my_marker.height = 60
                    self.typeImage.image = UIImage(named: "me")
    
                    self.nameText.text = "현재 위치"
    
                    my_marker.captionText = "내 위치"
                    my_marker.captionOffset = 5
                    my_marker.captionColor = UIColor.black
                    self.addressView.isHidden = false
                    return true // 이벤트 소비, -mapView:didTapMap:point 이벤트는 발생하지 않음
                } else {
                    my_marker.width = 50
                    my_marker.height = 50
                     self.addressView.isHidden = true
    
                    my_marker.captionText = ""
                    return false // 이벤트 넘겨줌, -mapView:didTapMap:point 이벤트가 발생할 수 있음
                }
            }

    : 마커를 클릭하면 "내 위치"라는 text가 하단에 나오고, 다시 지도를 클릭하게 되면 사라지도록 해두었다!

     

    2. API 통신 및 Marker 분리

    : URLSession을 이용해서 통신했으며, 통신이 정상적으로 되었다면, 미리 만들어둔 data Model에 데이터를 담아서 type에 따라 marker 이미지와 text를 분류했다! 

     

    → 데이터 구조가 잡기 어렵다면? (아래 블로그 참고)

    https://app.quicktype.io/

     

    Instantly parse JSON in any language | quicktype

     

    app.quicktype.io

    // MARK: - DataModelElement
    struct DataModelElement: Codable {
        let id: Int
        let name: String
        let type: String
        let latitude, longitude: Double
        let address: String
    }
    
    typealias DataModel = [DataModelElement]

    이미지는 Asset 파일에 미리 저장해두었다!

    // API 통신 (localhost)
            guard let url = URL(string: "http://localhost:8080/main") else {
                print("Invalid URL")
                return
            }
    
            let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
                if let error = error {
                    print("Error: \(error.localizedDescription)")
                    return
                }
    
                guard let httpResponse = response as? HTTPURLResponse else {
                    print("Invalid HTTP response")
                    return
                }
    
                if httpResponse.statusCode == 200 {
                    if let data = data {
                        do {
                            let decoder = JSONDecoder()
                            
                            // dataModel에 받아온 정보 담기
                            let dataModel = try decoder.decode([DataModelElement].self, from: data)
    
                            // 비동기 처리
                            DispatchQueue.main.async {
                                for dataElement in dataModel {
                                    // 마커 생성
                                    let new_marker = NMFMarker()
    
                                    // 마커 위치
                                    new_marker.position = NMGLatLng(lat: dataElement.latitude, lng: dataElement.longitude)
    
                                    // 업태 분류
                                    if(dataElement.type == "한식") {
                                        new_marker.iconImage = NMFOverlayImage(name: "rice")
                                    }
                                    else if(dataElement.type == "분식") {
                                        new_marker.iconImage = NMFOverlayImage(name: "tteokbokki")
                                    }
                                    else if(dataElement.type == "커피숍") {
                                        new_marker.iconImage = NMFOverlayImage(name: "coffee")
                                    }
                                    else if(dataElement.type == "제과영업점") {
                                        new_marker.iconImage = NMFOverlayImage(name: "bread")
                                    }
                                    else if(dataElement.type == "경양식") {
                                        new_marker.iconImage = NMFOverlayImage(name: "tonkatsu")
                                    }
                                    else if(dataElement.type == "호프/통닭") {
                                        new_marker.iconImage = NMFOverlayImage(name: "chicken")
                                    }
                                    else if(dataElement.type == "패밀리 레스토랑") {
                                        new_marker.iconImage = NMFOverlayImage(name: "restaurant")
                                    }
                                    else if(dataElement.type == "중국식") {
                                        new_marker.iconImage = NMFOverlayImage(name: "jjajangmyeon")
                                    }
                                    else if(dataElement.type == "패스트푸드") {
                                        new_marker.iconImage = NMFOverlayImage(name: "hamburger")
                                    }
                                    else if(dataElement.type == "일식") {
                                        new_marker.iconImage = NMFOverlayImage(name: "sushi")
                                    }
    
                                    new_marker.width = 40
                                    new_marker.height = 40
    
                                    new_marker.touchHandler = { (overlay: NMFOverlay) -> Bool in
                                        if self.addressView.isHidden {
                                            if(dataElement.type == "한식") {
                                                self.typeImage.image = UIImage(named: "rice")
                                            }
                                            else if(dataElement.type == "분식") {
                                                self.typeImage.image = UIImage(named: "tteokbokki")
                                            }
                                            else if(dataElement.type == "커피숍") {
                                                self.typeImage.image = UIImage(named: "coffee")
    
                                            }
                                            else if(dataElement.type == "제과영업점") {
                                                self.typeImage.image = UIImage(named: "bread")
    
                                            }
                                            else if(dataElement.type == "경양식") {
                                                self.typeImage.image = UIImage(named: "tonkatsu")
    
                                            }
                                            else if(dataElement.type == "호프/통닭") {
                                                self.typeImage.image = UIImage(named: "chicken")
    
                                            }
                                            else if(dataElement.type == "패밀리 레스토랑") {
                                                self.typeImage.image = UIImage(named: "restaurant")
    
                                            }
                                            else if(dataElement.type == "중국식") {
                                                self.typeImage.image = UIImage(named: "jjajangmyeon")
    
                                            }
                                            else if(dataElement.type == "패스트푸드") {
                                                self.typeImage.image = UIImage(named: "hamburger")
    
                                            }
                                            else if(dataElement.type == "일식") {
                                                self.typeImage.image = UIImage(named: "sushi")
    
                                            }
    
                                            new_marker.width = 50
                                            new_marker.height = 50
    
                                            self.addressText.text = dataElement.address
                                            self.nameText.text = dataElement.name
    
                                            new_marker.captionText = dataElement.name
                                            new_marker.captionOffset = 5
                                            new_marker.captionColor = UIColor.black
                                            self.addressView.isHidden = false
                                            return true // 이벤트 소비, -mapView:didTapMap:point 이벤트는 발생하지 않음
                                        } else {
                                            if(dataElement.type == "한식") {
                                                self.typeImage.image = UIImage(named: "rice")
                                            }
                                            else if(dataElement.type == "분식") {
                                                self.typeImage.image = UIImage(named: "tteokbokki")
                                            }
                                            else if(dataElement.type == "커피숍") {
                                                self.typeImage.image = UIImage(named: "coffee")
                                            }
                                            else if(dataElement.type == "제과영업점") {
                                                self.typeImage.image = UIImage(named: "bread")
                                            }
                                            else if(dataElement.type == "경양식") {
                                                self.typeImage.image = UIImage(named: "tonkatsu")
                                            }
                                            else if(dataElement.type == "호프/통닭") {
                                                self.typeImage.image = UIImage(named: "chicken")
                                            }
                                            else if(dataElement.type == "패밀리 레스토랑") {
                                                self.typeImage.image = UIImage(named: "restaurant")
                                            }
                                            else if(dataElement.type == "중국식") {
                                                self.typeImage.image = UIImage(named: "jjajangmyeon")
                                            }
                                            else if(dataElement.type == "패스트푸드") {
                                                self.typeImage.image = UIImage(named: "hamburger")
                                            }
                                            else if(dataElement.type == "일식") {
                                                self.typeImage.image = UIImage(named: "sushi")
                                            }
                                            new_marker.width = 40
                                            new_marker.height = 40
                                            self.addressView.isHidden = true
    
                                            new_marker.captionText = ""
                                            return false // 이벤트 넘겨줌, -mapView:didTapMap:point 이벤트가 발생할 수 있음
                                        }
                                    }
    
                                    new_marker.mapView = mapView
                                }
                            }
                        } catch {
                            print("Error decoding data: \(error.localizedDescription)")
                        }
                    } else {
                        print("No data received")
                    }
    
                } else {
                    print("HTTP status code: \(httpResponse.statusCode)")
                }
            }
    
            task.resume()
    
            print(latitude)
            print(longitude)
    
            // Do any additional setup after loading the view.
        }

     

Designed by Tistory.