iOS: problèmes TapGestureRecognizer

J'ai donc une application qui se comporte comme une galerie de photos et j'implémente la possibilité pour l'user de supprimer les images. Voici la configuration: J'ai 9 UIImageViews, imageView, imageView2, etc. J'ai aussi un button "Edit", et une méthode d'action tapGesture. J'ai fait glisser un reconnaisseur de gestes sur mon sharepoint vue dans IB, et je l'ai attaché à chacun des UIImageViews. J'ai également attaché la méthode d'action tapGesture à chacune des UIImageViews. Idéalement, j'aimerais que la méthode ne devienne active que lorsqu'on appuie sur le button «Modifier». Lorsque l'user clique sur Modifier, puis sur l'image à supprimer, je souhaite qu'un UIAlertView apparaisse, en demandant s'il est sûr de vouloir le supprimer. Voici le code que j'utilise:

- (IBAction)editButtonPressed:(id)sender { editButton.hidden = YES; backToGalleryButton.hidden = NO; tapToDeleteLabel.hidden = NO; } - (IBAction)tapGesture:(UITapGestureRecognizer*)gesture { UIAlertView *deleteAlertView = [[UIAlertView alloc] initWithTitle:@"Delete" message:@"Are you sure you want to delete this photo?" delegate:self cancelButtonTitle:@"No" otherButtonTitles:@"Yes", nil]; [deleteAlertView show]; if (buttonIndex != [alertView cancelButtonIndex]) { UIImageView *view = [self.UIImageView]; if (view) { [self.array removeObject:view]; } CGPoint tapLocation = [gesture locationInView: self.view]; for (UIImageView *imageView in self.view.subviews) { if (CGRectContainsPoint(self.UIImageView.frame, tapLocation)) { ((UIImageView *)[self.view]).image =nil; } } [self.user setObject:self.array forKey:@"images"]; } } 

Ce code est évidemment criblé d'erreurs: "Utilisation d'un index de button d'identificateur non déclaré" sur cette ligne: if (buttonIndex != [alertView cancelButtonIndex])

"Propriété UIImageView introuvable sur l'object de type PhotoViewController" sur cette ligne UIImageView *view = [self.UIImageView];

Et "Identificateur attendu" sur cette ligne ((UIImageView *)[self.view]).image =nil;

Je suis très novice en programmation et je suis surpris que je sois même arrivé si loin. Donc, j'essaie juste de comprendre comment je dois éditer mon code pour que les erreurs disparaissent, et qu'il puisse être utilisé quand l'une des 9 vues d'images est tapée, et aussi pour que cette méthode ne se triggers que lorsque le Le button Modifier est d'abord enfoncé. J'utilisais des balises plus tôt, et ça marchait bien, mais j'ai sauvegardé les images via NSData, donc je ne peux plus utiliser les balises. Toute aide est très appréciée, merci!

D'abord, vous ne voulez pas attacher le geste du robinet aux vues de l'image. En outre, si vous devez avoir plus de 9 images, vous pouvez vouloir une vue déroulante, ou gérer le défilement séparément. Tout d'abord, supprimez ce module de reconnaissance de gestes et toutes ses connections.

Ensuite, déterminez le type de vue que vous utiliserez comme canvas de votre galerie. Une vue simple, ou un ScrollView, ou peu importe … ça n'a pas vraiment d'importance maintenant, juste pour que ça marche. Vous voulez faire glisser ce sharepoint vue dans votre définition d'interface, il supprime donc un IBOutlet pour la vue (de cette façon, vous pouvez le referencer dans le code).

Vous allez placer vos images sur la vue que je viens de mentionner.

Vous pouvez avoir un indicateur interne pour le module de reconnaissance de gestes, mais il possède également une propriété que l'utilisation peut activer / désactiver quand vous le souhaitez. Ainsi, vous pouvez l'activer / désactiver assez facilement.

Tout ce que vous voulez faire est de déposer un seul reconnaisseur de gestes sur votre controller et de le connecter à la section d'implémentation du controller. Il va générer un bouchon pour gérer le système de reconnaissance. Il interprète les taps "généralement" pour le controller, et appelle votre code chaque fois qu'un robinet est fait sur la vue.

Encore un peu de code …

