MapCache Swift
MapKit 的一部分亮点:一种简单的方式来缓存 瓦片地图 以及支持地图的离线浏览。
当前功能
- 当用户浏览地图时,自动将瓦片保存在磁盘缓存中。
- 生成超过最大服务器缩放级别 (
{z}
) 的插值瓦片。 - 缓存容量。一旦缓存满了,将使用 LRU (Least Recently Used) 算法。
- 获取当前缓存大小
- 清除现有缓存
- 下载整个地图区域 (实验性)
- 可用的 参考文档
即将到来
- 智能预下载/缓存:预测在网络空闲期间可能需要的瓦片
- 后台缓存更新下载
安装
MapCache 通过 CocoaPods 提供。要安装它,只需将以下行添加到您的 Podfile
#Podfile
pod 'MapCache'
然后,在拥有 Podfile
的文件夹中运行以下命令
pod install
如何使用 MapCache?
在拥有 MKMapView
的视图控制器中,导入 MapCache
import MapCache
然后,在 ViewController 中添加
// ViewController.swift
class ViewController: UIViewController {
@IBOutlet weak var map: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
//...
map.delegate = self
//...
// First setup the config of our cache.
// The only thing we must provide is the url template of the tile server.
// (All other config options are explained below in the section MapCache Configuration)
let config = MapCacheConfig(withUrlTemplate: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png")
// initialize the cache with our config
let mapCache = MapCache(withConfig: config)
// We tell the MKMapView to use the cache
// So whenever it requires a tile, it will be requested to the
// cache
map.useCache(mapCache)
//...
}
最后,通知地图代理使用 mapCacheRenderer
//ViewController.swift
// Assuming that ViewController is the delegate of the map
// add this extension:
extension ViewController : MKMapViewDelegate {
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
return mapView.mapCacheRenderer(forOverlay: overlay)
}
}
设置地图缓存后,用户浏览过的地图区域将保存在磁盘上。如果用户再次浏览同一区域,将使用本地版本。
注意,在当前版本中,缓存不支持过期日期,因此如果您需要获取瓦片的最新版本,必须调用 clear()
方法,这将清除整个缓存。
mapCache.clear() {
// do something after clear
print("cache cleared!")
}
获取当前缓存大小
mapCache.calculateDiskSize()
可以查看 示例/文件夹 以查看完整的实现示例。
有关参考文档,请参阅 MapCache。
MapCache 配置
配置地图缓存相对简单。通常,您只需要设置 urlTemplate
,可选地,还需要设置 subdomains
。
以下是选项
var config = MapCacheConfig()
// Set the URL template.
// For Open Street Maps you can chose: https://wiki.openstreetmap.org/wiki/Tile_servers
// It defaults to OpenStreetMaps servers
//
// Below we set cartoDB Base map server (https://github.com/CartoDB/cartodb/wiki/BaseMaps-available)
config.urlTemplate: "https://${s}.basemaps.cartocdn.com/base-light/${z}/${x}/${y}.png"
// In the urlTemplate ${s} stands for subdomains, which allows you to balance
// the load among the
// different tile servers.
// Default value is ["a","b","c"].
config.subdomains = ["a", "b"]
// Cache Name is basically is the subfolder name in which the tiles are store.
// Default value is "MapCache"
config.cacheName = "Carto"
// Max zoom supported by the tile server
// Default value is 19
config.maximumZ = 21
// Minimum zoom can also be set.
// config.minimumZ = 0
// Continues to show map tiles even beyond maximumZ
// config.overZoomMaximumZ = true
// Capacity of the cache in bytes. Once the cache is full it uses a LRU algorithm
// (Least Recently Used), that is, it removes the tiles last used a lot of time ago.
// Each time a tile is retrieved from the cache it is updated the value of last time used.
// Default value of the capacity is unlimited.
config.capacity = 200 * 1024 * 1024 // 200 Megabytes
如果您需要在不同的控制器中使用 MapCache,请确保在配置中使用相同的值以避免问题。
MapCache 后台工作原理
如果您需要在 MapCache 上构建某些内容,请阅读以下内容。
MapCache 是苹果的地图框架 MapKit 的一种变体,MapKit 用于 iOS、macOS、tvOS 和 watchOS 平台。
理解 MapCache 引导程序
如“如何使用 MapCache?”部分所述,为了引导 MapCache,我们必须调用此方法
map.useCache(mapCache)
其中 map 是 MKMapView
的一个实例,它是 MapKit 用来显示地图的主要类。MapCache 通过在 MKMapView+MapCache
扩展中添加新的方法 useCache
来实现,该方法告诉 MKMapView
在默认图层之上显示新的瓦片图层。因此,在瓦片加载过程中,您可能会看到 Apple Maps 的默认瓦片。
此扩展还向MKMapView
添加了一个变量来保存缓存配置。
在MapKit术语中,地图中的图层被称为叠加层。MapCache使用类CachedTileOverlay
中实现的基于瓦片的叠加层,这是一个MKTileOverlay
的子类。
叠加层关联着渲染器,它们是实际绘制叠加层内容的类。例如,有用于点、线、多边形和瓦片的渲染器。当MapView
需要显示叠加层时,它会调用委托并传递要渲染的叠加层,你需要提供要使用的渲染器。为此,我们添加了mapCacheRenderer
方法,当传入的叠加层类为CachedTileOverlay
类型时,它会返回默认的MKTileOverlayRenderer。这就是为什么需要在地图视图的委托(MKMapViewDelegate
)中添加此代码的原因。
extension ViewController : MKMapViewDelegate {
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
return mapView.mapCacheRenderer(forOverlay: overlay)
}
}
CachedTileOverlay
和MapCacheProtocol
如前所述,CachedTileOverlay
是一个基于瓦片的图层,它作为MKTileOverlay
的子类实现。基本上,它只想重写父类中的两个方法
-
func url(forTilePath path: MKTileOverlayPath) -> URL
。此方法的目的是返回瓦片的URL。我们需要重写它以使用我们偏好的瓦片服务器。 -
func loadTile(at path: MKTileOverlayPath, result: @escaping (Data?, Error?) -> Void)
。此方法是返回实际瓦片的方法。
如果您查看CachedTileOverlay
的实现,您会注意到它将请求转发到由名为mapCache
的变量调用的方法中,该变量是一个实现MapCacheProtocol
的类的实例。
override public func url(forTilePath path: MKTileOverlayPath) -> URL {
return mapCache.url(forTilePath: path)
}
MapCacheProtocol
的定义很简单,它只需要有一个MapCacheConfig
实例作为配置变量和一个实现CachedTileOverlay
中调用的两个方法的实现。
public protocol MapCacheProtocol {
var config: MapCacheConfig { get set }
func url(forTilePath path: MKTileOverlayPath) -> URL
func loadTile(at path: MKTileOverlayPath, result: @escaping (Data?, Error?) -> Void)
}
如果您需要创建缓存的自定义实现,需要创建一个实现此协议的类,并使用map.useCache(myCustomCacheImplementationInstance)
来初始化缓存。库提供的实现位于MapCache
类中。
另一个可能有用的类是DiskCache
。
如果您需要更多信息,可以查看
MapCache 参考文档。
开发
克隆仓库
git clone https://github.com/merlos/MapCache
使用 Xcode 打开文件 Example/MapCache.xcworkspace
要检查 pod 是否准备就绪,请在根目录文件夹中运行以下命令
pod lib lint MapCache.podspec
生成文档
安装 jazzy
gem install jazzy --verbose
在项目根目录中运行
jazzy
将在 docs/
中生成 html
你可能也喜欢
- Open GPX Tracker. 一个免费的源 iOS App,可以创建 GPX 路径
- Core GPX 由 Vincent Neo 提供的一个 Swift 库,用于管理 GPX 文件
许可 - MIT
版权所有 © 2019-2020 Juan M. Merlos 及贡献者 @merlos。
特此授予任何人免费获取本软件及其相关文档副本(以下简称“软件”)的权利,不受任何限制地处理该软件,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或销售软件副本的权利,并允许将软件提供给其他人使用,以便他们可执行上述行为,前提是必须遵守以下条件:
在软件的所有副本或主要内容中必须包含上述版权声明和本许可声明。
软件按“现状”提供,不提供任何形式的保证,不论是明示的还是暗示的,包括但不限于适销性、适用于特定目的和不侵权保证。在任何情况下,作者或版权所有者不对任何索赔、损害或其他责任负责,无论是通过合同、侵权或其他行为,无论是出于软件或其使用或其他原因产生的。