Same issue here:
Post
Replies
Boosts
Views
Activity
The problem is now fixed. After building with Xcode 12.3 and run the code on IOS 14.3 it works fine. I set .alpha to 0.65 & it works ok now.
I checked with IOS14.3 after building with Xcode 12.3. The problem is not fixed yet.
I created a feedback report for this problem with number Nov 26, 2020 at 3:08 PM – FB8918120
I noticed, by running on various simulators, IOS 13.7 does not have the problem but 14.0, 14.1 and 14.2 do.
here is the code to reproduce
//
// ViewController.swift
// ios14PolylineMemoryLeak
//
// Created by Henri on 26/11/2020.
//
import UIKit
import MapKit
class ViewController: UIViewController, MKMapViewDelegate {
//
// to see reproduction run instruments/leaks
// - it will report leaks on IOS 14.2 and memory usage is increasing all the time.
// - On IOS 13.7 all is ok, no memory leaks, and memory usage remains at a contant value
//
// Below out that Instruments Leaks is giving me.
// Malloc 144 Bytes 111 < multiple > 15,61 KiB
// VectorKit geo::MallocZoneAllocator::allocate(unsigned long, unsigned long)
// MTLSimTexture 81 < multiple > 30,38 KiB
// MTLSimDriver_77-[MTLSimTexture newTextureViewWithPixelFormatInternal:isInternalTextureView:]blockinvoke
// Malloc 16 Bytes 93 < multiple > 1,45 KiB
// VectorKit geo::MallocZoneAllocator::allocate(unsigned long, unsigned long)
//
//
@IBOutlet weak var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
setupMapView()
reproduceIos14PolylineMemoryLeak()
}
func reproduceIos14PolylineMemoryLeak() {
= Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(fireTimer), userInfo: nil, repeats: true)
}
@objc func fireTimer() {
let coordinate1 = mapView.convert(CGPoint(x: 100, y: 100), toCoordinateFrom: mapView)
let coordinate2 = mapView.convert(CGPoint(x: 300, y: 300), toCoordinateFrom: mapView)
let farawayCoordinate = locationWithBearing(bearing: 90, distanceMeters: 50000, origin: coordinate2)
var coordinates = [CLLocationCoordinate2D]()
coordinates.append(coordinate1)
coordinates.append(coordinate2)
coordinates.append(farawayCoordinate)
let polyline = MKPolyline(coordinates: coordinates, count: coordinates.count)
let overlays = mapView.overlays
for overlay in overlays {
mapView.removeOverlay(overlay)
}
mapView.addOverlay(polyline)
}
func locationWithBearing(bearing:Double, distanceMeters:Double, origin:CLLocationCoordinate2D) -> CLLocationCoordinate2D {
let distRadians = distanceMeters / (6372797.6)
let rbearing = bearing * Double.pi / 180.0
let lat1 = origin.latitude * Double.pi / 180
let lon1 = origin.longitude * Double.pi / 180
let lat2 = asin(sin(lat1) * cos(distRadians) + cos(lat1) * sin(distRadians) * cos(rbearing))
let lon2 = lon1 + atan2(sin(rbearing) * sin(distRadians) * cos(lat1), cos(distRadians) - sin(lat1) * sin(lat2))
return CLLocationCoordinate2D(latitude: lat2 * 180 / Double.pi, longitude: lon2 * 180 / Double.pi)
}
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
if (overlay is MKPolyline)
{
let renderer = MKPolylineRenderer(overlay: overlay)
renderer.strokeColor = .systemBlue
renderer.lineWidth = 5.0
return renderer
}
return MKOverlayRenderer(overlay: overlay)
}
func setupMapView() {
let appleCoordinate = CLLocation(latitude: 37.33182, longitude: -122.03118)
mapView.delegate = self
let coordinateRegion = MKCoordinateRegion(
center: CLLocationCoordinate2D(
latitude: appleCoordinate.coordinate.latitude,
longitude: appleCoordinate.coordinate.longitude),
latitudinalMeters: 10 ,
longitudinalMeters: 1000)
mapView.setRegion(coordinateRegion, animated: true)
}
}
Update:
I noticed in instruments that the leak already occurs when adding the polyline overlay. So it does not happen on the mapView.removeOverlay(overlay) but on the mapView.addAnnotation(polyLine)
So my question is: Has anybody noticed the problem too?
Is there a workaround ?
Note: my app becomes unresponsive after a few hours because it runs out of memory.
To fix the problem the only change was:
renderer.alpha = 1.0 // change alpha from 0.8 to 1.0
Answer to question that was asked: When I do not specify renederer.alpha it also works fine.
Needless to say my goal is to specify transparency so that the underlaying layer can been seen. That fails so for now I use .alpha 1.0
This works ok:
func mapView( mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
let renderer = MKPolylineRenderer(overlay: overlay)
renderer.strokeColor = .red
renderer.lineWidth = 5.0
renderer.alpha = 1.0
return renderer
}
This also works ok:
func mapView( mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
let renderer = MKPolylineRenderer(overlay: overlay)
renderer.strokeColor = .red
renderer.lineWidth = 5.0
// renderer.alpha = 1.0
return renderer
}
This fails:
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
let renderer = MKPolylineRenderer(overlay: overlay)
renderer.strokeColor = .red
renderer.lineWidth = 5.0
renderer.alpha = 0.8 // <<<=== on IOS 14.1 this will cause the MKPolyline fail to show, works OK on iOS 13.7
return renderer
}
See
662219: iOS 14.0 Regression - MKPolyline is not shown on top of a MKTileOverlay
This is indeed the workaround
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
let renderer = MKPolylineRenderer(overlay: overlay)
if (overlay is MKPolyline) {
renderer.strokeColor = .red
renderer.lineWidth = 5.0
renderer.alpha = 1.0 // changed 0.8 to 1.0, now it works
}
}
I found in another thread that the workaround is to set renderer.alpha to 1.0
I changed rederer.alpha from 0.8 to 1.0 and indeed that indeed works.
So the bug is that .alpha fails in the above mentioned scenario.
So the following fails: I have an standard mapView
on top of that I have an OpenTopo overlay that covers the entire standard map
I try to display the route MKpolyline on top the OpenTopo map.
Now the MKPolyline (3) is not shown on IOS 14.1 hardware (ok on 13.7 hardware and the Xcode 14.1 simulator)
When I do: have an standard mapView
Display the route MKpolyline on top of the standard map
The MKPolyline is shown ok on both IOS 13.7 and 14.1 hardware.
See above for my answer about code code fragments.
My code is all over the place but I will try to provide the key snippets. I don't have a small demo version that you can run att. I hope this helps.
Part1:
self.mapView.removeOverlay(self.navigationRoute.polyline)
self.navigationRoute = response.routes[0]
self.navigationRoute.polyline.title = "navigationRoute"
self.mapView.addOverlay(self.navigationRoute.polyline, level: MKOverlayLevel.aboveLabels)
let distance = self.navigationRoute.distance
let expectedTime = self.navigationRoute.expectedTravelTime/60
let navDistance = self.formatDistance(distance: distance, round10m: true)
self.navLabel.text = "Nav \(navDistance) \(expectedTime)"
Part2:
if let overlay = openTopo {
mapView.addOverlay(overlay, level: MKOverlayLevel.aboveRoads)
}
Part3:
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
if (overlay is MKTileOverlay) {
return MKTileOverlayRenderer(overlay: overlay)
}
}