使用MKMapSnapshotter创建可点击的地图预览 [英] Create a clickable map preview using MKMapSnapshotter

查看:140
本文介绍了使用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)
    }
}

结果是:

不相关的观察结果

  1. 您正在使用MKCoordinateSpan(latitudeDelta: 0.1, longitudeDelta: 0.1).我个人认为跨度并不是非常有用.我可能建议您使用电表,例如

  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 to MKMapType.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屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