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などを使いこなしてください。

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」の目的は何ですか?
ジョウイ

それは私のアプリケーションに固有の無関係な変数です。システムが地図を現在地に自動的に配置するかどうかを追跡します
gonzojive

これは完璧なソリューションです。1つの明確化が必要です。「-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event」メソッドで、コードを使用する目的は何ですか。
サティヤム

1
これはほとんどの部分で問題なく動作しますが、1つの問題が見つかりました。WebビューのHTMLにvideoコントロール付きのHTML5 タグが含まれている場合、ジェスチャー認識機能により、ユーザーはコントロールを使用できなくなります。私はこれの回避策を探していましたが、まだ見つけていません。
ブライアンイレース

共有していただきありがとうございます。マップビューでのユーザーインタラクションを追跡するための適切なデリゲートメソッドがない理由は私には理解できませんが、これはうまく機能します。
Justin Driscoll

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
いいね。小さな提案:UI接頭辞を使用して独自のクラスに名前を付けることは避けてください。Appleは、NSまたはUIをクラスのプレフィックスとして使用することを予約または推奨します。これは、これらが(プライベートクラスであっても)Appleクラスと競合する可能性があるためです。
ダニエルディキソン09年

ちょっとダニエル、あなたは完全に正しいです、私もそう思いました!上記の私の回答を完了するために、少し警告を追加します。私の例では、すべてのイベントを消費しているオブジェクトviewTouchedが1つだけあると想定しています。しかし、それは真実ではありません。マップの上にいくつかの注釈を付けると、私のコードが機能しなくなります。100%動作させるには、各hitTestについて、その特定のイベントに関連付けられたビューを覚えておく必要があります(最終的に、touchesEndedまたはtouchesCancelledがトリガーされたときに解放して、完了したイベントを追跡する必要がないようにします...)。
マーティン

1
非常に便利なコード、マーティンに感謝します!これを実装した後でマップをピンチズームしようとしたのかどうか疑問に思いましたか?私にとって、基本的に同じコードを使用して機能させると、マップをピンチズームする以外は、すべてが機能するように見えました。誰かアイデアはありますか?
アダムアレクサンダー

こんにちは、アダム、私にもこの制限があり、理由がよくわかりません!それは本当に迷惑です。解決策を見つけたら、私に知らせてください!Thx
マーティン

最初に問題を解決したように見えたので、これに投票しました。しかしながら...!マルチタッチが機能しないようです。つまり、直接touchesBeganとtouchesMovedを渡してviewTouchedに渡しました(touchesEndedでインターセプトを実行しています)が、ピンチジェスチャーではマップをズームできません。(続き...)
オリー

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 2013年

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クラスリファレンスを使用可能なすべてのジェスチャー認識を参照してください。

デリゲートをselfに定義したので、プロトコル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 shouldRecognizeSimultaneouslyWithGestureRecognizer:をオーバーライドして、複数のジェスチャーを同時に認識できるようにします。

// 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(@ "handleLongPressAndPinchGesture Ended") ; }}
アレハンドロルエンゴ2013年

また、デリゲート<UIGestureRecognizerDelegate>を追加することを忘れないでください
Alejandro Luengo

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ベースのコントロールで頻繁に行われるように、タッチをキャッチするために透明なビューをオーバーレイする必要があるでしょう。マップビューは、マップを移動、中央揃え、ズームなどできるようにするために、タッチで既にいくつかの特別な処理を行っています...メッセージがアプリに表示されないようにします。

私が考えることができる他の2つの(テストされていない)オプション:

1)IB経由で最初のレスポンダーを辞任し、「ファイルの所有者」に設定して、ファイルの所有者がタッチに応答できるようにします。MKMapViewがNSObjectを拡張しているため、これが機能するのではないかと疑っています。UIViewではなく、結果として、タッチイベントがまだあなたに伝わらない可能性があります。

2)マップの状態が変化したとき(ズーム時など)トラップしたい場合は、MKMapViewDelegateプロトコルを実装して、特定のイベントをリッスンします。私の直感は、これはいくつかのインタラクションを簡単にトラップするのに最適なショットです(マップ上に透明なビューを実装するのではありません)。MKMapViewを含むビューコントローラをマップのデリゲートとして設定することを忘れないでください(map.delegate = self)。

幸運を。