Crée un cadre pour la "nouvelle" image dans la vue déroulante.

 - (CGRect)frameForData:(MyData*)data atIndex:(NSUInteger)idx { CGPoint topLeft; int row = idx / 4; int col = idx % 4; topLeft.x = (col+1)*HORIZ_SPACING + THUMBNAIL_WIDTH * (col); topLeft.y = (row+1)*VERT_SPACING + THUMBNAIL_HEIGHT * (row); return CGRectMake(topLeft.x, topLeft.y, THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT); } 

Crée une vue d'image pour chaque élément de métadonnées et une petite bordure.

 - (UIImageView*)createImageViewFor:(MetaData*)metadata { UIImageView *imageView = [[UIImageView alloc] initWithImage:metadata.lastImage]; imageView.frame = CGRectMake(0, 0, THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT);; imageView.layer.borderColor = [[UIColor blackColor] CGColor]; imageView.layer.borderWidth = 2.0; imageView.userInteractionEnabled = YES; return imageView; } 

C'est là que les vues sont créées et ajoutées au parent …

  imageView = [self createImageViewFor:metadata]; //[data.imageView sizeToFit]; // Make sure the scrollView contentSize represents the data CGRect lastFrame = [self frameForData:data atIndex:self.data.count-1]; CGFloat newHeight = lastFrame.origin.y + lastFrame.size.height; if (self.bookshelfScrollView.contentSize.height < newHeight) { CGSize newSize = self.bookshelfScrollView.contentSize; newSize.height = newHeight; self.bookshelfScrollView.contentSize = newSize; } [self.bookshelfScrollView addSubview:data.imageView]; 

Ainsi, vous créez simplement chaque image, les ajoutez à la vue, et la seule chose que vous avez à faire est de permettre l'interaction de l'user sur eux, parce que sinon la vue défilée n'autorise pas le mouvement.

