In my ios swift
app I have a UITableViewController
with cells added dynamically. Each cell has a MKMapView
embedded and I'm setting the center of the map for each cell on different coordinates. I'm doing so by calling this method:
func centerMapOnLocation(location: CLLocation, map: MKMapView, radius: CLLocationDistance) {
let coordinateRegion = MKCoordinateRegionMakeWithDistance(location.coordinate,
radius * 2.0, radius * 2.0)
map.setRegion(coordinateRegion, animated: true)
}
inside cellForRowAtIndexPath
:
override func tableView(tview: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tview.dequeueReusableCellWithIdentifier("cell") as! SingleCall
let user:SingleUser = self.items[indexPath.row] as! SingleUser
let regionRadius: CLLocationDistance = 150
let initialLocation = CLLocation(latitude: user.coordinate.latitude, longitude: user.coordinate.longitude)
centerMapOnLocation(initialLocation, map: cell.eventMap, radius: regionRadius)
cell.eventMap.zoomEnabled = false
cell.eventMap.scrollEnabled = false
cell.eventMap.userInteractionEnabled = false
}
This is fine and it works, but I imagine with lots of records there will be problems with memory - even now with only couple cells when user scrolls the table - each map loads instantly and I can only imagine how much compute power it takes to do so.
So my question is - is there a way of changing the dynamic map view to some kind of maybe screenshot of the actual position of the map? Will it work faster when it comes to lots of cells?
Yes, it is possible. In order to do so, you should switch to using a UIImageView (called mapImageView
in the code below) and MKMapSnapshotter. To make things really fly, you should cache the images that MKMapSnapshotter produces so that they load instantly when a user scrolls back to a cell that was seen before. This approach is gentle on resources since it only uses the one global MKMapSnapShotter rather than a map for each cell.
Here's some code that I've adapted to your situation. I haven't included the detail on how to cache specifically, since that depends on how you want to handle caching in your app. I've used the Haneke cocoapod: https://cocoapods.org/pods/Haneke in the past. Also, I've set many of the common snapshotted options below, but you should probably adapt them to your use case.
//CHECK FOR CACHED MAP, IF NOT THEN GENERATE A NEW MAP SNAPSHOT
let coord = CLLocationCoordinate2D(latitude: placeLatitude, longitude: placeLongitude)
let snapshotterOptions = MKMapSnapshotOptions()
snapshotterOptions.scale = UIScreen.mainScreen().scale
let squareDimension = cell.bounds.width < cell.bounds.height ? (cell.bounds.width)! : (cell.bounds.height)!
snapshotterOptions.size = CGSize(width: squareDimension, height: squareDimension)
snapshotterOptions.mapType = MKMapType.Hybrid
snapshotterOptions.showsBuildings = true
snapshotterOptions.showsPointsOfInterest = true
snapshotterOptions.region = MKCoordinateRegionMakeWithDistance(coord, 5000, 5000)
let snapper = MKMapSnapshotter(options: snapshotterOptions)
snapper.startWithCompletionHandler({ (snap, error) in
if(error != nil) {
print("error: " + error!.localizedDescription)
return
}
dispatch_async(dispatch_get_main_queue()) {
guard let snap = snap where error == nil else { return }
if let indexPaths = self.tview.indexPathsForVisibleRows {
if indexPaths.contains(indexPath) {
cell.mapImageView.image = snap
}
}
//SET CACHE HERE
}
})
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With