Как сослаться на контроллер представления из селектора 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 и прекрасно подходит для решения этой проблемы.