OK … En regardant le code que vous avez posté … puisque vous n'avez pas dit ce qui n'allait pas avec … difficile à dire … Le ci-dessous est votre code … Mes commentaires sont, bien, Commentaires .. .

 - (IBAction)editButtonPressed:(id)sender { editButton.hidden = YES; backToGalleryButton.hidden = NO; tapToDeleteLabel.hidden = NO; } - (IBAction)tapGesture:(UITapGestureRecognizer*)gesture { // I don't think I'd do this here, but it shouldn't cause "problems." UIAlertView *deleteAlertView = [[UIAlertView alloc] initWithTitle:@"Delete" message:@"Are you sure you want to delete this photo?" delegate:self cancelButtonTitle:@"No" otherButtonTitles:@"Yes", nil]; [deleteAlertView show]; // In your controller, you have the main view, which is the view // on which you added your UIViews. You need that view. Add it as an IBOutlet // You should know how to do that... ctrl-drag to the class INTERFACE source. // Assuming you name it "galleryView" // Take the tap location from the gesture, and make sure it is in the // coordinate space of the view. Loop through all the imageViews and // find the one that contains the point where the finger was taped. // Then, "remove" that one from its superview... CGPoint tapLocation = [gesture locationInView: self.galleryView]; for (UIImageView *imageView in self.galleryView.subviews) { if (CGRectContainsPoint(imageView.frame, tapLocation)) { [imageView removeFromSuperview]; } } } 

Personnellement, dans ma petite galerie de photos, j'ai contourné tous les éléments de reconnaissance de gestes en remplaçant les controls UIImageView controls UIButton , en définissant la propriété image pour le button comme vous le feriez pour UIImageView . Il semble identique, mais vous obtenez la fonctionnalité de taper sur une vignette gratuitement, sans aucun geste nécessaire.

Donc, ma vue a juste un UIScrollView , que j'ajoute par programmation mes images en tant que buttons avec l'set d'images pour le contrôle de button, par exemple:

 - (void)loadImages { listOfImages = [ImageData newArrayOfImagesForGallery:nil]; // some variables to control where I put my thumbnails (which happen to be 76 x 76px) int const imageWidth = 76; int const imageHeight = imageWidth; NSInteger imagesPerRow; NSInteger imagePadding; NSInteger cellWidth; NSInteger cellHeight; // some variables to keep track of where I am as I load in my images int row = 0; int column = 0; int index = 0; // add images to navigation bar for (ImageData *item in listOfImages) { // figure out what row and column I'm on imagesPerRow = self.view.frame.size.width / (imageWidth + 2); imagePadding = (self.view.frame.size.width - imageWidth*imagesPerRow) / (imagesPerRow + 1); cellWidth = imageWidth + imagePadding; cellHeight = imageHeight + imagePadding; // this is how I happen to grab my UIImage ... this will vary by implementation UIImage *thumb = [item imageThumbnail]; // assuming I found it... if (thumb) { // create my button and put my thumbnail image in it UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; button.frame = CGRectMake(column * cellWidth + imagePadding, row * cellHeight + imagePadding, imageWidth, imageHeight); [button setImage:thumb forState:UIControlStateNormal]; [button addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside]; button.tag = index++; [[button imageView] setContentMode:UIViewContentModeScaleAspectFit]; // add it to my view [scrollView addSubview:button]; // increment my column (and if necessary row) counters, making my scrollview larger if I need to) if (++column == imagesPerRow) { column = 0; row++; [scrollView setContentSize:CGSizeMake(self.view.frame.size.width, (row+1) * cellHeight + imagePadding)]; } } } } // I also have this in case the user changes orientation, so I'll move my images around if I need to - (void)rearrangeImages { if (!listOfImages) { [self loadImages]; return; } // a few varibles to keep track of where I am int const imageWidth = 76; int const imagesPerRow = self.view.frame.size.width / (imageWidth + 2); int const imageHeight = imageWidth; int const imagePadding = (self.view.frame.size.width - imageWidth*imagesPerRow) / (imagesPerRow + 1); int const cellWidth = imageWidth + imagePadding; int const cellHeight = imageHeight + imagePadding; NSArray *buttons = [[NSArray alloc] initWithArray:[scrollView subviews]]; int row; int column; int index; CGRect newFrame; // iterate through the buttons for (UIView *button in buttons) { index = [button tag]; if ([button isKindOfClass:[UIButton class]] && index < [listOfImages count]) { // figure out where the button should go row = floor(index / imagesPerRow); column = index % imagesPerRow; newFrame = CGRectMake(column * cellWidth + imagePadding, row * cellHeight + imagePadding, imageWidth, imageHeight); // if we need to move it, then animation the moving if (button.frame.origin.x != newFrame.origin.x || button.frame.origin.y != newFrame.origin.y) { [UIView animateWithDuration:0.33 animations:^{ [button setFrame:newFrame]; }]; } } } NSInteger numberOfRows = floor(([listOfImages count] - 1) / imagesPerRow) + 1; [scrollView setContentSize:CGSizeMake(self.view.frame.size.width, numberOfRows * cellHeight + imagePadding)]; } - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation { [self rearrangeImages]; } 

Espérons que cela vous donne une idée de la façon dont vous pouvez append par UIButton un UIButton pour agir comme une image dans une galerie. J'ai essayé d'éditer ceci à la volée, donc je m'excuse d'avance si j'ai introduit des erreurs dans le process, mais cela devrait vous donner une idée de ce que vous pourriez faire … J'ai enlevé mon code pour le faire dans un une queue GCD séparée (ce que je fais parce que j'ai près de 100 images, et faire cela dans la queue principale est trop lent.)

Quoi qu'il en soit, vous pouvez ensuite créer votre méthode buttonClicked pour afficher votre UIAlertView .

 - (void)buttonClicked:(UIButton *)sender { if (inEditMode) { // create your UIAlterView using [sender tag] to know which image you tapped on } } 

Enfin, vous avez deux buttons sur votre UIAlertView , mais vous ne semblez pas vérifier pour voir sur quel button l'user a cliqué. Votre controller de vue doit être un UIAlterViewDelegate , dans lequel vous avez défini votre alertView:clickedButtonAtIndex qui effectuera vos étapes d'édition.

 - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { // ok, will do what I need to do with whatever the user tapped in my alertview } 

La chose la plus simple à laquelle je puisse penser est que le geste est désactivé par défaut, et que le geste est activé dès que le button d'édition est touché. De cette façon, l'image ne répondra à l'outil de reconnaissance gestuelle que si elle est en mode "Edition".