【问题标题】:How do I tell my ViewController a View was touched?我如何告诉我的 ViewController 一个视图被触摸了?
【发布时间】:2014-03-06 01:45:19
【问题描述】:

我正在学习斯坦福 iOS 课程,并且有一点设计问题。在课堂上,我们正在制作一个卡片匹配游戏,屏幕上有大约 20 张卡片。我最近制作了卡片 UIViews,所以我可以正确地绘制它们。

我给了他们每个人一个方法tap,它将faceUp 交换为是/否,从而翻转卡片。我在我的 ViewController 中为每个手势识别器添加了手势识别器,它可以工作。单独的卡片知道它们何时被触摸和翻转。

但是,我需要在我的 ViewController 中知道 cardView 已被触摸...以及哪一个。

我必须如何/以什么方式做到这一点?我可以在我的视图中广播一些 ViewController 会监听的东西吗?我可以让我的 viewController 处理点击(但是如果我这样做,有没有办法获得发送视图?)如果这真的是基础,我很抱歉,但我是 iOS 新手,不想通过修补和实现来学习一个损坏的 MVC 模式。

编辑:仅供参考,这是我的最终实现。

每个 CardView 上都有一个点击识别器。当点击被识别时,它会调用:

- (void)cardTapped:(UIGestureRecognizer *)gesture
{
    UIView *view = [gesture view]; // This method is what I was looking for. 
    if ([view isKindOfClass:[PlayingCardView class]]) {
        PlayingCardView *playingCardView = (PlayingCardView *)view;
        [playingCardView flip];  // flips card
        // Game code
        if (!self.game.hasStarted) {
            [self startGame];
        }
        int cardIndex = [self.cardViews indexOfObject:playingCardView];
        [self.game chooseCardAtIndex:cardIndex];
        [self updateUI];
    }
}

【问题讨论】:

  • 如果您正在学习最后一门课程(为 iPhone 和 iPad 开发 IOS 7 应用程序),您应该在以下位置找到答案的开头:Lecture 1 / Slide 22(从视图到 VC,使用 Target Action !)
  • 是处理卡片视图级别翻转的代码还是包含您卡片的视图控制器?
  • 卡片会在当前状态下自行绘制。因此,所需要做的就是修改 faceUp 变量。在我当前的实现中,我的 ViewController 现在识别被点击的视图,修改 faceUp,然后继续进行卡片点击所需的游戏代码。
  • 仅供参考,您应该依赖附加到手势识别器的方法,而不是 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
  • @tiguero 我有点想知道这一点。现在看来我有一个没用的方法。但是 touchesBegan 里面有我需要的信息。而我似乎无法通过手势识别器调用的方法来获取该信息。此外,它独立于手势识别器工作。所以也许只删除手势识别器更有意义

标签: ios iphone objective-c


【解决方案1】:

tag 属性会告诉你哪个视图被点击了。在创建视图时设置正确的标签,并且在点击时触发的操作方法中,您可以调用委托方法,该方法将通知您的委托有关已点击的视图。使您的视图控制器具有委托,它将收到通知。

// your target method will look like this:
- (void) didTap:(id)sender {

   //... your code that handle flipping the card

   [self.delegate didTapOnCard:self]; // where delegate is your view controller

}

【讨论】:

    【解决方案2】:

    您可以使用 touchesBegan 方法来检测哪个视图被点击。

    -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    {
        UITouch *touch = [touches anyObject];
        NSLog(@"%d", [touch view].tag); // Considering you have set tags for your UIViews.. 
    
    if([touch view] == cardView1) // Considering you have a view as cardView1
    {
        NSLog(@"cardView1 is tapped");
    }
    
    }
    

    【讨论】:

    • 这会放在我的 ViewController 中吗?如果这是可能的,那将是理想的。然后我会将我的手势识别器移动到我的 ViewController 是吗?
    • 如果用户按下视图然后将其拖离,则触摸开始也会触发。
    【解决方案3】:

    在您的UIView 卡片类中添加

    - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)e {
        UITouch *touch = [touches anyObject];
    
        if ([self pointInside:[touch locationInView:self] withEvent:nil]) {
            [self touchesCancelled:touches withEvent:e];
            // Add your card flipping code here
        }
    }
    

    【讨论】:

      【解决方案4】:

      广播方式:在你的 UIView 的tap 方法中,发送通知:

      [[NSNotificationCenter defaultCenter] postNotificationName:@"cardTapped" object:self userInfo:@{ @"card": @(self.cardId), @"faceUp": @(self.faceup) }];
      

      并在您的 ViewController 中订阅该通知:

      [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(cardTapped:) name:@"cardTapped" object:nil];
      

      并实施

      -(void)cardTapped:(NSNotification*)notification
      {
          int card = [[notification.userInfo objectForKey:@"card"] intValue];
          BOOL faceUp = [[notification.userInfo objectForKey:@"faceUp"] boolValue];
      }
      

      【讨论】:

      • 为什么不使用委托?
      • 取决于...我有时更喜欢通知提供的松散耦合,尤其是当有多个接收者时。
      • 当你需要通知多个对象一个事件时,你应该使用通知这里只需要通知一个对象:视图控制器
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多