Как перехватить события касаний на объектах MKMapView или UIWebView?

96

Я не уверен, что делаю не так, но стараюсь улавливать прикосновения к MKMapViewобъекту. Я разделил его на подклассы, создав следующий класс:

#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>

@interface MapViewWithTouches : MKMapView {

}

- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *) event;   

@end

И реализация:

#import "MapViewWithTouches.h"
@implementation MapViewWithTouches

- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *) event {

    NSLog(@"hello");
    //[super touchesBegan:touches   withEvent:event];

}
@end

Но похоже, что когда я использую этот класс, я ничего не вижу в консоли:

MapViewWithTouches *mapView = [[MapViewWithTouches alloc] initWithFrame:self.view.frame];
[self.view insertSubview:mapView atIndex:0];

Есть идеи, что я делаю не так?

Мартин
источник

Ответы:

147

Я нашел лучший способ добиться этого с помощью распознавателя жестов. Оказывается, что другие способы включают в себя множество хакерских программ, которые несовершенно дублируют код Apple, особенно в случае мультитач.

Вот что я делаю: реализую распознаватель жестов, который нельзя предотвратить и который не может предотвратить другие распознаватели жестов. Добавьте его в представление карты, а затем используйте touchesBegan, touchesMoved и т. Д. Для gestureRecognizer по своему усмотрению.

Как обнаружить любой кран внутри MKMapView (без трюков)

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
    }
}
гонзойв
источник
3
для чего "lockedOnUserLocation"?
jowie
это посторонняя переменная, специфичная для моего приложения. он отслеживает, должна ли система автоматически
центрировать
Это отличное решение. Мне нужно одно пояснение: какова цель использования кода в методе «- (void) touchesBegan: (NSSet *) touch withEvent: (UIEvent *)»: if (touchesBeganCallback) touchesBeganCallback (touches, event);
Satyam
1
По большей части это отлично работает, но я обнаружил одну проблему. Если HTML-код в вашем веб-представлении содержит videoтег HTML5 с элементами управления, распознаватель жестов не позволит пользователю использовать элементы управления. Я искал обходной путь для этого, но еще не нашел его.
Брайан Ирейс 01
Спасибо, что поделились. Я не понимаю, почему нет подходящего метода делегирования для отслеживания взаимодействия пользователя с видом карты, но он работает хорошо.
Джастин Дрисколл,
29

После дня пиццы и криков я наконец нашел решение! Очень аккуратный!

Питер, я использовал ваш трюк выше и немного изменил его, чтобы наконец получить решение, которое отлично работает с MKMapView и должно также работать с UIWebView.

MKTouchAppDelegate.h

#import <UIKit/UIKit.h>
@class UIViewTouch;
@class MKMapView;

@interface MKTouchAppDelegate : NSObject <UIApplicationDelegate> {
    UIWindow *window;
    UIViewTouch *viewTouch;
    MKMapView *mapView;
}
@property (nonatomic, retain) UIViewTouch *viewTouch;
@property (nonatomic, retain) MKMapView *mapView;
@property (nonatomic, retain) IBOutlet UIWindow *window;

@end

MKTouchAppDelegate.m

#import "MKTouchAppDelegate.h"
#import "UIViewTouch.h"
#import <MapKit/MapKit.h>

@implementation MKTouchAppDelegate

@synthesize window;
@synthesize viewTouch;
@synthesize mapView;


