Как сослаться на контроллер представления из селектора UIPanGestureRecognizer в iOS?

Фон:

У меня есть поляроидный объект на основе MVC. Модель хранит метаданные фотографии и изображения. Представление отображает имя фотографии и изображение (через UIView). Контроллер имеет доступ к модели и представлению и координирует операции между ними (например, отображение модели при появлении изображения)

Моя цель:

Я хочу реализовать простую функцию перетаскивания в моей программе, чтобы пользователь мог перетащить представление полярида и viewcontroller в альбом.

Эта проблема:

Я могу добавить UIPanGestureRecognizer в поле зрения моего поляроида. Однако я не могу получить доступ к контроллеру или модели из метода polaroidPanned.

Добавление UIPanGestureRecognizer:

 UIPanGestureRecognizer *panRecogniser = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(polaroidPanned:)];
    [polaroidController.polaroidView addGestureRecognizer:panRecogniser];

Вот обработчик UIPanGestureRecognizer:

    - (void) polaroidPanned: (UIPanGestureRecognizer *) panGesture
{
    CGPoint touchLocation = [panGesture locationInView:self.view];

    //While being dragged
    if ([panGesture state] == UIGestureRecognizerStateBegan || [panGesture state] == UIGestureRecognizerStateChanged) 
    {
        //update the album view to the touch location
        [panGesture view].center = touchLocation;
    }
    else  if ([panGesture state] == UIGestureRecognizerStateEnded && isOntopOfAlbum)
    {
        //HERE I WANT TO PASS THE VIEW CONTROLLER OF THE [panGesture view] to my album
        [album addPolaroidViewController: ????]

    }
}

Я могу передать представление, но не могу ссылаться на ViewController представления.

Кто-нибудь знает, как мне это сделать? Или обойти это?

3 ответа

Решение

Предполагая, что вы не можете изменить код вашего PolaroidViewController или PolaroidView. У вас есть альтернативы. Одним из них является использование связанных объектов.

В Objective-C вы можете вставить свойства времени выполнения в объекты. Это идет с парой "уловок", но если у вас нет контроля над представлением и контроллером, это может помочь.

Сначала импортируйте objc/runtime.h в ваш источник

#import <objc/runtime.h>

Объявите ключ, используемый для получения вашего ассоциированного объекта

const NSString* kViewController = @"panGestureViewController";    

Затем, когда вы создаете свой UIPanGestureRecognizer, вы связываете объект следующим образом:

// Create
UIPanGestureRecognizer *panRecogniser = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(polaroidPanned:)];
[polaroidController.polaroidView addGestureRecognizer:panRecogniser];
// Associate
objc_setAssociatedObject(panRecogniser, &kViewController, polaroidController,OBJC_ASSOCIATION_ASSIGN);

Чтобы получить связанный объект в вашем обработчике

- (void) polaroidPanned:(UIPanGestureRecognizer *)panGesture
{
    PolaroidViewController* viewController = ((NSNumber*)objc_getAssociatedObject(panGesture, &kViewController)
    //...    
}

Я сделал аналогичный компонент недавно. Вы не можете (насколько я знаю) напрямую получить контроллер представления представления. Однако, если вы измените структуру объекта, являющегося целью распознавателя жестов, вы можете поддержать свой собственный поиск VC. Обычно я устанавливаю цель в качестве контроллера представления, который сначала создает распознаватель жестов. Затем я добавляю в словарь ключевые слова для представления, чтобы можно было искать контроллер представления из обратного вызова. Хитрость в использовании представления для словарного ключа состоит в том, чтобы "обернуть" его как NSValue с помощью [NSValue valueWithNonretainedObject:theView]

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

Другие вопросы по тегам