SwiftUI-地图框架

Apple 提供了一个 SwiftUI Map视图,它精美地包装了底层地图框架,让我们可以将地图、注释等与 SwiftUI 视图层次结构的其余部分一起放置。 地图及其所有配置数据都来自一个名为 MapKit 的专用框架,

简单显示地图

可以调整用户使用地图的方式,例如他们是否可以缩放或旋转其位置。例如,我们可以制作一张始终保持以特定位置为中心的地图,但用户仍然可以调整旋转和缩放:

scss 复制代码
Map(interactionModes: [.rotate, .zoom])  

可以不指定交互模式,这意味着地图始终是完全固定的:

scss 复制代码
Map(interactionModes: [ ])  

使用mapStyle()修改器来控制地图的外观

  • 卫星地图
  • 将卫星地图和街道地图结合起来
  • 可以获取两张地图以及真实的海拔高度,创建 3D 地图

这些都是简单的自定义选项,但其中三个需要更多思考:控制位置、放置注释和处理点击。

初始位置

创建一个存储伦敦位置的常量属性,跨度指定为 1 度 x 1 度:

less 复制代码
let position = MapCameraPosition.region(

    MKCoordinateRegion(
        center: CLLocationCoordinate2D(latitude: 51.507222, longitude: -0.1275),
        span: MKCoordinateSpan(latitudeDelta: 1, longitudeDelta: 1)
    )
)  

初始化传入位置

scss 复制代码
Map(initialPosition: position)

移动位置

如果您想随着时间的推移更改位置,则需要将其标记为@State然后将其作为绑定传递。

当position值发生变化,地图位置就会运动到该位置

跟踪位置变化

onMapCameraChange()修饰符,可以告诉我们位置何时发生变化,是立即发生变化还是在运动结束后发生变化。 可以编写当他们完成拖动地图时获取更新

scss 复制代码
Map(position: $position)
    .onMapCameraChange { context in

        print(context.region)
    }  

也可以让它发布连续更新:

scss 复制代码
Map(position: $position)

    .onMapCameraChange(frequency: .continuous) { context in

        print(context.region)
    }  

放置注释球 Maker

需要三个步骤:定义包含您的位置的新数据类型,创建包含您所有位置的数组,然后将它们添加为地图中的注释。无论您创建什么新数据类型来存储位置,它都必须符合Identifiable协议,以便 SwiftUI 可以唯一地识别每个地图标记。

swift 复制代码
struct Location: Identifiable {

    let id = UUID()
    var name: String
    var coordinate: CLLocationCoordinate2D
}  
php 复制代码
let locations = [

    Location(name: "Buckingham Palace", coordinate: CLLocationCoordinate2D(latitude: 51.501, longitude: -0.141)),
    Location(name: "Tower of London", coordinate: CLLocationCoordinate2D(latitude: 51.508, longitude: -0.076))
] 

第三步是重要的部分:我们可以将该位置数组Map作为其内容输入到视图中。 SwiftUI 为我们提供了几种不同的内容类型,但一种简单的内容类型称为Marker:附有标题和纬度/经度坐标的气球。

scss 复制代码
Map {
    ForEach(locations) { location in
        Marker(location.name, coordinate: location.coordinate)
    }
}  

自定义标记

如果您想更好地控制标记在地图上的显示方式,请使用Annotation。这使您可以提供完全自定义的视图,来代替标准系统标记气球 Maker,并且如果您愿意,您可以隐藏默认标题,以便您可以将其替换为您自己的标题,如下所示:

scss 复制代码
Map {
    ForEach(locations) { location in
    
        Annotation(location.name, coordinate: location.coordinate) {

            Text(location.name)
                .font(.headline)
                .padding()
                .background(.blue)
                .foregroundStyle(.white)
                .clipShape(.capsule)
        }
        .annotationTitles(.hidden)  
    }
} 

点击地图

最后,您可以使用onTapGesture() 处理地图上的点击。这告诉我们用户在地图上点击的位置,但它是在屏幕坐标中进行的- 例如,距顶部 50 点,距左侧 100 点。

为了获得地图上的实际位置,我们需要一个名为 MapReader 的特殊视图。当您将其中一个包裹在地图上时,您将收到一个特殊的MapProxy对象,该对象能够将屏幕位置转换为地图位置,并以另一种方式转换回来。

scss 复制代码
MapReader { proxy in

    Map()
        .onTapGesture { position in
        
            if let coordinate = proxy.convert(position, from: .local) {
                print(coordinate)
            }
        }
}  

.local部分意味着我们正在转换地图本地坐标空间中的位置,这意味着我们正在使用的点击位置是相对于地图的左上角而不是整个屏幕或其他一些坐标空间。

相关推荐
终端安全笔记4 小时前
iOS 27 之后「策略空转」:设备升级不报错,但旧策略不再管它
android·网络·安全·ios·智能手机
9765033357 小时前
iOS 上架 4.3a 被拒【uniapp专讲】
flutter·ios·objective-c·uniapp·swift
黑化旺仔20 小时前
【OC】KVO
macos·ios·objective-c·cocoa
HouWan1 天前
SwiftUI 小技巧:如何读取 SwiftUI Font 的详细信息
ios·swiftui·apple
李游Leo1 天前
HarmonyOS 7 实战开发 05:把页面做到可上线状态
ios·harmonyos
终端安全笔记1 天前
描述文件、企业证书、MDM 不是三个名字,是三层
android·ios·智能手机
传奇开心果编程1 天前
【SwiftUI入门练中学】第1课 从零开始
学习·ui·ios·swiftui·swift
丿Wayne1 天前
iOS Token 刷新实战(Actor 避免并发重复刷新)
ios·swift·token·actor·swift并发
终端安全笔记2 天前
iOS 27 给了租赁一个新工具,但它只认受监督的设备
android·网络·安全·ios
大熊猫侯佩2 天前
独立 App 首发完成 iPhone Duo 展开态适配
ios·swiftui·swift