- (void)applicationDidFinishLaunching:(UIApplication *)application {

    //We create a view wich will catch Events as they occured and Log them in the Console
    viewTouch = [[UIViewTouch alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];

    //Next we create the MKMapView object, which will be added as a subview of viewTouch
    mapView = [[MKMapView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
    [viewTouch addSubview:mapView];

    //And we display everything!
    [window addSubview:viewTouch];
    [window makeKeyAndVisible];


}


- (void)dealloc {
    [window release];
    [super dealloc];
}


@end

UIViewTouch.h

#import <UIKit/UIKit.h>
@class UIView;

@interface UIViewTouch : UIView {
    UIView *viewTouched;
}
@property (nonatomic, retain) UIView * viewTouched;

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event;

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;

@end

UIViewTouch.m

#import "UIViewTouch.h"
#import <MapKit/MapKit.h>

@implementation UIViewTouch
@synthesize viewTouched;

//The basic idea here is to intercept the view which is sent back as the firstresponder in hitTest.
//We keep it preciously in the property viewTouched and we return our view as the firstresponder.
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    NSLog(@"Hit Test");
    viewTouched = [super hitTest:point withEvent:event];
    return self;
}

//Then, when an event is fired, we log this one and then send it back to the viewTouched we kept, and voilà!!! :)
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    NSLog(@"Touch Began");
    [viewTouched touchesBegan:touches withEvent:event];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    NSLog(@"Touch Moved");
    [viewTouched touchesMoved:touches withEvent:event];
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    NSLog(@"Touch Ended");
    [viewTouched touchesEnded:touches withEvent:event];
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
    NSLog(@"Touch Cancelled");
}

@end

Я надеюсь, что это поможет некоторым из вас!

Ура

Мартин
источник
14
Ницца. Небольшое предложение: вам следует избегать именования собственных классов с префиксом пользовательского интерфейса. Apple резервирует / не рекомендует использовать NS или UI в качестве префикса класса, потому что они могут в конечном итоге конфликтовать с классом Apple (даже если это частный класс).
Дэниел Дикисон,
Эй, Дэниел, ты совершенно прав, я тоже так думала! Чтобы завершить свой ответ выше, позвольте мне добавить небольшое предупреждение: в моем примере предполагается, что существует только один объект viewTouched, который использует все события. Но это неправда. У вас может быть несколько аннотаций поверх вашей карты, и тогда мой код больше не работает. Чтобы работать на 100%, вам нужно запомнить для каждого hitTest представление, связанное с этим конкретным событием (и в конечном итоге отпустить его, когда срабатывает touchesEnded или touchesCancelled, поэтому вам не нужно отслеживать завершенные события ...).
Мартин
1
Очень полезный код, спасибо, Мартин! Мне было интересно, пробовали ли вы масштабировать карту щипком после этого? Для меня, когда я заставил его работать, используя в основном тот же код, что и у вас выше, все работало, кроме масштабирования карты щипком. У кого-нибудь есть идеи?
Adam Alexander
Привет, Адам, у меня тоже есть это ограничение, и я действительно не понимаю, почему! Это действительно раздражает. Если найдете решение, дайте мне знать! Спасибо
Мартин
Хорошо, я проголосовал за это, потому что изначально казалось, что он решает мою проблему. ТЕМ НЕ МЕНИЕ...! Я не могу заставить работать мультитач. То есть, даже несмотря на то, что я напрямую передаю touchesBegan и touchesMoved для viewTouched (я выполняю перехват на touchEnded), я не могу масштабировать карту с помощью жестов сжатия. (Продолжение ...)
Оли
24
UITapGestureRecognizer *tgr = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(handleGesture:)];   
tgr.numberOfTapsRequired = 2;
tgr.numberOfTouchesRequired = 1;
[mapView addGestureRecognizer:tgr];
[tgr release];


- (void)handleGesture:(UIGestureRecognizer *)gestureRecognizer
{
    if (gestureRecognizer.state != UIGestureRecognizerStateEnded)
        return;

    CGPoint touchPoint = [gestureRecognizer locationInView:mapView];
    CLLocationCoordinate2D touchMapCoordinate = [mapView convertPoint:touchPoint toCoordinateFromView:mapView];

    //.............
}
Говинд
источник
3
Я не уверен, почему это не лучший ответ. Кажется, работает отлично, и это намного проще.
elsurudo
12

Для MKMapView настоящее рабочее решение - распознавание жестов!

Я хотел перестать обновлять центр карты относительно моего местоположения, когда я перетаскиваю карту или зажимаю пальцы для увеличения.

Итак, создайте и добавьте свой распознаватель жестов в mapView:

- (void)viewDidLoad {

    ...

    // Add gesture recognizer for map hoding
    UILongPressGestureRecognizer *longPressGesture = [[[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPressAndPinchGesture:)] autorelease];
    longPressGesture.delegate = self;
    longPressGesture.minimumPressDuration = 0;  // In order to detect the map touching directly (Default was 0.5)
    [self.mapView addGestureRecognizer:longPressGesture];

    // Add gesture recognizer for map pinching
    UIPinchGestureRecognizer *pinchGesture = [[[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPressAndPinchGesture:)] autorelease];
    pinchGesture.delegate = self;
    [self.mapView addGestureRecognizer:pinchGesture];

    // Add gesture recognizer for map dragging
    UIPanGestureRecognizer *panGesture = [[[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanGesture:)] autorelease];
    panGesture.delegate = self;
    panGesture.maximumNumberOfTouches = 1;  // In order to discard dragging when pinching
    [self.mapView addGestureRecognizer:panGesture];
}

