कैसे एक 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 के कोड की नकल करते हैं, विशेष रूप से मल्टीटच के मामले में।

यहाँ मैं क्या कर रहा हूँ: एक जेस्चर पहचानकर्ता को लागू करें जिसे रोका नहीं जा सकता है और जो अन्य जेस्चर पहचानकर्ताओं को रोक नहीं सकता है। इसे मैप दृश्य में जोड़ें, और फिर अपने फैंस को जेस्चरक्राइज़र के टचबिजेन, टचसेमव्ड आदि का उपयोग करें।

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

स्विफ्ट 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
"LockOnUserLocation" किसके लिए है?
jowie

कि मेरे आवेदन के लिए एक विशिष्ट चर है। यह इस बात पर नज़र रखता है कि सिस्टम को वर्तमान स्थान पर मानचित्र को स्वचालित रूप से
केंद्रित

यह अचूक उपाय है। मुझे एक स्पष्टीकरण की आवश्यकता है: विधि में - "(शून्य) टचबेटन: (एनएसएसईटी *) छूता है साथ में: (UIEvent *) घटना", कोड का उपयोग करने का उद्देश्य क्या है: यदि (टचबेंसगन कॉलबैक) छूता हैबिजेनकॉलबैक (छूता है, घटना);
सत्यम

1
यह अधिकांश भाग के लिए बहुत अच्छा काम करता है लेकिन मुझे इसमें एक समस्या मिली है। यदि आपके वेब दृश्य में HTML में videoनियंत्रणों के साथ HTML5 टैग है, तो जेस्चर पहचानकर्ता उपयोगकर्ता को नियंत्रणों का उपयोग करने से रोक देगा। मैं इसके लिए वर्कअराउंड ढूंढ रहा हूं लेकिन अभी तक एक नहीं मिला है।
ब्रायन इयर्स

साझा करने के लिए धन्यवाद। उपयोगकर्ता के इंटरैक्शन को मैप व्यू के साथ ट्रैक करने के लिए उपयुक्त प्रतिनिधि विधि क्यों नहीं है, यह मेरे से परे है, लेकिन यह अच्छी तरह से काम करता है।
जस्टिन ड्रिस्कॉल

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 वर्ग (भले ही यह एक निजी वर्ग हो) के साथ टकराव हो सकता है।
डैनियल डिकिसन

हे डैनियल, आप पूरी तरह से सही हैं, मैंने भी सोचा था! ऊपर दिए गए मेरे उत्तर को पूरा करने के लिए, मुझे थोड़ी चेतावनी देनी चाहिए: मेरा उदाहरण मान लें कि केवल एक ही वस्तु दिखाई दे रही है, जो सभी घटनाओं का उपभोग कर रही है। लेकिन यह सच नहीं है। आपके मानचित्र के ऊपर कुछ एनोटेशन हो सकते हैं और फिर मेरा कोड अब काम नहीं करता है। 100% काम करने के लिए, आपको उस विशिष्ट घटना से जुड़े प्रत्येक हिटटेस्ट को देखने के लिए याद रखने की आवश्यकता है (और अंततः इसे तब जारी करें जब स्पर्श या स्पर्श किया गया हो या ट्रिगर किया गया हो, तो आपको समाप्त घटनाओं का ट्रैक रखने की आवश्यकता नहीं है ...)।
मार्टिन

1
बहुत उपयोगी कोड, धन्यवाद मार्टिन! मैं सोच रहा था कि क्या आपने इसे लागू करने के बाद नक्शे को चुटकी में ज़ूम करने की कोशिश की? मेरे लिए जब मुझे मूल रूप से एक ही कोड का उपयोग करके काम मिला, तो आप नक्शे को चुटकी में छोड़कर काम कर रहे थे। क्या किसी के भी पास कोई सुझाव है?
एडम अलेक्जेंडर

अरे एडम, मैं भी इस सीमा है और मैं सच में समझ में नहीं आता क्यों! यह वास्तव में कष्टप्रद है। अगर आपको कोई हल मिल जाए तो मुझे बताएं! Thx
मार्टिन

ठीक है, मैंने इसे एक वोट दिया क्योंकि यह शुरू में मेरी समस्या को हल करने के लिए दिखाई दिया। तथापि...! मैं काम करने के लिए मल्टी-टच प्राप्त नहीं कर सकता। हालांकि, भले ही मैं सीधे टचबिजेन पास करता हूं और छूता हूं देखने के लिए प्यार करता हूं (मैं टचसेप्ट पर अपनी इंटरसेप्टिंग करता हूं), मैं चुटकी इशारों के साथ नक्शे को ज़ूम नहीं कर सकता। (जारी ...)
ओली

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
मुझे यकीन नहीं है कि यह शीर्ष उत्तर क्यों नहीं है। पूरी तरह से काम करने लगता है, और बहुत सरल है।
एल्सरुडो

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;
...

