1

I'm, developing an app that needs different colored overlays for "delivery zones" so basically what I did was to subclass MKPolygon depending on the color I needed.

class YellowPolygon: MKPolygon {

}

class BluePolygon: MKPolygon {

}

class GreenPolygon: MKPolygon {

}

class PurplePolygon: MKPolygon {

}

class OrangePolygon: MKPolygon {

}

Once I finished doing this I added the classes like this

func addPolygon() {

let polygon1 = YellowPolygon(coordinates: coordArray[0], count: coordArray[0].count)
    print(coordArray[0])

    let polygon2 = BluePolygon(coordinates: coordArray[1], count: coordArray[1].count)
    print(coordArray[1])

    let polygon3 = GreenPolygon(coordinates: coordArray[2], count: coordArray[2].count)
    print(coordArray[2])

    let polygon4 = PurplePolygon(coordinates: coordArray[3], count: coordArray[3].count)
    print(coordArray[3])

    polygon1.title = "Narvarte1"
    polygon2.title = "Escandón"
    polygon3.title = "Narvarte2"
    polygon4.title = "Zona Roma Norte"

    poly1 = polygon1
    poly2 = polygon2
    poly3 = polygon3
    poly4 = polygon4

    mapView.add(polygon1)
    mapView.add(polygon2)
    mapView.add(polygon3)
    mapView.add(polygon4)
}

my renderer for overlay method looks like this:

func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {

    let yellowCustom = UIColor(red: 255/255, green: 255/255, blue: 0/255, alpha: 1.0)
    let blueCustom = UIColor(red: 1/255, green: 116/255, blue: 223/255, alpha: 1.0)
    let greenCustom = UIColor(red: 95/255, green: 180/255, blue: 4/255, alpha: 1.0)
    let purpleCustom = UIColor(red: 172/255, green: 88/255, blue: 250/255, alpha: 1.0)
    let orangeCustom = UIColor(red: 255/255, green: 128/255, blue: 0/255, alpha: 1.0)

  loadRutaView()

    if overlay is MKPolyline {
        let renderer = MKPolylineRenderer(overlay: overlay)
        renderer.strokeColor = UIColor.yellow
        renderer.lineWidth = 0
        return renderer

    } else if overlay is YellowPolygon {


        let renderer = MKPolygonRenderer(polygon: overlay as! MKPolygon)
        let currentMapPoint: MKMapPoint = MKMapPointForCoordinate(updatedUserLocation!)
        let polygonViewPoint: CGPoint = renderer.point(for: currentMapPoint)
        print(polygonViewPoint)

        if renderer.path.contains(polygonViewPoint) {
            print("Dentro de zona 1 (Amarilla)")
            enRuta = true
            loadRutaView()
            self.sinRutaView.isHidden = true
            self.rutaView.isHidden = false

            self.zonasLabel.text = rutas[0].zona
            self.diaLabel.text = rutas[0].dias
            self.fechaLabel.text = rutas[0].proxDia
            self.horarioLabel.text = rutas[0].hora

            rutaSelecta = rutas[0]

        } else {

            loadRutaView()
            print("fuera de la zona 1 (Amarilla)")
        }

        renderer.fillColor = yellowCustom.withAlphaComponent(0.5)
        renderer.strokeColor = yellowCustom
        renderer.lineWidth = 1

        return renderer

    } else if overlay is BluePolygon {

        let renderer = MKPolygonRenderer(polygon: overlay as! MKPolygon)
        let currentMapPoint: MKMapPoint = MKMapPointForCoordinate(updatedUserLocation!)
        let polygonViewPoint: CGPoint = renderer.point(for: currentMapPoint)
        print(polygonViewPoint)

        if renderer.path.contains(polygonViewPoint) {
            print("Dentro de zona 2 (Azul)")
            enRuta = true
            loadRutaView()

            self.zonasLabel.text = rutas[1].zona
            self.diaLabel.text = rutas[1].dias
            self.fechaLabel.text = rutas[1].proxDia
            self.horarioLabel.text = rutas[1].hora

            rutaSelecta = rutas[1]

        } else {
            loadRutaView()
            print("Fuera de la zona 2 (Azul)")
        }

        renderer.fillColor = blueCustom.withAlphaComponent(0.5)
        renderer.strokeColor = blueCustom
        renderer.lineWidth = 1

        return renderer


    } else if overlay is PurplePolygon {

        let renderer = MKPolygonRenderer(polygon: overlay as! MKPolygon)
        let currentMapPoint: MKMapPoint = MKMapPointForCoordinate(updatedUserLocation!)
        let polygonViewPoint: CGPoint = renderer.point(for: currentMapPoint)
        print(polygonViewPoint)

        if renderer.path.contains(polygonViewPoint) {
            print("Dentro de zona 3 (Morada)")
            enRuta = true
            loadRutaView()


            self.zonasLabel.text = rutas[2].zona
            self.diaLabel.text = rutas[2].dias
            self.fechaLabel.text = rutas[2].proxDia
            self.horarioLabel.text = rutas[2].hora

            rutaSelecta = rutas[2]

        } else {
            print("Fuera de la zona 3 (Morada")
            loadRutaView()
        }

        renderer.fillColor = purpleCustom.withAlphaComponent(0.5)
        renderer.strokeColor = purpleCustom
        renderer.lineWidth = 1

        return renderer

    } else if overlay is GreenPolygon {

        let renderer = MKPolygonRenderer(polygon: overlay as! MKPolygon)
        let currentMapPoint: MKMapPoint = MKMapPointForCoordinate(updatedUserLocation!)
        let polygonViewPoint: CGPoint = renderer.point(for: currentMapPoint)
        print(polygonViewPoint)

        if renderer.path.contains(polygonViewPoint) {

            print("Dentro de zona 4 (Verde)")
            enRuta = true
            loadRutaView()

            self.zonasLabel.text = rutas[3].zona
            self.diaLabel.text = rutas[3].dias
            self.fechaLabel.text = rutas[3].proxDia
            self.horarioLabel.text = rutas[3].hora

            rutaSelecta = rutas[3]

        } else {
            loadRutaView()
            print("Fuera de la zona 4 (Verde)")
        }

        renderer.fillColor = greenCustom.withAlphaComponent(0.5)
        renderer.strokeColor = greenCustom
        renderer.lineWidth = 1

        return renderer

    } else if overlay is OrangePolygon {

        let renderer = MKPolygonRenderer(polygon: overlay as! MKPolygon)
        let currentMapPoint: MKMapPoint = MKMapPointForCoordinate(updatedUserLocation!)
        let polygonViewPoint: CGPoint = renderer.point(for: currentMapPoint)
        print(polygonViewPoint)

        if renderer.path.contains(polygonViewPoint) {

            print("Dentro de zona 5 (Naranja)")
            enRuta = true
            loadRutaView()

            self.zonasLabel.text = rutas[4].zona
            self.diaLabel.text = rutas[4].dias
            self.fechaLabel.text = rutas[4].proxDia
            self.horarioLabel.text = rutas[4].hora

            rutaSelecta = rutas[0]

        } else {
            loadRutaView()
            print("Fuera de la zona 5 (Naranja)")
        }

        renderer.fillColor = orangeCustom.withAlphaComponent(0.5)
        renderer.strokeColor = orangeCustom
        renderer.lineWidth = 1


        return renderer

    }



    return MKOverlayRenderer()
}

