La mejor manera que he encontrado para lograr esto es con un Gesture Recognizer. Otras formas implican una gran cantidad de programación pirateada que duplica imperfectamente el código de Apple, especialmente en el caso de multitouch.
Esto es lo que hago: Implemento un reconocedor de gestos que no se puede prevenir y que no puede evitar otros reconocedores de gestos. Agréguelo a la vista del mapa, y luego use el gestoRecognizer's touchesBegan, touchesMoved, etc. a su gusto.
Cómo detectar cualquier toque dentro de un MKMapView (sin trucos)
WildcardGestureRecognizer * tapInterceptor = [[WildcardGestureRecognizer alloc] init];
tapInterceptor.touchesBeganCallback = ^(NSSet * touches, UIEvent * event) {
self.lockedOnUserLocation = NO;
};
[mapView addGestureRecognizer:tapInterceptor];
WildcardGestureRecognizer.h
//
// WildcardGestureRecognizer.h
// Copyright 2010 Floatopian LLC. All rights reserved.
//
#import <Foundation/Foundation.h>
typedef void (^TouchesEventBlock)(NSSet * touches, UIEvent * event);
@interface WildcardGestureRecognizer : UIGestureRecognizer {
TouchesEventBlock touchesBeganCallback;
}
@property(copy) TouchesEventBlock touchesBeganCallback;
@end
WildcardGestureRecognizer.m
//
// WildcardGestureRecognizer.m
// Created by Raymond Daly on 10/31/10.
// Copyright 2010 Floatopian LLC. All rights reserved.
//
#import "WildcardGestureRecognizer.h"
@implementation WildcardGestureRecognizer
@synthesize touchesBeganCallback;
-(id) init{
if (self = [super init])
{
self.cancelsTouchesInView = NO;
}
return self;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if (touchesBeganCallback)
touchesBeganCallback(touches, event);
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
}
- (void)reset
{
}
- (void)ignoreTouch:(UITouch *)touch forEvent:(UIEvent *)event
{
}
- (BOOL)canBePreventedByGestureRecognizer:(UIGestureRecognizer *)preventingGestureRecognizer
{
return NO;
}
- (BOOL)canPreventGestureRecognizer:(UIGestureRecognizer *)preventedGestureRecognizer
{
return NO;
}
@end
SWIFT 3
let tapInterceptor = WildCardGestureRecognizer(target: nil, action: nil)
tapInterceptor.touchesBeganCallback = {
_, _ in
self.lockedOnUserLocation = false
}
mapView.addGestureRecognizer(tapInterceptor)
WildCardGestureRecognizer.swift
import UIKit.UIGestureRecognizerSubclass
class WildCardGestureRecognizer: UIGestureRecognizer {
var touchesBeganCallback: ((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 canPrevent(_ preventedGestureRecognizer: UIGestureRecognizer) -> Bool {
return false
}
override func canBePrevented(by preventingGestureRecognizer: UIGestureRecognizer) -> Bool {
return false
}
}
video
etiqueta HTML5 con controles, el reconocedor de gestos evitará que el usuario pueda usar los controles. He estado buscando una solución alternativa para esto, pero todavía tengo que encontrar una.Después de un día de pizzas, gritos, ¡finalmente encontré la solución! ¡Muy aseado!
Peter, utilicé tu truco anterior y lo modifiqué un poco para finalmente tener una solución que funcione perfectamente con MKMapView y debería funcionar también con UIWebView
MKTouchAppDelegate.h
MKTouchAppDelegate.m
UIViewTouch.h
UIViewTouch.m
¡Espero que eso ayude a algunos de ustedes!
Salud
fuente
fuente
¡Para un MKMapView, la verdadera solución de trabajo es el reconocimiento de gestos!
Yo Quería dejar de actualizar el centro del mapa en mi ubicación cuando arrastro el mapa o pellizco para hacer zoom.
Entonces, crea y agrega tu reconocedor de gestos al mapView:
Consulte la referencia de clase de UIGestureRecognizer para ver todos los reconocedores de gestos disponibles.
Debido a que hemos definido el delegado a sí mismo, tenemos que implementar el protocolo UIGestureRecognizerDelegate:
Y anule el método gestoRecognizer: gestoRecognizer shouldRecognizeSimuallyWithGestureRecognizer: para permitir reconocer múltiples gestos simultáneamente, si entendí bien:
Ahora escriba los métodos que serán llamados por nuestros reconocedores de gestos:
fuente
En caso de que alguien esté intentando hacer lo mismo que yo: quería crear una anotación en el punto donde el usuario toca. Para eso usé la
UITapGestureRecognizer
solución:Sin embargo,
didTapOnMap:
también se llamó cuando hice tapping en la anotación y se crearía una nueva. La solución es implementarUIGestureRecognizerDelegate
:fuente
MKAnnotation
. En este caso, es posible que la subvista de otra anotación active el reconocedor de gestos. Tuve que comprobar de forma recursiva la supervista de touch.view para encontrar un MKAnnotationView potencialProbablemente necesitará superponer una vista transparente para captar los toques como se hace tan a menudo con los controles basados en UIWebView. La Vista del mapa ya hace un montón de cosas especiales con un toque para permitir que el mapa se mueva, centre, amplíe, etc. para que los mensajes no lleguen a su aplicación.
Otras dos opciones (NO PROBADAS) en las que puedo pensar:
1) Renuncie al primer respondedor a través de IB y configúrelo en "Propietario del archivo" para permitir que el propietario del archivo responda a los toques. Dudo que esto funcione porque MKMapView extiende NSObject, no UIView y, como resultado, es posible que los eventos táctiles aún no se propaguen hasta usted.
2) Si desea capturar cuando el estado del mapa cambia (como en un zoom) simplemente implemente el protocolo MKMapViewDelegate para escuchar eventos particulares. Mi corazonada es que esta es su mejor oportunidad para atrapar alguna interacción fácilmente (salvo implementar la Vista transparente sobre el mapa). No olvide configurar el controlador de vista que aloja MKMapView como delegado del mapa (
map.delegate = self
).Buena suerte.
fuente
No he experimentado, pero es muy probable que MapKit se base en un clúster de clases y, por lo tanto, crear subclases es difícil e ineficaz.
Sugeriría hacer que la vista MapKit sea una subvista de una vista personalizada, lo que debería permitirle interceptar eventos táctiles antes de que lleguen a ella.
fuente
Entonces, después de medio día de jugar con esto, encontré lo siguiente:
En los videos del iPhone de Stanford, un tipo de Apple dice que muchas de las cosas de UIKit causarán muchos errores si "transfieres" las solicitudes táctiles (también conocidas como los dos métodos descritos anteriormente), y probablemente no conseguirás que funcione.
LA SOLUCIÓN : se describe aquí: Interceptación / Secuestro de eventos táctiles de iPhone para MKMapView . Básicamente, "captas" el evento antes de que lo reciba cualquier respondedor y lo interpretas allí.
fuente
En Swift 3.0
fuente
Haga de MKMapView una subvista de una vista personalizada e implemente
en la vista personalizada para devolver self en lugar de la subvista.
fuente
Gracias por la pizza y los gritos, me ahorraste mucho tiempo.
multipletouchenabled funcionará esporádicamente.
Al final, cambié las vistas cuando necesitaba capturar el toque (un punto en el tiempo diferente al de necesitar pellizcos):
fuente
Noto que puede rastrear el número y la ubicación de los toques y obtener la ubicación de cada uno en una vista:
¿Alguien más ha intentado usar estos valores para actualizar el nivel de zoom del mapa? Sería cuestión de registrar las posiciones de inicio y luego las posiciones de llegada, calcular la diferencia relativa y actualizar el mapa.
Estoy jugando con el código básico proporcionado por Martin, y parece que funcionará ...
fuente
Esto es lo que reuní, que permite pellizcar zoom en el simulador (no lo he probado en un iPhone real), pero creo que estaría bien:
La idea principal es que si el usuario usa dos dedos, usted rastrea los valores. Grabo los puntos de inicio y finalización en los puntos de inicio A y B. Luego, registro los puntos de seguimiento actuales, y cuando termino, en touchchesEnded, puedo llamar a una rutina para calcular las longitudes relativas de la línea entre los puntos con los que comienzo , y la línea entre el punto con el que termino usando calc. La relación entre ellos es la cantidad de zoom: multiplico el intervalo de la región por esa cantidad.
Espero que sea útil para alguien.
fuente
Tomé la idea de una vista transparente "superpuesta", de la respuesta de MystikSpiral, y funcionó perfectamente para lo que estaba tratando de lograr; Solución rápida y limpia.
En resumen, tenía un UITableViewCell personalizado (diseñado en IB) con un MKMapView en el lado izquierdo y algunos UILabels en el derecho. Quería hacer la celda personalizada para que pudiera tocarla en cualquier lugar y esto impulsaría un nuevo controlador de vista. Sin embargo, tocar el mapa no pasó toques 'hacia arriba' a UITableViewCell hasta que simplemente agregué una UIView del mismo tamaño que la vista del mapa justo encima (en IB) e hice que su fondo fuera el 'color claro' en el código ( ¿No crees que puedes establecer clearColor en IB ??):
Pensé que podría ayudar a alguien más; ciertamente, si desea lograr el mismo comportamiento para una celda de vista de tabla.
fuente