Посмотрите ссылку на класс UIGestureRecognizer, чтобы увидеть все доступные средства распознавания жестов.

Поскольку мы определили делегата для себя, мы должны реализовать протокол UIGestureRecognizerDelegate:

typedef enum {
    MapModeStateFree,                    // Map is free
    MapModeStateGeolocalised,            // Map centred on our location
    MapModeStateGeolocalisedWithHeading  // Map centred on our location and oriented with the compass
} MapModeState;

@interface MapViewController : UIViewController <CLLocationManagerDelegate, UIGestureRecognizerDelegate> {
    MapModeState mapMode;
}

@property (nonatomic, retain) IBOutlet MKMapView *mapView;
...

И переопределите метод gestureRecognizer: gestureRecognizer shouldRecognizeSimuallyWithGestureRecognizer: чтобы разрешить одновременное распознавание нескольких жестов, если я правильно понял:

// Allow to recognize multiple gestures simultaneously (Implementation of the protocole UIGestureRecognizerDelegate)
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
    return YES;
}

Теперь напишите методы, которые будут вызываться нашими распознавателями жестов:

// On map holding or pinching pause localise and heading
- (void)handleLongPressAndPinchGesture:(UIGestureRecognizer *)sender {
    // Stop to localise and/or heading
    if (sender.state == UIGestureRecognizerStateBegan && mapMode != MapModeStateFree) {
        [locationManager stopUpdatingLocation];
        if (mapMode == MapModeStateGeolocalisedWithHeading) [locationManager stopUpdatingHeading];
    }
    // Restart to localise and/or heading
    if (sender.state == UIGestureRecognizerStateEnded && mapMode != MapModeStateFree) {
        [locationManager startUpdatingLocation];
        if (mapMode == MapModeStateGeolocalisedWithHeading) [locationManager startUpdatingHeading];
    }
}

// On dragging gesture put map in free mode
- (void)handlePanGesture:(UIGestureRecognizer *)sender {
    if (sender.state == UIGestureRecognizerStateBegan && mapMode != MapModeStateFree) [self setMapInFreeModePushedBy:sender];
}
Джоан
источник
Это решение идеальное! Вот несколько быстрых подсказок: если вы хотите перехватить, когда пользователь заканчивает выполнение каких-либо действий с использованием этого, должно быть достаточно - (void) handleLongPressAndPinchGesture: (UIGestureRecognizer *) sender {if (sender.state == UIGestureRecognizerStateEnded) {NSLog (@ "handleLongPressAndPinchGest) ; }}
Алехандро Луенго
Также не забудьте добавить делегата <UIGestureRecognizerDelegate>
Алехандро Луенго
6

На всякий случай кто-то пытается сделать то же самое, как я: я хотел создать аннотацию в точке, где пользователь нажимает. Для этого я использовал UITapGestureRecognizerрешение:

UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTapOnMap:)];
[self.mapView addGestureRecognizer:tapGestureRecognizer];
[tapGestureRecognizer setDelegate:self];

- (void)didTapOnMap:(UITapGestureRecognizer *)gestureRecognizer
{
    CGPoint point = [gestureRecognizer locationInView:self.mapView];
    CLLocationCoordinate2D coordinate = [self.mapView convertPoint:point toCoordinateFromView:self.mapView];
    .......
}

Однако didTapOnMap:он также вызывался, когда я нажимал на аннотацию и создавал новую. Решение состоит в том, чтобы реализовать UIGestureRecognizerDelegate:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
    if ([touch.view isKindOfClass:[MKAnnotationView class]])
    {
        return NO;
    }
    return YES;
}
джимпик
источник
Это отличное решение! Но это не работает, если вы используете пользовательское представление как MKAnnotation. В этом случае у вас может быть подпредставление другой аннотации, запускающее распознаватель жестов. Мне пришлось рекурсивно проверить супервизор touch.view, чтобы найти потенциальный MKAnnotationView
KIDdAe
3

Вам, вероятно, потребуется наложение прозрачного представления, чтобы улавливать касания, как это часто делается с элементами управления на основе UIWebView. Просмотр карты уже выполняет ряд специальных функций касанием, чтобы можно было перемещать карту, центрировать, масштабировать и т. Д., Чтобы сообщения не попадали в ваше приложение.

Я могу придумать еще два (НЕПРОВЕРЕННЫХ) варианта:

