Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In each cell in UITableViewController I have embedded map. Is there a way of changing it to screenshots of map instead?

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?

like image 511
user3766930 Avatar asked May 20 '16 00:05

user3766930


1 Answers

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
                    }
                })
like image 105
apod Avatar answered Jan 04 '23 14:01

apod