从 UITouch 对象调用 UIGestureRecognizer

Posted

技术标签:

【中文标题】从 UITouch 对象调用 UIGestureRecognizer【英文标题】:Calling UIGestureRecognizer from UITouch object 【发布时间】:2014-01-16 00:16:26 【问题描述】:

我正在尝试将 Gesture 与 UITouch 对象相关联,因为我需要通过目标操作方法传递数据。

我实现了一些东西,但效率低下,它得到了 100% 的 CPU 处理,可能是因为它编码不正确。

我的 UITouch 事件的实例方法调用了 UIPangesture

- (BOOL)beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event

return YES;


UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc]
                                      initWithTarget:self action:@selector(handlePan:)];



[self addGestureRecognizer: panGesture];




UIPAnGestureRecognizer 有我的实例方法

- (IBAction)handlePan:(UIPanGestureRecognizer *)event

if (event.numberOfTouches==1)

    CGPoint lastPoint = [event locationOfTouch: event.numberOfTouches - 1 inView:     event.view];
    CGRect bounds = self.bounds;
    CGPoint center = CGPointMake(CGRectGetMidX(bounds), CGRectGetMidY(bounds));
    CGPoint delta = CGPointMake(lastPoint.x - center.x,  lastPoint.y - center.y);
    CGFloat angle = (delta.y == 0 ? delta.x >= 0 ? 0 : M_PI : atan2(delta.y, delta.x));
    angle = fmod(angle,  M_PI * 2.0);
    angle += angle >= 0 ? 0 : M_PI * 2.0;
    UIColor *color = [UIColor colorWithHue: angle / (M_PI * 2.0) saturation:1. brightness:1. alpha:1];
    if ([color getRed: &r green: &g blue:&b alpha: &a])
        rValue = r;
        gValue = g;
        bValue = b;

        [self setNeedsDisplay];
        [self sendActionsForControlEvents:UIControlEventValueChanged];
        [self updateLabels];


    
  

还有调用action方法从颜色选择器中获取变量的方法

- (void)setup:(CsoundObj *)csoundObj

NSLog(@"Color value - R : %f G : %f : B %f", rValue, gValue, bValue);
channelPtrR = [csoundObj getInputChannelPtr:@"mix" channelType:CSOUND_CONTROL_CHANNEL];
channelPtrG = [csoundObj getInputChannelPtr:@"pitch" channelType:CSOUND_CONTROL_CHANNEL];
channelPtrB = [csoundObj getInputChannelPtr:@"c" channelType:CSOUND_CONTROL_CHANNEL];
cachedValueR = rValue;
cachedValueG = gValue;
cachedValueB = bValue;
self.cacheDirty = YES;

[self addTarget:self action:@selector(updateValueCache:) forControlEvents:UIControlEventValueChanged];


- (void)updateValueCache:(id)sender

cachedValueR = ((CustomView*)sender).rValue;
cachedValueG = ((CustomView*)sender).gValue;
cachedValueB = ((CustomView*)sender).bValue;
self.cacheDirty = YES;


- (void)updateValuesToCsound

if (self.cacheDirty) 
    *channelPtrR = cachedValueR;
    *channelPtrG = cachedValueG;
    *channelPtrB = cachedValueB;
    self.cacheDirty = NO;



- (void)updateValuesFromCsound




- (void)cleanup

[self removeTarget:self action:@selector(updateValueCache:)   forControlEvents:UIControlEventValueChanged];

我知道问题在于调用 UIPangesture 的 UITouch 事件的实例方法,还有其他更有效的方法吗?

【问题讨论】:

【参考方案1】:

我认为您过于频繁地调用这部分代码:

   CGPoint lastPoint = [event locationOfTouch: event.numberOfTouches - 1 inView:     event.view];
    CGRect bounds = self.bounds;
    CGPoint center = CGPointMake(CGRectGetMidX(bounds), CGRectGetMidY(bounds));
    CGPoint delta = CGPointMake(lastPoint.x - center.x,  lastPoint.y - center.y);
    CGFloat angle = (delta.y == 0 ? delta.x >= 0 ? 0 : M_PI : atan2(delta.y, delta.x));
    angle = fmod(angle,  M_PI * 2.0);
    angle += angle >= 0 ? 0 : M_PI * 2.0;
    UIColor *color = [UIColor colorWithHue: angle / (M_PI * 2.0) saturation:1. brightness:1. alpha:1];
    if ([color getRed: &r green: &g blue:&b alpha: &a])
        rValue = r;
        gValue = g;
        bValue = b;

        [self setNeedsDisplay];
        [self sendActionsForControlEvents:UIControlEventValueChanged];
        [self updateLabels];


    

您可能会在没有变化或几乎没有变化时调用它。您可以做两件事来减少调用次数。您可以像这样测试角度的显着变化:

//class property
@property (nonatomic, assign) CGFloat lastAngle;

//In your code
    CGFloat deltaAngle = fabs(self.lastAngle - angle)
    if (deltaAngle > 0.5)   //select whatever delta works best
        angle += angle >= 0 ? 0 : M_PI * 2.0;
        UIColor *color = [UIColor colorWithHue: angle / (M_PI * 2.0) saturation:1. brightness:1. alpha:1];
        if ([color getRed: &r green: &g blue:&b alpha: &a])
            rValue = r;
            gValue = g;
            bValue = b;

            [self sendActionsForControlEvents:UIControlEventValueChanged];
            [self updateLabels];
            [self setNeedsDisplay];
        
    

或者您可以像这样测试自上次更新以来的时间

  //class property
    @property (nonatomic, retain) NSDate *lastTime;

    //set it when the view loads
    self.lastTime = [NSDate date];

    //In your code
        NSTimeInterval interval = [[NSDate date] timeIntervalSinceDate:lastdate];
        self.lastTime = [NSDate date];
        if (interval > 0.05)   //select whatever time interval works best
            angle += angle >= 0 ? 0 : M_PI * 2.0;
            UIColor *color = [UIColor colorWithHue: angle / (M_PI * 2.0) saturation:1. brightness:1. alpha:1];
            if ([color getRed: &r green: &g blue:&b alpha: &a])
                rValue = r;
                gValue = g;
                bValue = b;

                [self sendActionsForControlEvents:UIControlEventValueChanged];
                [self updateLabels];
                [self setNeedsDisplay];
            
        

另外,您确定需要 [self setNeedsDisplay] 吗?

【讨论】:

非常感谢 HalR,你说得对,我在调用 setNeedsDisplay 但我不需要它,现在它运行得非常好。

以上是关于从 UITouch 对象调用 UIGestureRecognizer的主要内容,如果未能解决你的问题,请参考以下文章

iOS开发UITouch触摸API简介

苹果触屏接口啥时候打开

UITouch

如何从 - (void)touchesEnded:withEvent: 获取 UITouch 位置的 UIView 对象?

UITouch && UIGestureRecognizer

如何将 Obj-C 中的 UITouch 对象与 WebKit JavaScript 中的相应触摸对象匹配?