【问题标题】:Probelem with NSTimerNSTimer 的问题
【发布时间】:2010-07-26 09:37:09
【问题描述】:

NSTimer 有问题。 我收到了“SIGABRT”错误和[NSCFTimer intValue]: unrecognized selector sent to instance

这是我的代码:

-(void)detectionMove:(NSNumber*)arrayIndex{


    static BOOL notFind = FALSE;
    static int countVariable = 0;
    static int countRilevamenti = 0;

    notFind = FALSE;

    for(int i = countVariable+1; i<[[[[sharedController arrayMovement]objectAtIndex:[arrayIndex intValue]] arrayPositionMove]count]; i++){

        if(!notFind){

            if((actualAccelerometerX+sensibilityMovement) >= [[[[[sharedController arrayMovement]objectAtIndex:[arrayIndex intValue]] arrayPositionMove]objectAtIndex:i]valueX] && (actualAccelerometerX-sensibilityMovement) <= [[[[[sharedController arrayMovement]objectAtIndex:[arrayIndex intValue]] arrayPositionMove]objectAtIndex:i]valueX] &&
               (actualAccelerometerY+sensibilityMovement) >= [[[[[sharedController arrayMovement]objectAtIndex:[arrayIndex intValue]] arrayPositionMove]objectAtIndex:i]valueY] && (actualAccelerometerY-sensibilityMovement) <= [[[[[sharedController arrayMovement]objectAtIndex:[arrayIndex intValue]] arrayPositionMove]objectAtIndex:i]valueY] &&
               (actualAccelerometerZ+sensibilityMovement) >= [[[[[sharedController arrayMovement]objectAtIndex:[arrayIndex intValue]] arrayPositionMove]objectAtIndex:i]valueZ] && (actualAccelerometerZ-sensibilityMovement) <= [[[[[sharedController arrayMovement]objectAtIndex:[arrayIndex intValue]] arrayPositionMove]objectAtIndex:i]valueZ])
            {
                countVariable = i;
                notFind = TRUE;
                countRilevamenti++;
            }
        }
    }

    if(!notFind)
        return;

    else if(countVariable+1 == [[[[sharedController arrayMovement]objectAtIndex:[arrayIndex intValue]]  arrayPositionMove]count]){

        if(countRilevamenti + tollerance >= [[[[sharedController arrayMovement]objectAtIndex:[arrayIndex intValue]] arrayPositionMove]count])
            movementDetected = [arrayIndex intValue];
        else
            NSLog(@"troppo veloce");

        countVariable = 0;
        notFind = FALSE;
        countRilevamenti = 0;       

        return;
    }

    [NSTimer scheduledTimerWithTimeInterval:timeToCatch target:self selector:@selector(detectionMove:) userInfo:(NSNumber*)arrayIndex repeats:NO];      
}

