Swift 다 중 맵 원본 업무 기반 맵 컨트롤 구현 (2): 사용자 정의 UI 표시
제 사용자 정의 로 그림 외 에 도 보 여 드릴 정보 가 있 기 때문에 데이터 구조 로 표 시 된 정 보 를 표시 합 니 다.
public enum MeshAnnotationType {
case homePoint
}
public class MeshMapAnnotation {
public var type: MeshAnnotationType
init(type: MeshAnnotationType) {
self.type = type
}
}
간단 한 레이 블 스타일 이기 때문에 View 의 실현 도 간단 합 니 다.
class MeshAnnotaionView: UIView {
private(set) var annotion: MeshMapAnnotation
private(set) var imageView = UIImageView(image: nil)
init(annotion: MeshMapAnnotation) {
self.annotion = annotion
super.init(frame: CGRect.zero)
addSubview(imageView)
setupUI()
}
private func setupUI() {
switch type {
case .homePoint:
imageView.image = Asset.Map.iconMapHomepoint.image
imageView.frame = CGRect(x: 0, y: 0, width: 32, height: 32)
bounds = imageView.frame
default:
break
}
}
}
이곳 의 스타일 은 간단 한 icon 입 니 다.표 시 된 스타일 은 여기 서 설명 하지 않 겠 습 니 다. (중점 이 아 닙 니 다) 어쨌든 자신 이 하나의 View 를 실현 한 것 입 니 다.다음 단 계 는 사용자 정의 UI 를 관리 하기 위해 사용자 정의 MapOverlayView 를 정의 합 니 다.
class CustomMapOverlayView: UIView {
private var homePointAnnotationView: MeshAnnotaionView?
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = UIColor.clear
isUserInteractionEnabled = false
}
func updateHomePoint(_ point: CGPoint?) {
if let point = point {
if homePointAnnotationView == nil {
let annotation = MeshMapAnnotation(type: .homePoint)
homePointAnnotationView = MeshAnnotaionView(annotion: annotation)
addSubview(homePointAnnotationView!)
}
homePointAnnotationView?.center = point
} else {
homePointAnnotationView?.removeFromSuperview()
}
}
}
Custom MapOverlayView 의 디 테 일 은 isUser InteractionEnabled 를 false 로 설정 해 야 합 니 다. 이 층 은 지도 원본 상단 에 덮 여 있 기 때문에 대화 이벤트 에 도 응답 하면 사용 자 는 지 도 를 드래그 하고 크기 를 조정 할 수 없습니다.이 View 에 표 시 된 사용자 정의 관 리 는 각자 의 업무 장면 에 달 려 있다.내 가 있 는 지도 에는 몇 가지 유형 이 표시 되 어 있 기 때문에 선택 할 수 있 는 속성 으로 직접 정의 되 었 다.상부 에 더 큰 유연성 을 주 려 면 사전 으로 저장 할 수도 있다.
현재 이 구조 에서 우리 의 사용자 정의 표 시 는 지도 에서 벗 어 나 단독으로 테스트 할 수 있다.테스트 항목 에서 CustomMapOverlayView 를 직접 초기 화하 고 updateHomePoint 를 호출 하면 homepointView 를 렌 더 링 할 수 있 습 니 다.UI 요 소 를 사용자 정의 하면 유닛 테스트 를 잘 지원 할 수 있 습 니 다.이것 도 디자인 할 때 한 가 지 를 고려 하여 모든 단원 이 가능 한 한 안 으로 모여 야 한다.외부 와 데이터 연결 을 통 해 자신의 논 리 를 독립 적 으로 실행 할 수 있 습 니 다.이렇게 하면 마지막 전체적인 구 조 는 각 작은 단원 이 연결 되 는 것 이지 한 무더기 의 단원 이 직접 용접 되 어 죽 는 것 이 아니다.
다음은 사용자 정의 MapOverlayView 를 지도 컨트롤 에 통합 합 니 다.
public class MeshMapView: UIView {
let customOverlayView: CustomMapOverlayView
public init() {
customOverlayView = CustomMapOverlayView(frame: CGRect.zero)
super.init(frame: CGRect.zero)
addVendorMapView()
addSubview(customOverlayView)
customOverlayView.snp.makeConstraints { (make) in
make.edges.equalToSuperview()
}
}
}
사용자 정의 UI 층 이 맵 원본 위 에 있어 야 하기 때문에 지 도 를 추가 하고 사용자 정의 View 를 추가 해 야 합 니 다.
통합 후 외부 호출 에 인 터 페 이 스 를 노출 할 수 있 습 니 다:
public class MeshMapView: UIView {
public var homePoint: CLLocationCoordinate2D? {
didSet {
updateHomePoint(homePoint)
}
}
private func updateHomePoint(_ coordinate: CLLocationCoordinate2D?) {
let correspondingPoint = convertCoordinateToCustomOverlayView(coordinate: coordinate)
customOverlayView.updateHomePoint(correspondingPoint)
}
private func convertCoordinateToCustomOverlayView(coordinate: CLLocationCoordinate2D?) -> CGPoint? {
guard let coordinate = coordinate else { return nil }
let standardCoordindate = MeshMapView.convertCoordinateToGCJIfNeeded(coordinate: coordinate)
guard let point = map?.convert(coordinate: standardCoordindate, toPointTo: customOverlayView) else { return nil }
if point.x.isNaN || point.y.isNaN { //
return nil
}
return point
}
}
국내 지도 에서 사용 하 는 좌 표 는 모두 GCJ 이지 만 국제 적 으로 GPS 좌표 가 많이 존재 하기 때문에 이곳 은 좌 표를 바 꿀 때 하나의 인 터 페 이 스 를 호출 하여 WGS 84 를 GCJ 로 바 꾸 었 다. 물론 이곳 의 오 차 는 분명 있 을 것 이다.위의 코드 중점 은 표 시 된 지리 좌 표를 저장 하고 customeOverlayView 에 추가 하기 전에 지리 좌 표를 평면 좌표 로 변환 해 야 한 다 는 것 이다.변환 이 완료 되면 customeOverlayView. updateHomePoint 를 호출 할 수 있 습 니 다.
또 하나의 디 테 일 은 지리 좌표 에서 평면 좌표 로 전환 하 는 것 으로 지도 가 다 로드 되 지 않 으 면 전환 에 실패 할 수도 있다.CGPoint 는 값 형식 이기 때문에 어떤 맵 은 SDK 변환 에 실패 하면 NaN 으로 값 이 전 환 됩 니 다.전환 후 x 와 y 의 값 이 유효한 지 판단 해 야 한다.
위의 코드 를 완성 한 후 updateHomePoint 를 호출 하면 표 시 된 위 치 를 보 여줄 수 있 습 니 다.그러나 현재 이 실현 에 또 하나의 문제 가 있 습 니 다. 사용자 가 지 도 를 이동 할 때 보기 에 표 시 된 위 치 는 변동 이 없습니다.정확 한 반응 은 지도 위치 가 바 뀌 었 고 표 시 된 위치 도 함께 바 뀌 었 을 것 이다.자 연 스 럽 게 지도 구역 변화 통 지 를 감청 하고 표 시 된 위 치 를 업데이트 해 야 합 니 다.
우선, 우 리 는 지도 원 으로 하 는 대리 대상 을 설명 합 니 다.
protocol VendorMapDelegate: class {
func mapViewDidChange()
func mapInitComplete()
}
class VendorMapDelegateProxy: NSObject, MAMapViewDelegate {
weak var delegate: VendorMapDelegate?
init(vendorMapDelegate: VendorMapDelegate) {
self.delegate = vendorMapDelegate
super.init()
}
func mapViewRegionChanged(_ mapView: MAMapView!) {
delegate?.mapViewDidChange()
}
func mapInitComplete(_ mapView: MAMapView!) {
delegate?.mapInitComplete()
}
}
지도 원 의 알림 이 벤트 를 표시 하기 위해 일반적인 인터페이스 인 VendorMapDelegate 를 발 표 했 습 니 다.매 순간 하나의 맵 소스 만 존재 하기 때문에 VendorMapDelegate Proxy 도 하나의 인 스 턴 스 만 MeshMapView 와 연 결 됩 니 다.mapInitComplete 방법 은 고 덕 특유 의 것 입 니 다. 서로 다른 지도 SDK 는 자신 이 불 러 온 것 을 표시 하 는 방식 이 다 릅 니 다. 어떤 것 은 finishLoading 이 고, 고 덕 은 mapInitComplete 입 니 다.지도 로 딩 이 완 료 된 사건 에 대해 서도 외부 에서 관심 을 갖 기 때문에 이 방법 도 밝 혔 다.
이어서 우 리 는 대리 대상 을 MeshMapView 에 통합 시 켰 다.
public class MeshMapView: UIView {
public var homePoint: CLLocationCoordinate2D? {
didSet {
updateHomePoint(homePoint)
}
}
private lazy var mapDelegateProxy: VendorMapDelegateProxy = {
return VendorMapDelegateProxy(vendorMapDelegate: self)
}()
private func addVendorMapView() {
switch MeshMapView.currentMapVendor {
case .gaode:
let gaodeMap = MAMapView(frame: CGRect.zero)
gaodeMap.delegate = mapDelegateProxy
addSubview(gaodeMap)
gaodeMap.snp.makeConstraints { (make) in
make.edges.equalToSuperview()
}
self.gaodeMap = gaodeMap
case .baidu:
// 。。。
}
}
func refreshCustomOverlay() {
updateHomePoint(homePoint)
}
}
extension MeshMapView: VendorMapDelegate {
func mapViewDidChange() {
refreshCustomOverlay()
}
func mapInitComplete() {
//。。。
}
}
이 코드 를 통합 하면 homepoint 의 지리 좌 표를 저장 해 야 하 는 이 유 를 알 수 있 습 니 다. 지도 영역 이 변 한 후에 표 시 를 다시 렌 더 링 해 야 하기 때문에 메타 데이터 가 평면 좌 표를 다시 매 핑 하여 위 치 를 업데이트 해 야 합 니 다.
이 모듈 의 디자인 요점 은 CustomMapOverlayView 의 직책 을 반드시 명확 하 게 구분 하고 평면 좌표 업데이트 위치 만 받 아들 여야 한 다 는 것 이다.이렇게 하면 Custom MapOverlay View 는 업무 와 결합 할 수 있 고 표 시 된 그리 기 능력 만 제공 합 니 다.지도 컨트롤 은 좌표 변환 을 관리 하고 지도 구역 이 변 경 된 후 다시 렌 더 링 할 시 기 를 관리 해 야 합 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.