1) Подайте в отставку первого респондента через IB и установите для него значение «Владелец файла», чтобы позволить владельцу файла отвечать на прикосновения. Я сомневаюсь, что это сработает, потому что MKMapView расширяет NSObject, а не UIView, и в результате события касания все еще могут не распространяться на вас.

2) Если вы хотите поймать при изменении состояния карты (например, при увеличении), просто реализуйте протокол MKMapViewDelegate для прослушивания определенных событий. Я предполагаю, что это ваш лучший способ легко захватить какое-либо взаимодействие (если не считать реализации прозрачного вида поверх карты). Не забудьте установить View Controller, содержащий MKMapView, в качестве делегата карты ( map.delegate = self).

Удачи.

MystikSpiral
источник
MKMapView определенно является подклассом UIView.
Дэниел Дикисон
2

Я не экспериментировал, но есть большая вероятность, что MapKit основан на кластере классов, и поэтому создание его подклассов сложно и неэффективно.

Я бы предложил сделать представление MapKit подвидом пользовательского представления, которое должно позволить вам перехватывать события касания до того, как они достигнут его.

грэмпарки
источник
Привет, Грэм! Спасибо за помощь! Если я сделаю супер настраиваемый вид, как вы предлагаете, как я могу затем перенаправить события в MKMapView? Любая идея?
Мартин
2

Итак, после полдня возиться с этим я обнаружил следующее:

  1. Как выяснили все, щипание не работает. Я пробовал создать подкласс MKMapView и метод, описанный выше (перехватывая его). И результат тот же.
  2. В видеороликах Stanford iPhone парень из Apple говорит, что многие вещи UIKit вызовут множество ошибок, если вы «передадите» запросы касания (то есть два метода, описанных выше), и вы, вероятно, не заставите его работать.

  3. РЕШЕНИЕ : описано здесь: Перехват / захват событий касания iPhone для MKMapView . По сути, вы «ловите» событие до того, как его получит ответчик, и интерпретируете его там.

thuang513
источник
2

В Swift 3.0

import UIKit
import MapKit

class CoordinatesPickerViewController: UIViewController {

    @IBOutlet var mapView: MKMapView!
    override func viewDidLoad() {
        super.viewDidLoad()

        let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(clickOnMap))
        mapView.addGestureRecognizer(tapGestureRecognizer)
    }

    @objc func clickOnMap(_ sender: UITapGestureRecognizer) {

        if sender.state != UIGestureRecognizerState.ended { return }
        let touchLocation = sender.location(in: mapView)
        let locationCoordinate = mapView.convert(touchLocation, toCoordinateFrom: mapView)
        print("Tapped at lat: \(locationCoordinate.latitude) long: \(locationCoordinate.longitude)")

    }

}
Франсиско Кастро
источник
0

Сделайте MKMapView подвидом пользовательского представления и реализуйте

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event

в пользовательском представлении, чтобы вернуть self вместо subview.

Питер Н. Льюис
источник
Привет, Питер, спасибо за ответ! Но я думаю, что, сделав это, MKMapView, возможно, не сможет получить какие-либо события касания, не так ли? Я ищу способ просто поймать событие, а затем переслать его в MKMapView.
Мартин
0

Спасибо за пиццу и крики - вы сэкономили мне много времени.

multitouchenabled будет работать время от времени.

viewTouch.multipleTouchEnabled = TRUE;

В конце концов, я отключил виды, когда мне нужно было уловить прикосновение (другой момент времени, чем когда мне нужны щипки):

    [mapView removeFromSuperview];
    [viewTouch addSubview:mapView];
    [self.view insertSubview:viewTouch atIndex:0];
BankStrong
источник
но не работает с масштабированием в реальном времени. Также кажется, что всегда уменьшать масштаб.
Rog
0

Я заметил, что вы можете отслеживать количество и расположение касаний и получать местоположение каждого в виде:

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    NSLog(@"Touch Moved %d", [[event allTouches] count]);

 NSEnumerator *enumerator = [touches objectEnumerator];
 id value;

 while ((value = [enumerator nextObject])) {
  NSLog(@"touch description %f", [value locationInView:mapView].x);
 }
    [viewTouched touchesMoved:touches withEvent:event];
}

Кто-нибудь еще пробовал использовать эти значения для обновления уровня масштабирования карты? Это будет вопрос записи начальных позиций, а затем конечных точек, вычисления относительной разницы и обновления карты.

