使用MKMapSnapshotter创建可点击的地图预览 [英] Create a clickable map preview using MKMapSnapshotter
问题描述
我有一张地图,该地图当前显示了用户的当前位置,没有显示任何确切的位置.我想使地图成为用户设置位置的照片.我只知道如何显示他们的设备在哪里,并需要他们能够设置其操作基础.我不需要特定的地址.我只需要他们居住的城市.
I have a map that currently shows the user's current location with no pin to show them exactly where they are. I want to make the map a photo of where the user's set location is. I only know how to show where their device is and need them to be able to set their base of operations. I don't need specific addresses. I just need the city where they reside.
然后我需要能够轻敲图像.轻按时,图像将使MapKit全屏显示并进行交互.然后,他们可以在地图上缩放并查看其他用户在哪里设置操作基础.
I then need the image to be able to be tapped on. When tapped, the image makes the MapKit full screen and interactive. They can then zoom around the map and see where other users' set their base of operations.
我是编码的新手,即使他们在全国各地移动,也无法弄清楚如何允许用户设置永久位置.我也不知道如何设置mapsnapshot,并在点击以显示完整的地图视图时在其上方扩展.
I am new to coding and can't figure out how to allow the user to set a permanent location even if they move around the country. I also don't know how to set up the mapsnapshot and on top of that expand when tapped to show a fully working map view.
我目前只能询问是否可以激活位置服务,然后在加载时显示其地图视图.这是代码:
I am only currently able to ask if I can activate location services and then show their map view where they are when it is loaded. Here is the code:
import UIKit
import CoreLocation
import MapKit
class HomeTableViewController: UITableViewController, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout, CLLocationManagerDelegate, MKMapViewDelegate {
@IBOutlet weak var activityIndicator: UIActivityIndicatorView!
@IBOutlet weak var mapPreviewImageView: UIImageView!
@IBOutlet weak var mapView: MKMapView!
let manager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
manager.desiredAccuracy = kCLLocationAccuracyBest // battery
manager.delegate = self
manager.requestWhenInUseAuthorization()
manager.startUpdatingLocation()
// Always adopt a light interface style.
overrideUserInterfaceStyle = .light
takeSnapShot()
}
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return 7
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let location = locations.first {
manager.stopUpdatingLocation()
render(location)
}
}
func render (_ location: CLLocation) {
let coordinate = CLLocationCoordinate2D(latitude: location.coordinate.latitude, longitude: location.coordinate.longitude)
let span = MKCoordinateSpan(latitudeDelta: 0.1, longitudeDelta: 0.1)
let region = MKCoordinateRegion(center: coordinate, span: span)
mapView.setRegion(region, animated: true)
}
func takeSnapShot() {
let location = CLLocation()
let mapSnapshotOptions = MKMapSnapshotter.Options()
let coordinate = CLLocationCoordinate2D(latitude: location.coordinate.latitude, longitude: location.coordinate.longitude)
let span = MKCoordinateSpan(latitudeDelta: 0.1, longitudeDelta: 0.1)
let region = MKCoordinateRegion(center: coordinate, span: span)
mapSnapshotOptions.region = region
// Set the scale of the image. We'll just use the scale of the current device, which is 2x scale on Retina screens.
mapSnapshotOptions.scale = UIScreen.main.scale
// Show buildings and Points of Interest on the snapshot
mapSnapshotOptions.showsBuildings = true
mapSnapshotOptions.mapType = .satellite
let snapShotter = MKMapSnapshotter(options: mapSnapshotOptions)
snapShotter.start() { snapshot, error in
guard let snapshot = snapshot else {
return
}
self.mapPreviewImageView.image = snapshot.image
}
}
}
非常感谢您的帮助.我确实需要在此应用上取得一些进展,而且似乎找不到有关如何执行此操作的任何教程或网络结果.
Thanks for your help in advance. I really need to make some progress on this app and I can't seem to find any tutorials or web results on how to do this.
我尝试添加一个将UIImage转换为快照的函数.我能够返回图像,但是它不显示我的位置,并且比我的UIImage小.我已经编辑了上面的代码以反映我所做的更改.我不知道我在做什么错.
I have tried adding a function that turns my UIImage into the snapshot. I am able to return an image but it doesn't show my location and it is smaller than my UIImage. I had edited the code above to reflect the changes I made. I don't know what I am doing wrong.
推荐答案
在您的示例中,您正在创建CLLocationManager
,但未使用它.您正在使用CLLocation()
.那显然没有(有意义的)坐标与之相关.确保提供有效的坐标.例如,让didUpdateLocations
调用takeSnapshot
:
In your example, you are creating a CLLocationManager
, but not using it. You are using CLLocation()
. That obviously has no (meaningful) coordinate associated with it. Make sure to supply a valid coordinate. For example, have didUpdateLocations
call takeSnapshot
:
class ViewController: UIViewController {
@IBOutlet weak var imageView: UIImageView!
private weak var snapshotter: MKMapSnapshotter?
private lazy var manager: CLLocationManager = {
let manager = CLLocationManager()
manager.delegate = self
manager.distanceFilter = 20
return manager
}()
override func viewDidLoad() {
super.viewDidLoad()
if manager.authorizationStatus == .notDetermined {
manager.requestWhenInUseAuthorization()
}
manager.startUpdatingLocation()
}
func takeSnapshot(of location: CLLocation) {
snapshotter?.cancel() // cancel prior one, if any
let options = MKMapSnapshotter.Options()
options.camera = MKMapCamera(lookingAtCenter: location.coordinate, fromDistance: 1000, pitch: 0, heading: 0)
options.mapType = .satellite
options.size = imageView.bounds.size
let snapshotter = MKMapSnapshotter(options: options)
snapshotter.start() { snapshot, _ in
self.imageView.image = snapshot?.image
}
self.snapshotter = snapshotter
}
}
extension ViewController: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let location = locations.last(where: { $0.horizontalAccuracy >= 0 } ) else { return }
takeSnapshot(of: location)
}
}
结果是:
不相关的观察结果
-
您正在使用
MKCoordinateSpan(latitudeDelta: 0.1, longitudeDelta: 0.1)
.我个人认为跨度并不是非常有用.我可能建议您使用电表,例如
You are using
MKCoordinateSpan(latitudeDelta: 0.1, longitudeDelta: 0.1)
. I personally do not find spans in degrees to be terribly useful. I might advise using meters, e.g.
options.region = MKCoordinateRegion(center: location.coordinate, latitudinalMeters: 1000, longitudinalMeters: 1000)
或使用MKMapCamera
:
options.camera = MKMapCamera(lookingAtCenter: location.coordinate, fromDistance: 1000, pitch: 0, heading: 0)
如果使用的地图类型为satellite
,则没有必要使用showsBuildings
. 文档说:
There is no point in using showsBuildings
if you are using a map type of satellite
. The docs say:
必须将
mapType
属性设置为MKMapType.standard
用于显示挤压建筑物.
The
mapType
property must be set toMKMapType.standard
for extruded buildings to be displayed.
我认为您不必设置scale
. 文档说:
I do not believe that you have to set the scale
. The docs say:
此属性设置为默认值,该值与当前设备的显示器的分辨率相对应.
This property is set to a default value that corresponds to the resolution of the current device’s display.
此外,无论如何该属性现在已被弃用.
Besides, this property is now deprecated, anyway.
不过,我建议设置 <图片的c11> .
这篇关于使用MKMapSnapshotter创建可点击的地图预览的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!