DismissModaViewController on Mail composer not working - mfmailcomposeviewcontroller

I have a problem when i finished a screenshot and try to email out the screenshot in an app. Normally it works perfectly when sending text, but once sending screenshot, no matter cancel or sent the email, the screen won't go away. May I know what is the problem of this?
Here is my code. Thank you very much.
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == 0) {
UIGraphicsBeginImageContext(self.view.frame.size);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage * image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSData * imageData = UIImageJPEGRepresentation(image, 1.0);
if ( [MFMailComposeViewController canSendMail] ) {
MFMailComposeViewController * mailComposer = [[[MFMailComposeViewController alloc] init] autorelease];
mailComposer.delegate = self;
[mailComposer addAttachmentData:imageData mimeType:#"image/jpeg" fileName:#"attachment.jpg"];
/* Configure other settings */
[self presentModalViewController:mailComposer animated:YES];
}
}
}
- (void)mailComposeController:(MFMailComposeViewController*)controller{
[self dismissModalViewControllerAnimated:YES];
}

The delegate method you need to implement is mailComposeController:didFinishWithResult:error:, not mailComposeController:. See the documentation for details.

Related

Why is shouldStartLoadWithRequest only being invoked the first time through?

I'm trying to display a list of web pages the user can switch between in my app. I've done this successfully with documents. however, I don't want the user to be able to navigate from these pages. I found out how to do this by looking it up. The problem is that it only executes on the first page. When I switch to another page shouldStartLoadWithRequest stops working even when I go back to the first page. (This is all done with my specially designed back and forward buttons.) How can I fix this so that it will be invoked every single time and prevent the user from clicking links and navigating away from my set pages? I'm new to objective-c. All the relevant code is below. Some things were declared globally in the .h. Sorry it's kind of rough. I tabbed over only what was needed to make it into code formatting. Thanks!
My .h file:
#import <UIKit/UIKit.h>
#interface learnViewController : UIViewController <UINavigationControllerDelegate>
{
IBOutlet UIWebView *web;
UIButton *backButton;
UIButton *forButton;
}
#end
My .m file
#import "learnViewController.h"
#import "ViewController.h"
static NSString* links[] =
{
#"http://www.nlm.nih.gov/medlineplus/ency/article/000141.htm",
#"http://www.nlm.nih.gov/medlineplus/ency/article/000065.htm",
#"http://www.nlm.nih.gov/medlineplus/ency/article/001087.htm",
#"http://www.nlm.nih.gov/medlineplus/ency/article/000091.htm",
#"http://www.nlm.nih.gov/medlineplus/ency/article/007270.htm",
#"http://www.nlm.nih.gov/medlineplus/ency/article/000145.htm",
#"http://www.nlm.nih.gov/medlineplus/ency/article/000093.htm",
#"http://www.nlm.nih.gov/medlineplus/ency/article/000087.htm",
#"http://www.nlm.nih.gov/medlineplus/ency/article/000140.htm",
#"http://www.nlm.nih.gov/medlineplus/ency/article/000132.htm"
};
int numlinks = 10;
int i = 0;
#interface learnViewController ()
#end
#implementation learnViewController
- (void)viewDidLoad
{
[super viewDidLoad];
float viewWidth = self.view.frame.size.width;
float viewHeight = self.view.frame.size.height;
self.view.multipleTouchEnabled = true;
//Background
UIImageView *backgroundView = [[UIImageView alloc] initWithFrame:CGRectMake(0.0, 0.0, viewWidth, viewHeight)];
backgroundView.image = [UIImage imageNamed:#"Background.png"];
[self.view addSubview:backgroundView];
//Show Portal
web = [[UIWebView alloc]initWithFrame:CGRectMake(0.0, viewHeight/34.0, viewWidth, (viewHeight - viewHeight/6.4))];
self->web.delegate = self;
web.scrollView.scrollEnabled = TRUE;
web.scalesPageToFit = TRUE;
[self loadDocument:links[i] inView:web];
[self.view addSubview:web];
//Buttons
UIButton *homeButton = [[UIButton alloc] initWithFrame:CGRectMake((viewWidth/2.0 - viewWidth/6.0/2.0), (viewHeight - viewHeight*280.0/2208.0/2.0 - viewWidth/6.0/2.0), (viewWidth/6.0), (viewWidth/6.0))];
[homeButton
setBackgroundImage:[UIImage imageNamed:#"Home.png"]
forState:UIControlStateNormal];
[homeButton addTarget:self action:#selector(homePressed:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:homeButton];
backButton = [[UIButton alloc] initWithFrame:CGRectMake((viewWidth/2.0/3.5 - viewWidth/9.0/2.0), (viewHeight - viewHeight*280.0/2208.0/2.0 - viewWidth/9.0/2.0), (viewWidth/9.0), (viewWidth/9.0))];
[backButton
setBackgroundImage:[UIImage imageNamed:#"Back.png"]
forState:UIControlStateNormal];
backButton.enabled = FALSE;
[backButton addTarget:self
action:#selector(backPressed:)
forControlEvents:UIControlEventTouchDown];
[self.view addSubview:backButton];
forButton = [[UIButton alloc] initWithFrame:CGRectMake((viewWidth/2.0/3.5*2.0 - viewWidth/9.0/2.0), (viewHeight - viewHeight*280.0/2208.0/2.0 - viewWidth/9.0/2.0), (viewWidth/9.0), (viewWidth/9.0))];
[forButton
setBackgroundImage:[UIImage imageNamed:#"Forward.png"]
forState:UIControlStateNormal];
[forButton addTarget:self
action:#selector(forPressed:)
forControlEvents:UIControlEventTouchDown];
[self.view addSubview:forButton];
UIButton *refButton = [[UIButton alloc] initWithFrame:CGRectMake((viewWidth - viewWidth/2.0/3.5*2.0 - viewWidth/9.0/2.0), (viewHeight - viewHeight*280.0/2208.0/2.0 - viewWidth/9.0/2.0), (viewWidth/9.0), (viewWidth/9.0))];
[refButton
setBackgroundImage:[UIImage imageNamed:#"Scale.png"]
forState:UIControlStateNormal];
[refButton addTarget:self
action:#selector(refPressed:)
forControlEvents:UIControlEventTouchDown];
[self.view addSubview:refButton];
UIButton *webButton = [[UIButton alloc] initWithFrame:CGRectMake((viewWidth - viewWidth/2.0/3.5 - viewWidth/9.0/2.0), (viewHeight - viewHeight*280.0/2208.0/2.0 - viewWidth/9.0/2.0), (viewWidth/9.0), (viewWidth/9.0))];
[webButton
setBackgroundImage:[UIImage imageNamed:#"Web.png"]
forState:UIControlStateNormal];
[webButton addTarget:self
action:#selector(webPressed:)
forControlEvents:UIControlEventTouchDown];
[self.view addSubview:webButton];
}
//Button presses
-(void)homePressed:(id)sender
{
ViewController *home = [[ViewController alloc] initWithNibName:nil bundle:nil];
[self presentViewController:home animated:YES completion:NULL];
}
- (void) refPressed:(id)sender
{
[self loadDocument:links[i] inView:web];
}
-(void)backPressed:(id)sender
{
float viewWidth = self.view.frame.size.width;
float viewHeight = self.view.frame.size.height;
if (i > 0)
{
[web removeFromSuperview];
i--;
web = [[UIWebView alloc] initWithFrame:CGRectMake(0.0, viewHeight/34.0, viewWidth, (viewHeight - viewHeight/6.4))];
[self loadDocument:links[i] inView:web];
web.scrollView.scrollEnabled = TRUE;
web.scalesPageToFit = TRUE;
[self.view addSubview:web];
forButton.enabled = TRUE;
}
if (i == 0)
{
backButton.enabled = FALSE;
}
}
-(void)forPressed:(id)sender
{
float viewWidth = self.view.frame.size.width;
float viewHeight = self.view.frame.size.height;
if (i < numlinks - 1)
{
[web removeFromSuperview];
i++;
web = [[UIWebView alloc] initWithFrame:CGRectMake(0.0, viewHeight/34.0, viewWidth, (viewHeight - viewHeight/6.4))];
[self loadDocument:links[i] inView:web];
web.scrollView.scrollEnabled = TRUE;
web.scalesPageToFit = TRUE;
[self.view addSubview:web];
backButton.enabled = TRUE;
}
if (i == numlinks - 1)
{
forButton.enabled = FALSE;
}
}
-(void)loadDocument:(NSString*)documentName inView:(UIWebView*)webView
{
NSString *url = links[i];
NSURL *nsurl = [NSURL URLWithString:url];
NSURLRequest *nsrequest = [NSURLRequest requestWithURL:nsurl];
[webView loadRequest:nsrequest];
}
-(void)webPressed:(id)sender
{
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:links[i]]];
}
-(BOOL) webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
NSURL *url = request.URL;
NSString *urlString = url.absoluteString;
NSRange range = [urlString rangeOfString:links[i]];
if (range.location != NSNotFound)
{
return YES;
}
else
{
return NO;
}
}
- (void)viewDidUnload
{
[self->web stopLoading];
self->web.delegate = nil;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Okay, I figured it out through trial and error since no one wanted to help me. I tried looking for answers to similar questions, but nothing actually worked for me. If you're reading this and having the same problem, this is how you fix it. All you have to do is reset the web delegate to nil then back to self as so:
self.webView.delegate = nil;
self.webView.delegate = self;
I don't know why everyone else's code was so complex, and I can only speculate as to why this works. I just got lucky honestly, but I think it maybe clears the cache when you do this, thus making each page fresh to the program. That's what other people were talking about. However, their methods did not work for me either because of my lack of experience or because they do not fit my particular case. This is much simpler and is guaranteed to work as long as you make sure it does this each time you load one of your designated web pages. You're welcome if you're reading this. If anyone would so kindly as to look at my post and explain why this works in better detail, please feel free to do so!

GPUImage saving video in background issue

I'm having an issue with saving video from a GPUImage videoCamera to the Camera Roll when my app goes into the background. The file is only saved to the camera roll when the app returns to the foreground / is restarted. I'm no doubt making a beginners code error , if anyone can point it out that would be appreciated.
- (void)applicationDidEnterBackground:(UIApplication *)application {
if (isRecording){
[self stopRecording];
};
if (self.isViewLoaded && self.view.window){
[videoCamera stopCameraCapture];
};
runSynchronouslyOnVideoProcessingQueue(^{
glFinish();
});
NSLog(#"applicationDidEnterBackground");
and then
-(void)stopRecording {
[filterBlend removeTarget:movieWriter];
videoCamera.audioEncodingTarget = nil;
[movieWriter finishRecording];
NSString *path = [NSTemporaryDirectory() stringByAppendingPathComponent:#"file.mov"];
ALAssetsLibrary *al = [[ALAssetsLibrary alloc] init];
[al writeVideoAtPathToSavedPhotosAlbum:[NSURL fileURLWithPath:path] completionBlock:^(NSURL *assetURL, NSError *error) {
if (error) {
NSLog(#"Error %#", error);
} else {
NSLog(#"Success");
}
}];
isRecording = NO;
NSLog(#"Stop recording");
It was exactly as Brad pointed out in his, as usual, insightful comment, the -writeVideoAtPathToSavedPhotosAlbum:completionBlock: wasn't completing till after the app returned to the foreground, I solved it by adding
self.backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
NSLog(#"Background handler called. Not running background tasks anymore.");
[[UIApplication sharedApplication] endBackgroundTask:self.backgroundTask];
self.backgroundTask = UIBackgroundTaskInvalid;
}];
and
#property (nonatomic) UIBackgroundTaskIdentifier backgroundTask;
Found this solution at http://www.raywenderlich.com/29948/backgrounding-for-ios

FBLoginView: login isn't performed

I'm adding FBLoginView to my ViewController < FBLoginViewDelegate >:
FBLoginView *loginview = [[FBLoginView alloc] init];
loginview.frame = CGRectOffset(loginview.frame, 5, 5);
loginview.delegate = self;
[self.view addSubview:loginview];
[loginview sizeToFit];
All the necessary fields in plist (FacebookAppID, FacebookDisplayName, URL Schemes) are all set according to the tutorial. The facebook app is also configured according to the tutorial (bundle ID is set, Facebook login is enabled).
But the login still isn't performed. When I press on "log in", I get redirected to the browser with facebook login, but when it's finished, I'm not logged in the app (loginViewFetchedUserInfo:user: isn't called, "log in" hasn't changed to "log out").
What can be the problem?
Everything worked after I implemented the following in the AppDelegate.m (taken from one of the official examples):
- (void)sessionStateChanged:(FBSession *)session
state:(FBSessionState) state
error:(NSError *)error
{
switch (state) {
case FBSessionStateOpen:
if (!error) {
// We have a valid session
//NSLog(#"User session found");
[FBRequestConnection
startForMeWithCompletionHandler:^(FBRequestConnection *connection,
NSDictionary<FBGraphUser> *user,
NSError *error) {
if (!error) {
self.loggedInUserID = user.id;
self.loggedInSession = FBSession.activeSession;
}
}];
}
break;
case FBSessionStateClosed:
case FBSessionStateClosedLoginFailed:
[FBSession.activeSession closeAndClearTokenInformation];
break;
default:
break;
}
[[NSNotificationCenter defaultCenter]
postNotificationName:FBSessionStateChangedNotification
object:session];
if (error) {
UIAlertView *alertView = [[UIAlertView alloc]
initWithTitle:#"Error"
message:error.localizedDescription
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alertView show];
}
}
/*
* Opens a Facebook session and optionally shows the login UX.
*/
- (BOOL)openSessionWithAllowLoginUI:(BOOL)allowLoginUI {
return [FBSession openActiveSessionWithReadPermissions:nil
allowLoginUI:allowLoginUI
completionHandler:^(FBSession *session,
FBSessionState state,
NSError *error) {
[self sessionStateChanged:session
state:state
error:error];
}];
}
/*
*
*/
- (void) closeSession {
[FBSession.activeSession closeAndClearTokenInformation];
}
/*
* If we have a valid session at the time of openURL call, we handle
* Facebook transitions by passing the url argument to handleOpenURL
*/
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation {
// attempt to extract a token from the url
return [FBAppCall handleOpenURL:url sourceApplication:sourceApplication];
}
You need to add the following to the app delegate
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation {
// Call FBAppCall's handleOpenURL:sourceApplication to handle Facebook app responses
BOOL wasHandled = [FBAppCall handleOpenURL:url sourceApplication:sourceApplication];
// You can add your app-specific url handling code here if needed
return wasHandled;
}
You may need to implement the
(BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url method
Be sure to call:
return [FBSession.activeSession handleOpenURL:url];
When applicable.
#Sergey: Are you want to open FBDialog on your native app or in browser? If you to want open in your native app then use "FBSessionLoginBehaviorForcingWebView". Here is my code that I am using:
NSArray *permission = [NSArray arrayWithObjects:kFBEmailPermission,kFBUserPhotosPermission, nil];
FBSession *session = [[FBSession alloc] initWithPermissions:permission];
[FBSession setActiveSession: [[FBSession alloc] initWithPermissions:permission] ];
[[FBSession activeSession] openWithBehavior:FBSessionLoginBehaviorForcingWebView completionHandler:^(FBSession *session, FBSessionState status, NSError *error) {
switch (status) {
case FBSessionStateOpen:
[self yourmethod];
break;
case FBSessionStateClosedLoginFailed: {
// prefer to keep decls near to their use
// unpack the error code and reason in order to compute cancel bool
NSString *errorCode = [[error userInfo] objectForKey:FBErrorLoginFailedOriginalErrorCode];
NSString *errorReason = [[error userInfo] objectForKey:FBErrorLoginFailedReason];
BOOL userDidCancel = !errorCode && (!errorReason || [errorReason isEqualToString:FBErrorLoginFailedReasonInlineCancelledValue]);
if(error.code == 2) {
UIAlertView *errorMessage = [[UIAlertView alloc] initWithTitle:#"FBAlertTitle"
message:#"FBAuthenticationErrorMessage"
delegate:nil
cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
[errorMessage performSelectorOnMainThread:#selector(show) withObject:nil waitUntilDone:YES];
errorMessage = nil;
}
}
break;
// presently extension, log-out and invalidation are being implemented in the Facebook class
default:
break; // so we do nothing in response to those state transitions
}
}];
permission = nil;
or you want to open in browser then use following :
In your .h file
#import <FacebookSDK/FacebookSDK.h> and add FBLoginViewDelegate delegate
In you .m file
FBLoginView *loginview = [[FBLoginView alloc] init];
loginview.frame = CGRectOffset(loginview.frame, 5, 5);
loginview.delegate = self;
[self.view addSubview:loginview];
[loginview sizeToFit];
// use following delegate methods
- (void)loginViewShowingLoggedInUser:(FBLoginView *)loginView {
// first get the buttons set for login mode
}
- (void)loginViewFetchedUserInfo:(FBLoginView *)loginView
user:(id<FBGraphUser>)user {
// here we use helper properties of FBGraphUser to dot-through to first_name and
// id properties of the json response from the server; alternatively we could use
// NSDictionary methods such as objectForKey to get values from the my json object
NSLog(#"userprofile:%#",user);
}
- (void)loginViewShowingLoggedOutUser:(FBLoginView *)loginView {
//BOOL canShareAnyhow = [FBNativeDialogs canPresentShareDialogWithSession:nil];
}
- (void)loginView:(FBLoginView *)loginView handleError:(NSError *)error {
// see https://developers.facebook.com/docs/reference/api/errors/ for general guidance on error handling for Facebook API
// our policy here is to let the login view handle errors, but to log the results
NSLog(#"FBLoginView encountered an error=%#", error);
}

Updating the UI control's value in the runtime from background thread.

I know this sound a very simple question. I'm still a newbie in iPad app development. Would you please tell me how would I update the contents in the run time. The following code may be helpful to know my question in detail.
In the following code, I'm trying to display text contents in the TexViewcontrol. When I change the for loop form 10 to 100000, I needed to wait until everything fills up. I need to display the contents on the screen while loop is running.
- (IBAction)RunHelloWorld:(id)sender
{
tctView.text = #"tt";
for(int i=0;i<10;i++)
{
NSString *result1 = #"Testing";
tctView.text = [tctView.text stringByAppendingString:result1];
tctView.scrollEnabled = YES;
}
}
Would you please give me any help? Thanks a LOT!!!
-Teva
Finally I found the solution with the following URL's help. http://samplecodebank.blogspot.com/2011/05/nsthread-example_12.html
Thanks a LOT!
This is my code.
PCViewController.h file code
#import <UIKit/UIKit.h>
#interface PCViewController : UIViewController
{
IBOutlet UITextView *txtView;
}
-(void)ReadFile;
- (void) mainThreadSetText:(NSString*)text;
#end
PCViewController.m file code
#import "PCViewController.h"
#interface PCViewController ()
#end
#implementation PCViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[NSThread detachNewThreadSelector:#selector(ReadFile) toTarget:self withObject:nil];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
-(void)ReadFile
{
// Check whether current thread is externally terminated or not.
char line[1024];
FILE *fp = fopen("/Users/Teva/Desktop/File1.txt","r");
while([[NSThread currentThread] isCancelled] == NO)
{
if( fp != NULL )
{
while( fgets(line,1024,fp) )
{
printf("%s\n",line);
NSString *result1 = [NSString stringWithCString:line encoding:NSASCIIStringEncoding];
[self performSelectorOnMainThread:#selector(mainThreadSetText:) withObject:result1 waitUntilDone:YES];
[NSThread sleepForTimeInterval:1.0];
}
}
}
}
// Screen processing should be done outside the Thread.
- (void) mainThreadSetText:(NSString*)text
{
txtView.text = [txtView.text stringByAppendingString:text];
txtView.scrollEnabled = YES;
}
- (void)dealloc
{
[txtView release];
[super dealloc];
}
#end

How to capture Tap gesture on MKMapView

I am trying to capture tap event on my MKMapView, this way I can drop a MKPinAnnotation on the point where user tapped. Basically I have a map overlayed with MKOverlayViews (an overlay showing a building) and I would like to give user more information about that Overlay when they tap on it by dropping a MKPinAnnotaion and showing more information in the callout.
Thank you.
You can use a UIGestureRecognizer to detect touches on the map view.
Instead of a single tap, however, I would suggest looking for a double tap (UITapGestureRecognizer) or a long press (UILongPressGestureRecognizer). A single tap might interfere with the user trying to single tap on the pin or callout itself.
In the place where you setup the map view (in viewDidLoad for example), attach the gesture recognizer to the map view:
UITapGestureRecognizer *tgr = [[UITapGestureRecognizer alloc]
initWithTarget:self action:#selector(handleGesture:)];
tgr.numberOfTapsRequired = 2;
tgr.numberOfTouchesRequired = 1;
[mapView addGestureRecognizer:tgr];
[tgr release];
or to use a long press:
UILongPressGestureRecognizer *lpgr = [[UILongPressGestureRecognizer alloc]
initWithTarget:self action:#selector(handleGesture:)];
lpgr.minimumPressDuration = 2.0; //user must press for 2 seconds
[mapView addGestureRecognizer:lpgr];
[lpgr release];
In the handleGesture: method:
- (void)handleGesture:(UIGestureRecognizer *)gestureRecognizer
{
if (gestureRecognizer.state != UIGestureRecognizerStateEnded)
return;
CGPoint touchPoint = [gestureRecognizer locationInView:mapView];
CLLocationCoordinate2D touchMapCoordinate =
[mapView convertPoint:touchPoint toCoordinateFromView:mapView];
MKPointAnnotation *pa = [[MKPointAnnotation alloc] init];
pa.coordinate = touchMapCoordinate;
pa.title = #"Hello";
[mapView addAnnotation:pa];
[pa release];
}
I setup a long press (UILongPressGestureRecognizer) in viewDidLoad: but it just detect the only one touch from the first.
Where can i setup a long press to detect all touch? (it means the map ready everytime waiting user touch to screen to push a pin)
The viewDidLoad: method!
- (void)viewDidLoad {
[super viewDidLoad];mapView.mapType = MKMapTypeStandard;
UILongPressGestureRecognizer *longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(handleLongPressGesture:)];
[self.mapView addGestureRecognizer:longPressGesture];
[longPressGesture release];
mapAnnotations = [[NSMutableArray alloc] init];
MyLocation *location = [[MyLocation alloc] init];
[mapAnnotations addObject:location];
[self gotoLocation];
[self.mapView addAnnotations:self.mapAnnotations];
}
and the handleLongPressGesture method:
-(void)handleLongPressGesture:(UIGestureRecognizer*)sender {
// This is important if you only want to receive one tap and hold event
if (sender.state == UIGestureRecognizerStateEnded)
{NSLog(#"Released!");
[self.mapView removeGestureRecognizer:sender];
}
else
{
// Here we get the CGPoint for the touch and convert it to latitude and longitude coordinates to display on the map
CGPoint point = [sender locationInView:self.mapView];
CLLocationCoordinate2D locCoord = [self.mapView convertPoint:point toCoordinateFromView:self.mapView];
// Then all you have to do is create the annotation and add it to the map
MyLocation *dropPin = [[MyLocation alloc] init];
dropPin.latitude = [NSNumber numberWithDouble:locCoord.latitude];
dropPin.longitude = [NSNumber numberWithDouble:locCoord.longitude];
// [self.mapView addAnnotation:dropPin];
[mapAnnotations addObject:dropPin];
[dropPin release];
NSLog(#"Hold!!");
NSLog(#"Count: %d", [mapAnnotations count]);
}
}
If you want to use a single click/tap in the map view, here's a snippet of code I'm using. (Cocoa and Swift)
let gr = NSClickGestureRecognizer(target: self, action: "createPoint:")
gr.numberOfClicksRequired = 1
gr.delaysPrimaryMouseButtonEvents = false // allows +/- button press
gr.delegate = self
map.addGestureRecognizer(gr)
in the gesture delegate method, a simple test to prefer the double-tap gesture …
func gestureRecognizer(gestureRecognizer: NSGestureRecognizer, shouldRequireFailureOfGestureRecognizer otherGestureRecognizer: NSGestureRecognizer) -> Bool {
let other = otherGestureRecognizer as? NSClickGestureRecognizer
if (other?.numberOfClicksRequired > 1) {
return true; // allows double click
}
return false
}
you could also filter the gesture in other delegate methods if you wanted the Map to be in various "states", one of which allowed the single tap/click
For some reason, the UIGestureRecognizer just didn't work for me in Swift. When I use the UIGestureRecognizer way. When I used the touchesEnded method, it returns a MKNewAnnotationContainerView. It seems that this MKNewAnnotationContainerView blocked my MKMapView. Fortunately enough, it's a subview of MKMapView. So I looped through MKNewAnnotationContainerView's superviews till self.view to get the MKMapView. And I managed to pin the mapView by tapping.
Swift 4.1
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
let t = touches.first
print(t?.location(in: self.view) as Any)
print(t?.view?.superview?.superview.self as Any)
print(mapView.self as Any)
var tempView = t?.view
while tempView != self.view {
if tempView != mapView {
tempView = tempView?.superview!
}else if tempView == mapView{
break
}
}
let convertedCoor = mapView.convert((t?.location(in: mapView))!, toCoordinateFrom: mapView)
let pin = MKPointAnnotation()
pin.coordinate = convertedCoor
mapView.addAnnotation(pin)
}

Resources