Я играю с базовым кодом, предоставленным Мартином, и похоже, что он будет работать ...

Дэн Дональдсон
источник
0

Вот то, что я собрал, что позволяет увеличивать масштаб в симуляторе (не пробовал на настоящем iPhone), но я думаю, что все будет хорошо:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    NSLog(@"Touch Began %d", [touches count]);
 reportTrackingPoints = NO;
 startTrackingPoints = YES;
    [viewTouched touchesBegan:touches withEvent:event];
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
 if ([[event allTouches] count] == 2) {
  reportTrackingPoints = YES;
  if (startTrackingPoints == YES) {
   BOOL setA = NO;
   NSEnumerator *enumerator = [[event allTouches] objectEnumerator];
   id value;
   while ((value = [enumerator nextObject])) {
    if (! setA) {
     startPointA = [value locationInView:mapView];
     setA = YES;
    } else {
     startPointB = [value locationInView:mapView];
    }
   }
   startTrackingPoints = NO;
  } else {
   BOOL setA = NO;
   NSEnumerator *enumerator = [[event allTouches] objectEnumerator];
   id value;
   while ((value = [enumerator nextObject])) {
    if (! setA) {
     endPointA = [value locationInView:mapView];
     setA = YES;
    } else {
     endPointB = [value locationInView:mapView];
    }
   }
  }
 }
 //NSLog(@"Touch Moved %d", [[event allTouches] count]);
    [viewTouched touchesMoved:touches withEvent:event];
}

- (void) updateMapFromTrackingPoints {
 float startLenA = (startPointA.x - startPointB.x);
 float startLenB = (startPointA.y - startPointB.y);
 float len1 = sqrt((startLenA * startLenA) + (startLenB * startLenB));
 float endLenA = (endPointA.x - endPointB.x);
 float endLenB = (endPointA.y - endPointB.y);
 float len2 = sqrt((endLenA * endLenA) + (endLenB * endLenB));
 MKCoordinateRegion region = mapView.region;
 region.span.latitudeDelta = region.span.latitudeDelta * len1/len2;
 region.span.longitudeDelta = region.span.longitudeDelta * len1/len2;
 [mapView setRegion:region animated:YES];
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
 if (reportTrackingPoints) {
  [self updateMapFromTrackingPoints];
  reportTrackingPoints = NO;
 }


    [viewTouched touchesEnded:touches withEvent:event];
}

Основная идея заключается в том, что если пользователь использует два пальца, вы отслеживаете значения. Я записываю начальную и конечную точки в startPoints A и B. Затем я записываю текущие точки отслеживания, и когда я закончу, на touchesEnded я могу вызвать процедуру для вычисления относительной длины линии между точками, с которых я начинаю. , а линия между точкой I заканчивается простым вычислением гипотенузы. Соотношение между ними и есть величина увеличения: я умножаю диапазон области на эту величину.

Надеюсь, это кому-то пригодится.

Дэн Дональдсон
источник
0

Я взял идею «оверлейного» прозрачного представления из ответа MystikSpiral, и он отлично сработал для того, чего я пытался достичь; быстрое и чистое решение.

Короче говоря, у меня был собственный UITableViewCell (разработанный в IB) с MKMapView слева и некоторыми UILabels справа. Я хотел сделать пользовательскую ячейку, чтобы вы могли касаться ее где угодно, и это подтолкнуло бы к новому контроллеру представления. Однако прикосновение к карте не передавало касаний «вверх» UITableViewCell, пока я просто не добавил UIView того же размера, что и вид карты, прямо поверх него (в IB) и не сделал его фоном «прозрачным цветом» в коде ( не думаю, что вы можете установить clearColor в IB ??):

dummyView.backgroundColor = [UIColor clearColor];

Думал, что это может помочь кому-то другому; конечно, если вы хотите добиться того же поведения для ячейки табличного представления.

Питер
источник
«Однако прикосновение к карте не передавало прикосновений« вверх »к UITableViewCell, пока я просто не добавил UIView того же размера, что и вид карты, прямо поверх него» Это неверно. Карта обрабатывает касания, потому что у нее есть собственные взаимодействия с пользователем, такие как прокрутка и т. Д. Если вы хотите обнаружить хотя в ячейке вместо взаимодействия с картой, просто установите map.isUserInteractionEnabled = false Затем вы можете просто использовать didSelectRowAtIndexPath в таблице просмотр делегата.
BROK3N S0UL