MKMapViewは間違いなくUIViewのサブクラスです。
ダニエルディキソン09年

2

私は実験していませんが、MapKitがクラスクラスターに基づいている可能性が高いため、サブクラス化は難しく、効果がありません。

MapKitビューをカスタムビューのサブビューにすることをお勧めします。これにより、タッチイベントが到達する前にインターセプトできるようになります。


こんにちはグラハム!ご協力ありがとうございました!あなたが提案するようなスーパーカスタムビューを作成した場合、どのようにしてイベントをMKMapViewに転送できますか?何か案が?
マーティン

2

だから半日かけてこれをいじった後、私は以下を見つけました:

  1. 他の皆が見つけたように、ピンチは機能しません。MKMapViewのサブクラス化と上記のメソッド(それをインターセプト)の両方を試しました。そして結果は同じです。
  2. スタンフォードのiPhoneビデオで、Appleの人は、タッチリクエストを「転送」すると(前述の2つの方法とも呼ばれます)、UIKitの多くが多くのエラーを引き起こし、おそらく機能しないと述べています。

  3. ソリューション:ここで説明されています。インターセプト/ハイジャックiPhoneタッチイベントをMKMapViewため。基本的に、応答者がイベントを取得する前にイベントを「キャッチ」し、そこで解釈します。


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

カスタムビューでサブビューの代わりに自分自身を返します。


こんにちはピーター、あなたの答えをありがとう!しかし、そうすることで、MKMapViewはtoucheイベントを取得できない可能性があると思いますよね。イベントをキャッチしてMKMapViewに転送する方法を探しています。
マーティン、

0

ピザと叫び声をありがとう-あなたは私に多くの時間を節約しました。

multipletouchenabledは散発的に機能します。

viewTouch.multipleTouchEnabled = TRUE;

最後に、タッチをキャプチャする必要があるときにビューを切り替えました(ピンチズームが必要なときとは異なる時点)。

    [mapView removeFromSuperview];
    [viewTouch addSubview:mapView];
    [self.view insertSubview:viewTouch atIndex:0];

ただし、ライブズームでは機能しません。また、常にズームアウトしているようです。
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];
}

他の誰かがこれらの値を使用してマップのズームレベルを更新しようとしましたか?開始位置を記録してから終了位置を記録し、相対差を計算してマップを更新するだけです。

Martinが提供する基本的なコードで遊んでいますが、これはうまくいくようです...


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];
}

主な考え方は、ユーザーが2本の指を使用している場合は、値を追跡することです。startPoints AとBに開始点と終了点を記録します。次に、現在の追跡点を記録し、完了したらtouchesEndedでルーチンを呼び出して、開始点間の線の相対的な長さを計算できます、そして私が単純な斜辺計算を使用して終了する点の間の線。それらの間の比率がズーム量です。私は、リージョンスパンにその量を掛けます。

それが誰かに役立つことを願っています。


0

私はMystikSpiralの回答から「オーバーレイ」の透明なビューのアイデアを取り入れ、それは私が達成しようとしていたことに対して完全に機能しました。迅速かつクリーンなソリューション。

要するに、左側にMKMapView、右側にいくつかのUILabelsを持つカスタムUITableViewCell(IBで設計)がありました。カスタムセルを作成して、どこにでも触れることができるようにしたかったので、新しいビューコントローラをプッシュします。ただし、マップにタッチすると、その上に(IBで)マップビューと同じサイズのUIViewを追加し、その背景をコードで 'クリアカラー'にするまで、UITableViewCellにタッチアップが渡されませんでした( IBでclearColorを設定できるとは思わない??):

dummyView.backgroundColor = [UIColor clearColor];

それは他の誰かを助けるかもしれないと思った。テーブルビューセルに対して同じ動作を実現したい場合は確かです。


「しかし、マップをタッチしても、その上にマップビューと同じサイズのUIViewを追加するまで、UITableViewCellにタッチアップが渡されませんでした」これは正しくありません。スクロールなどの独自のユーザー操作があるため、マップはタッチを処理しています。マップと対話するのではなく、セルでスルーを検出する場合は、単純にmap.isUserInteractionEnabled = falseを設定します。テーブルでdidSelectRowAtIndexPathを使用できます。代理人を表示します。
BROK3N S0UL 2018
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.