और मेथोड जेस्चर को पहचानें।

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

यह समाधान एकदम सही है! यहां कुछ क्विकिज़: यदि आप उपयोगकर्ता द्वारा किसी भी क्रिया को समाप्त करने के बाद इंटरसेप करना चाहते हैं, तो यह पर्याप्त होना चाहिए - (शून्य) हैंडललॉन्गप्रेसएंडपंचगस्ट्योर: (UIGestureRecognizer *) प्रेषक {अगर (प्रेषक .state == UIGestureRecognizerStateEnded) {NSLog (@Long #) ; }}
एलेजांद्रो लुएंगो

साथ ही प्रतिनिधि को जोड़ना न भूलें <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। इस मामले में, आपके पास एक और एनोटेशन का सबव्यू हो सकता है जो जेस्चर पहचानकर्ता को ट्रिगर करता है। मुझे एक संभावित MKAnnotationView
KIDdAe

3

संभवतः आपको यूआईवेबव्यू-आधारित नियंत्रणों के साथ ऐसा करने के लिए पारदर्शी दृश्य को ओवरले करने की आवश्यकता होगी, जैसे कि अक्सर किया जाता है। मानचित्र दृश्य पहले से ही एक स्पर्श के साथ विशेष चीजों का एक गुच्छा करता है ताकि नक्शे को स्थानांतरित करने, केंद्रित, ज़ूम करने आदि के लिए अनुमति दी जा सके ... कि संदेश आपके ऐप पर बुदबुदा नहीं रहे हैं।

दो अन्य (UNTESTED) विकल्प जो मैं सोच सकता हूं:

1) आईबी के माध्यम से पहले उत्तरदाता को इस्तीफा दें और इसे "फाइल का मालिक" सेट करें ताकि फाइल के मालिक को स्पर्शों का जवाब देने की अनुमति मिल सके। मुझे संदेह है कि यह काम करेगा क्योंकि MKMapView NSObject का विस्तार करता है, न कि UIView ans के परिणामस्वरूप स्पर्श की घटनाओं को अभी भी आप तक प्रचारित नहीं किया जा सकता है।

2) यदि आप चाहते हैं कि जब मानचित्र स्थिति में बदलाव हो (जैसे कि ज़ूम पर) तो विशेष घटनाओं के लिए सुनने के लिए MKMapViewDelegate प्रोटोकॉल लागू करें। मेरा कूबड़ यह आसानी से कुछ इंटरैक्शन को फँसाने के लिए आपका सबसे अच्छा शॉट है (मानचित्र पर पारदर्शी दृश्य को लागू करने की कमी)। मानचित्र के प्रतिनिधि के रूप में MKMapView के नियंत्रक आवास को देखना न भूलें map.delegate = self

शुभ लाभ।


MKMapView निश्चित रूप से UIView को उपवर्गित करता है।
डैनियल डिकिसन

2

मैंने प्रयोग नहीं किया है, लेकिन एक अच्छा मौका है MapKit एक वर्ग क्लस्टर के आसपास आधारित है, और इसलिए इसे उप-वर्ग करना मुश्किल और अप्रभावी है।

मैं सुझाव देता हूं कि MapKit को एक कस्टम दृश्य का एक उप-दृश्य बनाएं, जो आपको पहुंचने से पहले स्पर्श घटनाओं को रोकना चाहिए।


नमस्ते ग्राहम! आपके सहयोग के लिए धन्यवाद! यदि मैं आपके सुझाव के अनुसार एक सुपर कस्टम दृश्य बनाता हूं, तो मैं फिर एमकेपॉपर व्यू को कैसे आगे बढ़ा सकता हूं? कोई उपाय?
मार्टिन

2

तो इस के साथ खिलवाड़ के आधे दिन के बाद मुझे निम्नलिखित मिला:

  1. जैसा कि बाकी सभी ने पाया, चुटकी लेने से काम नहीं चलता। मैंने MKMapView और ऊपर वर्णित विधि (इसे इंटरसेप्ट करते हुए) दोनों उपवर्ग का प्रयास किया। और नतीजा वही होता है।
  2. स्टैनफोर्ड iPhone वीडियो में, Apple का एक व्यक्ति कहता है कि यदि आप स्पर्श अनुरोधों (उक्त वर्णित दो तरीकों) को "स्थानांतरित" करते हैं, और संभवत: आपको यह काम करने के लिए नहीं मिलेगा।

  3. समाधान : यहां वर्णित है: MKMapView के लिए iPhone टच इवेंट को इंटरसेप्ट करना / अपहरण करना । मूल रूप से आप किसी भी उत्तरदाता को मिलने से पहले ही उस घटना को "पकड़" लेते हैं, और उसकी व्याख्या करते हैं।


2

स्विफ्ट 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 किसी भी टौच ईवेंट को प्राप्त करने में सक्षम नहीं हो सकता है, है ना? मैं सिर्फ इवेंट को पकड़ने का तरीका ढूंढ रहा हूं और फिर इसे MKMapView पर अग्रेषित करता हूं।
मार्टिन

0

पिज्जा और चिल्ला के लिए धन्यवाद - आपने मुझे बहुत समय बचाया।

बहुस्तरीय काम छिटपुट रूप से काम करेगा।

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

क्या मानचित्र के ज़ूम स्तर को अपडेट करने के लिए किसी और ने इन मूल्यों का उपयोग करने की कोशिश की है? यह शुरू करने वाले पदों को दर्ज करने और फिर स्थानों को खत्म करने, सापेक्ष अंतर की गणना करने और नक्शे को अपडेट करने की बात होगी।

मैं मार्टिन द्वारा प्रदान किए गए मूल कोड के साथ खेल रहा हूं, और ऐसा लगता है कि यह काम करेगा ...


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. में शुरुआती और समाप्ति बिंदुओं को रिकॉर्ड करता हूं। फिर मैं वर्तमान ट्रैकिंग बिंदुओं को रिकॉर्ड करता हूं, और जब मैं पूरा हो जाता हूं, तो टचडाउन पर, मैं उन बिंदुओं के बीच की रेखा की सापेक्ष लंबाई की गणना करने के लिए एक रूटीन कॉल कर सकता हूं, जो मैं शुरू करता हूं। , और बिंदु के बीच की रेखा मैं सरल कर्ण का उपयोग करके समाप्त होता है। उनके बीच का अनुपात ज़ूम राशि है: मैं उस राशि से क्षेत्र की अवधि को गुणा करता हूं।

आशा है कि यह किसी के लिए उपयोगी है।


0

मैंने मिस्टिकस्पिरल के उत्तर से एक "ओवरले" पारदर्शी दृश्य का विचार लिया, और यह पूरी तरह से काम कर रहा था कि मैं क्या हासिल करना चाहता था; त्वरित, और साफ समाधान।

संक्षेप में, मेरे पास एक कस्टम UITableViewCell (IB में डिज़ाइन किया गया) है, जो बाईं ओर एक MKMapView और दाईं ओर कुछ UILabels है। मैं कस्टम सेल बनाना चाहता था ताकि आप इसे कहीं भी छू सकें और यह एक नए व्यू कंट्रोलर को आगे बढ़ाएगा। हालाँकि मानचित्र को छूना UITableViewCell को 'टच' पास नहीं करता था, जब तक कि मैंने बस उसी आकार का एक UIView नहीं जोड़ा था, जैसा कि मानचित्र उसके ऊपर (IB में) दाईं ओर दिखता है और उसने कोड में 'स्पष्ट रंग' पृष्ठभूमि की है ( नहीं लगता कि आप IB में क्लियरलाइन सेट कर सकते हैं ??):

dummyView.backgroundColor = [UIColor clearColor];

सोचा कि यह किसी और की मदद कर सकता है; निश्चित रूप से यदि आप टेबल व्यू सेल के लिए समान व्यवहार प्राप्त करना चाहते हैं।


"हालांकि, जब तक मैं मानचित्र को इसके ठीक ऊपर के दृश्य के समान नहीं देखता, तब तक मैप को छूना UITableViewCell के लिए 'अप' को नहीं छूता था।" यह सच नहीं है। नक्शा छू रहा है, क्योंकि इसमें स्वयं के उपयोगकर्ता इंटरैक्शन हैं जैसे स्क्रॉलिंग आदि। यदि आप मानचित्र के साथ बातचीत करने के बजाय सेल पर पता लगाना चाहते हैं, तो बस map.isUserInteractionEnabled = false सेट करें। आप तब तालिका में dideelectRowAtIndexPath का उपयोग कर सकते हैं प्रतिनिधि देखें।
BROK3N S0UL
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.