Вопрос по ios, uiimageview, xcode, objective-c – iOS: Проблемы с TapGestureRecognizer

1

Поэтому у меня есть приложение, которое ведет себя как фотогалерея, и я реализую возможность удаления изображений пользователем. Вот настройка: у меня есть 9 UIImageViews, imageView, imageView2 и т. Д. У меня также есть & quot; Редактировать & quot; кнопка и метод действия tapGesture. Я перетащил Распознаватель жестов касанием на свое представление в IB и прикрепил его к каждому из UIImageView. Я также прикрепил метод действия tapGesture к каждому из UIImageViews. В идеале мне бы хотелось, чтобы этот метод стал активным только тогда, когда & quot; Редактировать & quot; кнопка нажата. Когда пользователь нажимает кнопку «Редактировать», а затем нажимает на изображение, которое он хочет удалить, я хотел бы, чтобы UIAlertView появился, спрашивая, уверены ли они, что хотят удалить его. Вот код, который я использую:

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

Этот код явно пронизан ошибками: & quot; Использование необъявленного идентификатора кнопки индекса & quot; на этой линии:if (buttonIndex != [alertView cancelButtonIndex])

& quot; Свойство UIImageView не найдено для объекта типа PhotoViewController & quot; на этой линииUIImageView *view = [self.UIImageView];

И & quot; Ожидаемый идентификатор & quot; на этой линии((UIImageView *)[self.view]).image =nil;

Я очень новичок в программировании, и я удивлен, что даже сделал это так далеко. Итак, я просто пытаюсь выяснить, как мне нужно отредактировать мой код, чтобы ошибки исчезли, и чтобы его можно было использовать при каждом касании одного из 9 видов изображений, а также чтобы этот метод срабатывал только тогда, когда Кнопка редактирования нажимается первой. Ранее я использовал теги, и они отлично работали, но я сохраняю изображения через NSData, поэтому больше не могу использовать теги. Любая помощь высоко ценится, спасибо!

Ваш Ответ

3   ответа
2

вы не хотите прикреплять жест касания к изображениям. Кроме того, если у вас будет более 9 изображений, вам может потребоваться просмотр с прокруткой или управление прокруткой отдельно. Сначала удалите этот распознаватель жестов и все его соединения.

Затем определите, какой тип представления вы будете использовать в качестве холста галереи. Простой View, или ScrollView, или что-то еще ... это сейчас не имеет большого значения, просто чтобы это заработало. Вы хотите перетащить это представление ctrl в определение вашего интерфейса, чтобы он отбрасывал IBOutlet для представления (таким образом, вы можете ссылаться на него в коде).

Вы поместите ваши ImageViews на вид, который я только что упомянул.

Вы можете иметь внутренний флаг для распознавателя жестов, но у него также есть свойство, которое можно использовать, чтобы включить / отключить его в любое время. Таким образом, вы можете сделать его активным / неактивным довольно легко.

Все, что вы хотите сделать, это добавить один распознаватель жестов на ваш контроллер и подключить его к секции реализации контроллера. Это создаст заглушку для обработки распознавателя. Он будет интерпретировать метки «обычно». для контроллера, и вызывайте свой код всякий раз, когда на вид делается касание.

Еще немного кода ...

Создает фрейм для & quot; нового & quot; изображение в виде прокрутки.

- (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);
}

Создает представление изображения для каждого фрагмента метаданных и небольшую рамку.

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

Это где представления создаются и добавляются в родительский ...

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

Таким образом, вы просто создаете каждый фрейм, добавляете их в представление, и единственное, что вам нужно сделать, это включить взаимодействие с пользователем, поскольку в противном случае представление прокрутки не позволяет выполнить жест.

Хорошо ... Глядя на код, который вы разместили ... так как вы не сказали, что с ним не так ... трудно сказать ... Ниже приведен ваш код ... Мои комментарии, ну, в общем, Комментарии ... ,

- (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];
        }
    }
}
Да! Перетащите от жеста в исходный файл (.m).
Нет. Я уверен, что вы перетащили ctrl из кнопки в свой код, верно? Он генерирует скелет функции, который вы заполняете, и эта функция вызывается при нажатии кнопки. Сделайте то же самое с жестом касания. Перетащите его в свой код, удерживая нажатой клавишу Ctrl, и он подключит функцию, которая будет вызываться, когда пользователь нажимает на экран. Вот где код идет, чтобы найти правильный UIImageView.
Ах, хорошо, это имеет смысл, большое спасибо! Итак, я удалил все, что я сделал, а затем перетащил новый распознаватель жестов на мой элемент управления (в итоге он появился на боковой панели IB). Затем я перетащил элемент управления из распознавателя жестов касания на значок «Управление», и появившаяся розетка была «Делегировать». Я связал это также. Я сделал правильные шаги? Извините за невероятно начинающие вопросы, и я очень ценю вашу помощь. Henry F
Я на самом деле управлял перетаскиванием от значка распознавателя жестов касания на боковой панели слева, до значка управления чуть выше него. Извините, я не понимаю, как я могу управлять перетаскиванием значка распознавания жестов касания в мой фактический код? Должен ли я управлять перетаскиванием в файл .m контроллера представления? Henry F
Большое спасибо, я только что сделал это успешно. Вы знаете, как я мог исправить ошибки в моем коде выше? Я думал, что все написал правильно, и что все будет в порядке. Но у него все еще есть несколько ошибок по какой-то причине. Еще раз спасибо! Henry F
0

которую я могу придумать, - это отключить жест по умолчанию, а затем включить жест после нажатия кнопки редактирования. Таким образом, изображение будет отображаться в распознавателе жестов касания только в том случае, если оно находится в & quot; Редактировать & quot; Режим.

Круто, большое спасибо, я сейчас посмотрю на это. Кроме того, у вас есть идеи, как избавиться от кода выше ошибок? Я думал, что все бы сошло с ума, и я не могу понять, почему это не так. Извините за вопросы новичка, я учусь, как я иду сюда. Henry F
1

стов, заменивUIImageView контролирует сUIButton управления, установка свойства изображения для кнопки, как вы бы дляUIImageView, Выглядит идентично, но тогда вы получаете возможность бесплатно нажимать на миниатюру без каких-либо жестов.

Итак, мой взгляд просто имеетUIScrollViewкоторый я программно добавляю к своим изображениям в виде кнопок с изображением, установленным для управления кнопками, например:

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

Надеюсь, что это дает вам представление о том, как вы можете программно добавитьUIButton выступать в качестве изображения в галерее. Я пытался отредактировать это на лету, поэтому заранее прошу прощения, если я внес какие-либо ошибки в процесс, но это должно дать вам представление о том, что вы могли бы предположительно сделать ... Я удалил свой код, чтобы сделать это в отдельная очередь GCD (что я делаю, потому что у меня есть около 100 изображений, и делать это в основной очереди слишком медленно.)

В любом случае, вы можете создать свойbuttonClicked способ сделать ваше отображение вашегоUIAlertView.

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

Наконец, у вас есть две кнопки на вашемUIAlertView, но вы, похоже, не проверяли, на какую кнопку нажал пользователь. Ваш контроллер представления должен бытьUIAlterViewDelegate, в котором вы определилиalertView:clickedButtonAtIndex который сделает ваши фактические шаги редактирования.

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

Похожие вопросы