【问题讨论】:

    标签: iphone objective-c nstimer


    【解决方案1】:

    您的方法签名错误

    - (void)timerFireMethod:(NSTimer*)theTimer
    

    不是NSNumber

    --edit2--

    NSMutableDictionary *myDictionary = [[NSMutableDictionary alloc] init];  
    [myDictionary setObject:arrayIndex forKey:@"index"];
    [NSTimer scheduledTimerWithTimeInterval:timeToCatch target:self selector:@selector(detectionMove:) userInfo:myDictionary repeats:NO];  
    

    --编辑--

    如果您想保留旧方法,以便可以使用 NSNumber 参数从其他地方调用它,您必须创建一个新方法供 NSTimer 调用,然后在实现 NSTimer 方法您可以使用任何合适的数字调用NSNumber 方法。

    -(void)detectionMove:(NSNumber*)arrayIndex{
     // still does whatever
    }
    
    -(void)automaticDetectionMove:(NSTimer*)theTimer{
     [self detectionMove:whatevernumber];
    }
    
    // update with new method name
    [NSTimer scheduledTimerWithTimeInterval:timeToCatch target:self selector:@selector(automaticDetectionMove:) userInfo:(NSNumber*)arrayIndex repeats:NO];
    

    【讨论】:

    • 那么它将无法与 NSTimer 一起使用。 NSTimer 无论如何都不知道您想将哪个数字传递给该方法。这有意义吗?
    • 但是 [NSTimer scheduledTimerWithTimeInterval:timeToCatch 目标:self 选择器:@selector(automaticDetectionMove:) userInfo:(NSNumber*)arrayIndex repeats:NO];是否进入 -(void)automaticDetectionMove:(NSTimer*)theTimer{ } 方法?还是不行?
    • 不,您必须创建自己的字典并将其发送到 NSTimer,请参阅 update2
    【解决方案2】:

    NSTimerfire 方法必须有签名:

    - (void)myMethod:(NSTimer *)timer;
    

    计时器将自己作为参数传递给您设置的方法。

    如果您需要额外的参数,请将它们设置在用户信息字典中,然后使用它们的键检索它们:

    [[timer userInfo] objectForKey:@"myUserInfoParamterKey"];
    

    例如,您应该在用户信息中设置 NSNumber 对象并以这种方式检索它,而不是将其作为参数传递给计时器方法。

    【讨论】:

      【解决方案3】:

      正如其他几个答案所指出的,NSTimer 签名是

      - (void)methodName:(NSTimer *)timer;
      

      如果您有时需要直接调用方法,有时通过计时器(或者可能使用包含所需参数的键的字典)而不是包装,您可能需要考虑添加一组帮助宏来放置在您的项目 .pch 文件中

      #define ifThenElse(_if_,_then_,_else_) ( (_if_) ? _then_ : _else_ )
      
      #define isClass(objectToTest,isOfClass) ifThenElse(objectToTest==nil,NO,[objectToTest isKindOfClass:[isOfClass class]])
      
      #define asClass(object,requiredClass) \
      /**/ifThenElse(isClass(object,requiredClass),\
      /*****/((requiredClass *)object),\
      /****/nil\
      /***/)
      
      
      #define asClassViaMethod(object,requiredClass,viaClass,viaMethod) \
      /**/ifThenElse(isClass(object,requiredClass),\
      /*****/(requiredClass *)object,\
      /*****/ifThenElse(isClass(object,viaClass),\
      /*********/(requiredClass *)[(viaClass*)object viaMethod],\
      /*********/nil)\
      /***/)
      

      您使用它们的方式相对简单,而且恕我直言,与将函数包装 3 次以解决变体调用相比,imho 生成的代码更具可读性。

      但首先要了解它的工作原理。

      您的计时器方法选择器可以以最基本的形式相当安全地表达,

      - (void)myMethod:(id)sender;
      

      途中没有发生任何令人讨厌的事情。这意味着“发件人”没有对象类型,如果不将其转换为您期望的类型,您将无法做很多事情。 但是,在您可以安全地进行转换之前,您需要确定对象的类型是正确的。

      这就是宏的帮助,因为它们使用一系列测试来包装发送者,这些测试过滤掉不正确的类型并返回 nil,而不是允许您向无法响应的对象发送不正确的选择器。请注意,宏本身可以用更简洁的方式表达,但是为了理解它们是如何工作的,并且没有任何性能开销,我选择用 cmets 来表达它们。你总是可以修剪它们,但是没有真正的性能优势,因为它们会产生相同的编译输出。

      理论使用示例:

      NSTimer 收件人 - 您希望使用 NSNumber,但计时器会自行发送给您。

      - (void)myMethod:(id)sender{
          NSNumber *argument = asClassViaMethod(sender,NSNumber,NSTimer,userInfo);
      
      
      }
      

      UIGestureRecognizer 收件人 - 您希望视图使用,由 GR 自己发送给您。

      - (void)myMethod:(id)sender{
          NSNumber *argument = asClassViaMethod(sender,UIView,UIGestureRecognizer,view);
      
      
      }
      

      您正在扩展的自定义方法,但不想破坏它 它曾经是:

      - (void)myMethod:(NSNumber *)number{
           [myOtherObject setNumber:number];
      }
      

      但它现在需要一个 NSNumber 和一个 NSString,而不仅仅是一个 NSNumber。您有时也可能只想自己发送一个 NSString

      调整了方法头和参数解析器

      - (void)myMethod:(id)sender{
      
          NSNumber *number = asClassViaMethod(sender,UIView,NSDictionary,objectForKey:@"number");
          NSNumber *string = asClassViaMethod(sender,UIView,NSDictionary,objectForKey:@"string");
      
          if (number) {
             // do something funky with number
          }
      
          if (string) {
             // do something funky with string
          }
      
      }
      

      现实世界使用我的一个项目中的示例剪切和粘贴:

      NSInteger artistIndex = asClassViaMethod(artistIndex_, NSNumber, NSTimer, userInfo).integerValue;
      

      ...

      NSDictionary *payload = asClassViaMethod(sender,NSDictionary,NSTimer,userInfo);
      

      附带说明,当您希望灵活地直接调用该方法而不需要包装器时,这是一种将多个参数发送到计时器方法的便捷方式...

      UIView *tappee = asClassViaMethod(sender,UIView,UITapGestureRecognizer,view);
      

      ...

          for (id element in connectArray) {
              NSURL *url                  =  asClassViaMethod(element, NSURL,   NSDictionary, objectForKey:@"url");
              NSArray *additionalHeaders  =  asClassViaMethod(element, NSArray, NSDictionary, objectForKey:@"headers");
      
      
              NSString *path = [url path];
              NSString *query = [url query];
              if (query.length) {
                  path = [[url path] stringByAppendingFormat:@"?%@",query];
              }
      
      
              [self requestDocument:path additionalHeaders:additionalHeaders];
          }
      

      在最后一个例子中,如果数组包含一个 NSURL,它会使用它,“additionalHeaders”被解析为 nil。 如果数组包含一个 NSDictionary,其中包含一个 NSURL 和一个 NSArray,键分别为 @"url" 和 @"headers",它使用提供的值。

      最后,如果不明显,调用你的计时器方法

      [NSTimer scheduledTimerWithTimeInterval:10.0 target:self selector:@selector(myMethod:) userInfo:[NSNumber numberWithInteger:myNSInteger] repeats:NO];
      

      ...或...

      [NSTimer scheduledTimerWithTimeInterval:10.0 target:self selector:@selector(myMethod:) userInfo:[NSDictionary dictionaryWithObjectsAndKeys: myNSNumber,@"number",myNSString,@"string",nil] repeats:NO];
      

      【讨论】:

        猜你喜欢
        • 2011-10-07
        • 2023-04-08
        • 1970-01-01
        • 2016-06-19
        • 1970-01-01
        • 2011-03-21
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多