Как сделать кнопку перехвата надписью для перехвата событий?

Скажем, у меня есть этот код:

#import  @interface MyView : UIView @end @implementation MyView - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { // How can I get this to show up even when the button is touched? NSLog(@"%@", [touches anyObject]); } @end @interface TestViewAppDelegate : NSObject  { UIWindow *window; } @end @implementation TestViewAppDelegate - (void)applicationDidFinishLaunching:(UIApplication *)application { window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; MyView *view = [[MyView alloc] initWithFrame:[window frame]]; [view setBackgroundColor:[UIColor whiteColor]]; UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect]; [button setTitle:@"Hiya!" forState:UIControlStateNormal]; [button setFrame:CGRectMake(100.0, 100.0, 200.0, 200.0)]; [view addSubview:button]; [window addSubview:view]; [window makeKeyAndVisible]; } - (void)dealloc { [window release]; [super dealloc]; } @end 

Есть ли способ перехватить события касания, отправляемые на кнопку? В конечном итоге я хотел бы сделать подclass UIView, который будет сообщать controllerу своего представления (или делегировать, в зависимости от того, что произойдет), когда он обнаружит салфетки, чтобы он мог «нажать» следующий controller представления в стек (подобно домашнему экрану iPhone ). Я решил, что это был первый шаг, но я открыт для предложений, если я приближаюсь к этому неправильно.

Мне было бы интересно увидеть другие решения, но самым простым способом, который я знаю, является переопределение любого из этих двух методов UIView:

 - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event; - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event; 

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

 return [super hitTest:point withEvent:event]; 

или

 return [super pointInside:point withEvent:event]; 

Инстинкт скажет «подclass UIButton», но UIButton – это кластер classов (т. Е. Фактический тип объекта прозрачно изменяется в зависимости от того, какую кнопку вы хотите создать), что делает его чрезвычайно сложным для подclassа. Если вы не переписываете UIButton, вы вряд ли сможете это сделать.

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

 @interface MyView : UIView { UIView * visibleView; } - (id) initWithFrame:(CGRect)frame controlClass:(Class)class; @end @implementation MyView - (id) initWithFrame:(CGRect)frame controlClass:(Class)class { if (self = [super initWithFrame:frame]) { CGRect visibleViewFrame = frame; visibleViewFrame.origin = CGPointZero; visibleView = [[class alloc] initWithFrame:visibleViewFrame]; [visibleView setUserInteractionEnabled:NO]; [self addSubview:visibleView]; [self setUserInteractionEnabled:YES]; [self setBackgroundColor:[UIColor clearColor]]; } return self; } - (void) dealloc { [visibleView removeFromSuperview]; [visibleView release], visibleView = nil; [super dealloc]; } - (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { if (someCondition == YES) { [visibleView touchesBegan:touches withEvent:event]; } } //and similar methods for touchesMoved:, touchesEnded:, etc @end 

Основная идея заключается в том, что вы вставляете кнопку (или что-то еще) в class контейнера (аналогично тому, что вы описали в своем вопросе). Тем не менее, вы отключите взаимодействие на кнопке, а это означает, что когда пользователь нажимает кнопку, событие нажатия «провалится» на кнопку и в кнопки, содержащие супервизор (в этом случае ваш экземпляр MyView). Оттуда вы можете обработать касание соответствующим образом. Если вы хотите, чтобы кнопка «отвечала» на ощупь, просто позвольте кнопке сделать это, отправив соответствующее сообщение UIResponder. (Возможно, сначала вам нужно снова включить userInteractionEnabled в visualView. Я не уверен в этом.)

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

Могу ли я предложить использовать этот подход вместо этого:

  UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapDetected:)]; tapRecognizer.numberOfTapsRequired = 1; tapRecognizer.numberOfTouchesRequired = 1; [self.view addGestureRecognizer:tapRecognizer]; 

Вы можете сделать это из супервизора, не нужно создавать пользовательские элементы пользовательского интерфейса.

Спасибо за предложения и информативные ответы. В итоге я просто использовал объяснение, показанное на этой странице: (в разделе «Trick 1: Emulating Photos app swiping / масштабирование / прокрутка с помощью одного UIScrollView»).

Я считаю, что в этом случае вам придется подclassифицировать UIButton и переопределить ответы на события касания и движения UIResponder. Затем вы можете перенаправить их на любой объект, который вы хотели бы предположить, что подclass UIButton может получить к нему.

В этом случае вы передадите их в супервизор UIButton.

 @interface MyButton : UIButton @end @implementation MyButton - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { [[self superview] touchesMoved:touches withEvent:event]; } @end 

См. Документацию UIResponder

  • установить фоновое изображение для всего приложения iPhone / iPad
  • Есть ли способ указать позицию / индекс аргумента в NSString stringWithFormat?
  • iOS8 - ограничения двусмысленно указывают на высоту нуля
  • Представление controllerа модального вида сразу после отклонения другого
  • Как преобразовать значения NSString в шестнадцатеричные значения
  • Можем ли мы пригласить людей использовать наше приложение или отправить запрос друга из приложения через Facebook в iOS 5?
  • Сравнение поплавковых и двойных типов данных в объекте C
  • Как я могу получить объект NSDate на сегодня в полночь?
  • Убедитесь, что вход в UITextField только числовой
  • Остановить UIWebView от «подпрыгивания» по вертикали?
  • UISlider вместе с ProgressView
  • Давайте будем гением компьютера.