The code works, but when I leave this view the memory used by these polygons and the mapview isn't released. (I get a spike from 68mb to 263mb when I first access this view, if I leave and come back goes from 263mb to 356.5mb if I do it again it goes from 356.5mb to 453.8mb, and so on).

Any possible workaround? (I absolutely need to have different colored mkpolygons because the customer wants this).

Thanks :)

Octavio Rojas
  • 187
  • 13
  • I suspect the problem rests elsewhere, not in the overlays themselves. I'd suggest using Xcode 8's "debug memory graph" (see http://stackoverflow.com/a/30993476/1271826) feature to identify which objects are not getting released. And don't dwell on the overlays, but rather make sure the view controller that contains the view with this map view is getting released. And if that's not leaking, look for map objects. Bottom line, I suspect you have some strong reference cycle, but there's not enough here to diagnose it, as it isn't caused by the code provided thus far. – Rob Feb 20 '17 at 19:19
  • It's just checking out if it should load the view that gives options when the user is inside a delivery route, or if it should load the view when there is no delivery route. `func loadRutaView() { if enRuta { self.sinRutaView.isHidden = true self.rutaView.isHidden = false } else { self.rutaView.isHidden = true self.sinRutaView.isHidden = false } } }` – Octavio Rojas Feb 20 '17 at 19:26
  • Yes it's pretty weird, I don't understand what's causing the problem either. I thought it was the polygons, but for some reason the mapview isn't being released. – Octavio Rojas Feb 20 '17 at 19:29
  • So far the only segue I have is the back button, I still haven't coded the exit segue from the app (in the case the user is inside a delivery area and presses the accept button). I have this code inside my `willMove(toParentViewController)`method. `if parent == nil { mapView.remove(poly1) mapView.remove(poly2) mapView.remove(poly3) mapView.remove(poly4) mapView.removeAnnotations(mapView.annotations) mapView.reloadInputViews() mapView.removeFromSuperview() }` – Octavio Rojas Feb 20 '17 at 19:54
  • I'm going through the debug memory graph you mentioned and so far what I noticed is the following. I opened the view with the map once, closed it and reopened like 4 times and these objects increased. **GeoServices 4337 - 5416, MapKit 53 - 269, MetalTools 4241 - 18634, VectorKit 75532 - 343526** What else should I try? – Octavio Rojas Feb 20 '17 at 20:59
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/136188/discussion-between-rob-and-octavio-rojas). – Rob Feb 20 '17 at 21:30

0 Answers0