当用户在屏幕上移动手指时,我想绘制一条折线。我根据一些文章编写代码,并且可以在一定程度上发挥作用。在某些时候,一切开始滞后,应用程序崩溃。
我试图清洁覆盖物并减少点数,但这并没有帮助我。
var rendersWorkaround: [MKOverlayRenderer] = []
var currentRender: MKOverlayRenderer?
var points: [CLLocationCoordinate2D] = []
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.rendersWorkaround.forEach { item in
self.mapView.removeOverlay(item.overlay)
}
self.rendersWorkaround = []
self.points = []
if let touch = touches.first {
let coordinate = mapView.convert(touch.location(in: mapView), toCoordinateFrom: mapView)
points.append(coordinate)
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
// if self.lastTouchTime != nil && (Date().timeIntervalSinceReferenceDate - self.lastTouchTime!) < 0.025 { return }
if self.rendersWorkaround.count > 10 {
let countForDelete: Int = Int((Double(self.rendersWorkaround.count) / 2.0).rounded())
for index in 0...countForDelete {
self.mapView.removeOverlay(self.rendersWorkaround[index].overlay)
}
self.rendersWorkaround.removeSubrange(0...countForDelete)
}
if let touch = touches.first {
let coordinate = mapView.convert(touch.location(in: mapView), toCoordinateFrom: mapView)
points.append(coordinate)
if points.count > 299 {
points = points.indices.compactMap { return $0 % 2 != 0 ? points[$0] : nil }
}
let polyline = MKPolyline(coordinates: points, count: points.count)
mapView.addOverlay(polyline)
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
let polygon = MKPolygon(coordinates: &points, count: points.count)
mapView.addOverlay(polygon)
points = []
}
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
if overlay is MKPolyline {
let polylineRenderer = MKPolylineRenderer(overlay: overlay)
polylineRenderer.strokeColor = .orange
polylineRenderer.lineWidth = 5
self.rendersWorkaround.append(polylineRenderer)
self.currentRender = polylineRenderer
return polylineRenderer
} else if overlay is MKPolygon {
let polygonView = MKPolygonRenderer(overlay: overlay)
polygonView.fillColor = .magenta
self.rendersWorkaround.append(polygonView)
return polygonView
}
return MKTileOverlayRenderer(overlay: overlay)
}
答案 0 :(得分:0)
是的,我在 iOS 13 更新后注意到了这一点。 Apple 进行了大量地图更新,现在“rendererFor 叠加层”滞后了。我不知道为什么。我最终移动到覆盖地图的 UIView。用户可以在该视图上绘制然后我将接触点转换为 mapView。所以最后会调用 rendererFor。
此页面上有一个答案,他们正在做类似的事情。 iOS + MKMapView user touch based drawing
这是我的代码:
import Foundation
struct DrawViewViewModel {
let lineColor: UIColor
let lineWidth: CGFloat
}
protocol DrawViewDelegate: AnyObject {
func touchesEnded(points: [CGPoint])
}
class DrawView: UIView {
weak var delegate: DrawViewDelegate?
private var lineArray: [CGPoint] = [CGPoint]()
var firstPoint = CGPoint.zero
var viewModel: DrawViewViewModel?
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
// 2
guard let touch = touches.first else { return }
firstPoint = touch.location(in: self)
// 3
lineArray.append(firstPoint)
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first else { return }
let currentPoint = touch.location(in: self)
lineArray.append(currentPoint)
setNeedsDisplay()
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first else { return }
let currentPoint = touch.location(in: self)
lineArray.append(currentPoint)
delegate?.touchesEnded(points: lineArray)
//delete draw lines
lineArray = []
setNeedsDisplay()
}
override func draw(_ rect: CGRect) {
guard let context = UIGraphicsGetCurrentContext() else { return }
draw(inContext: context)
}
func draw(inContext context: CGContext) {
// 2
if let VM = viewModel {
context.setLineWidth(VM.lineWidth)
context.setStrokeColor(VM.lineColor.cgColor)
}
context.setLineCap(.round)
// 3
for (index, point) in lineArray.enumerated() {
// 4
context.beginPath()
context.move(to: point)
if index+1 < lineArray.count {
context.addLine(to: lineArray[index+1])
}
context.strokePath()
}
}
}
接着是我的 MKMapView 使用的委托:
//MARK - DrawViewDelegate
func touchesEnded(points: [CGPoint]) {
let mapPoints = convertPointsToCords(points: points)
let polygon = MKPolygon(coordinates: mapPoints, count: mapPoints.count)
let worldPoly = getWorldPoly()
let polygonInverted = MKPolygon(coordinates: worldPoly, count: worldPoly.count, interiorPolygons: [polygon]) //create an inverted polygon
coreMapView.addOverlay(polygonInverted) //Add polygon areas
//Then run the search
// update search criteria
updateSearchCriteria(polygonBoundPoints: mapPoints)
// move map
coreMapView.zoomToPolygon(polygon: polygon)// make sure to call this after we hang the DnDSign
// allow map movement and disable drawing
coreMapView.isScrollEnabled = true
coreMapView.isZoomEnabled = true
coreMapView.isUserInteractionEnabled = true
}
func convertPointsToCords(points:[CGPoint]) -> [CLLocationCoordinate2D] {
var mapPoints = [CLLocationCoordinate2D]()
for point in points {
let convertedPoint = mapDrawView.convert(point, to: coreMapView)
let coordinate = coreMapView.convert(convertedPoint, toCoordinateFrom: coreMapView)
mapPoints.append(coordinate)
}
return mapPoints
}
如果你想要像我这里那样的倒多边形是世界多边形,所以你可以在里面设置你的。
func getWorldPoly() -> [CLLocationCoordinate2D] {
return [CLLocationCoordinate2D(latitude: 90, longitude: 0),
CLLocationCoordinate2D(latitude: 90, longitude: 180),
CLLocationCoordinate2D(latitude: -90, longitude: 180),
CLLocationCoordinate2D(latitude: -90, longitude: 0),
CLLocationCoordinate2D(latitude: -90, longitude: -180),
CLLocationCoordinate2D(latitude: 90, longitude: 180)]
}