我正在尝试在我的mapView上实现自定义手势识别器,这将阻止用户放大或缩小超过MKCoordinateSpan设置的某个阈值。
mapView的ViewController是选项卡栏Controller的一部分,因此,每当视图消失时,我都会删除mapView,并出于内存目的重新添加它。
自从我添加了“自定义手势识别器”以来,视图消失时不会释放内存。除了从mapView中删除手势识别器之外,我还缺少什么?
MapViewController:
class MapViewController: UIViewController, CLLocationManagerDelegate {
@IBOutlet var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
loadMapView()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if mapView == nil {
loadMapView()
}
}
override func viewDidDisappear(_ animated:Bool) {
super.viewDidDisappear(animated)
self.applyMapViewMemoryFix()
}
func loadMapView() {
self.edgesForExtendedLayout = []
setMapView()
}
func setMapView() {
if self.mapView == nil {
addMapView()
}
mapView.delegate = self
mapView.mapType = .mutedStandard
mapView.autoresizingMask = [.flexibleWidth,.flexibleHeight]
}
func addMapView() {
mapView = MKMapView()
mapView.frame = self.navigationController!.view.bounds
mapView.mapType = MKMapType.standard
mapView.isZoomEnabled = true
mapView.isScrollEnabled = true
self.view.addSubview(mapView)
}
func applyMapViewMemoryFix() {
for recognizer in (self.mapView?.gestureRecognizers)! {
if recognizer is WildCardGestureRecognizer {
self.mapView.removeGestureRecognizer(recognizer)
}
}
self.mapView.showsUserLocation = false
self.mapView.delegate = nil
self.mapView.removeFromSuperview()
self.mapView = nil
}
}
我在其中为手势识别器设置边界的扩展:
extension MapViewController: MKMapViewDelegate {
// View Region Changing
func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
let northernBorder = 32.741152
let southernBorder = 32.731461
let easternBorder = -117.143622
let westernBorder = -117.157399
var latitude = mapView.region.center.latitude
var longitude = mapView.region.center.longitude
if (mapView.region.center.latitude > northernBorder) {
latitude = northernBorder
}
if (mapView.region.center.latitude < southernBorder) {
latitude = southernBorder
}
if (mapView.region.center.longitude > easternBorder) {
longitude = easternBorder
}
if (mapView.region.center.longitude < westernBorder) {
longitude = westernBorder
}
let tapInterceptor = WildCardGestureRecognizer(target: nil, action: nil)
tapInterceptor.touchesBeganCallback = {_, _ in
mapView.isZoomEnabled = true
}
tapInterceptor.touchesMovedCallback = {_, _ in
if tapInterceptor.scale < 1 {
if (latitude != mapView.region.center.latitude || longitude != mapView.region.center.longitude)
|| ((mapView.region.span.latitudeDelta > (northernBorder - southernBorder) )
|| (mapView.region.span.longitudeDelta > (easternBorder - westernBorder))) {
let span = MKCoordinateSpan.init(latitudeDelta: 0.007, longitudeDelta: 0.007)
if mapView.region.span.latitudeDelta > span.latitudeDelta || mapView.region.span.longitudeDelta > span.longitudeDelta {
mapView.isZoomEnabled = false
} else {
mapView.isZoomEnabled = true
}
}
} else if tapInterceptor.scale > 1 {
let minimumSpan = MKCoordinateSpan.init(latitudeDelta: 0.002, longitudeDelta: 0.002)
if mapView.region.span.latitudeDelta < minimumSpan.latitudeDelta || mapView.region.span.longitudeDelta < minimumSpan.longitudeDelta {
mapView.isZoomEnabled = false
} else {
mapView.isZoomEnabled = true
}
}
}
tapInterceptor.touchesEndedCallback = {_, _ in
mapView.isZoomEnabled = true
}
mapView.addGestureRecognizer(tapInterceptor)
}
}
自定义手势识别器:
class WildCardGestureRecognizer: UIPinchGestureRecognizer {
var touchesBeganCallback: ((Set<UITouch>, UIEvent) -> Void)?
var touchesMovedCallback: ((Set<UITouch>, UIEvent) -> Void)?
var touchesEndedCallback: ((Set<UITouch>, UIEvent) -> Void)?
override init(target: Any?, action: Selector?) {
super.init(target: target, action: action)
self.cancelsTouchesInView = false
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
super.touchesBegan(touches, with: event)
touchesBeganCallback?(touches, event)
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent) {
super.touchesMoved(touches, with: event)
touchesMovedCallback?(touches, event)
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent) {
super.touchesEnded(touches, with: event)
touchesEndedCallback?(touches, event)
}
override func canPrevent(_ preventedGestureRecognizer: UIGestureRecognizer) -> Bool {
return false
}
override func canBePrevented(by preventingGestureRecognizer: UIGestureRecognizer) -> Bool {
return false
}
}
答案 0 :(得分:1)
在此处声明手势时内存泄漏
let tapInterceptor = WildCardGestureRecognizer(target: nil, action: nil)
.
.
.
mapView.addGestureRecognizer(tapInterceptor)
在regionDidChangeAnimated
内,由于多次调用,随着区域的变化,您会在地图视图中添加许多手势,因此最好创建像
var tapInterceptor:WildCardGestureRecognizer!
并在函数内部添加手势init和回调,然后将其称为viewDidLoad
还删除@IBOutle
@IBOutlet var mapView: MKMapView!
如果您不将其放置在Storyboard中,我也不认为删除/添加方式会有所作为,因为IOS中对象的解除分配始终不会释放整个组件,因此最好将mapview与这只是一个手势,而不是在选择/取消选择水龙头
时从丢失的水流中累积大量泄漏