Пробелем с NSTimer - PullRequest
       2

Пробелем с NSTimer

1 голос
/ 26 июля 2010

У меня проблема с 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];      
}

Ответы [ 3 ]

2 голосов
/ 26 июля 2010

У вас неправильная подпись для вашего метода

- (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];  

- edit -

Если вы хотите сохранить свой старый метод, чтобы вы могли вызывать его из другого места с аргументом 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];
1 голос
/ 26 июля 2010

NSTimer методы огня должны иметь подпись:

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

Таймер передает себя в качестве аргумента установленному вами методу.

Если вам нужны дополнительные параметры, установите их в словаре информации о пользователе, а затем получите их, используя их ключ, используя:

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

Так, в качестве примера, вы должны установить объект NSNumber в своей пользовательской информации и получить его таким образом, не передавая его в качестве параметра методу таймера.

0 голосов
/ 02 декабря 2011

, как указано в нескольких других ответах, сигнатура 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)\
/***/)

способ их использования относительно прост, и imho делает для болеечитаемый код, чем оборачивание функции 3 раза для учета вариантов вызова.

, но сначала некоторая справочная информация о том, как она работает.

ваш селектор метода таймера может быть достаточно безопасно выражен в его самой простой форме,

- (void)myMethod:(id)sender;

без каких-либо неприятных событий на пути.все это означает, что «отправитель» не имеет типа объекта, и вы не можете многое с ним сделать, не приведя его к типу, который вы ожидаете.прежде чем вы сможете безопасно выполнить приведение, вам необходимо точно знать, что объект имеет правильный тип.

Вот где макросы помогают в том, что они оборачивают отправителя серией тестов, отфильтровывающих неправильные типы иверните ноль вместо того, чтобы позволить вам отправить неправильный селектор объекту, который не может ответить на него.обратите внимание, что сами макросы могут быть выражены более кратко, однако для понимания того, как они работают, и без каких-либо потерь производительности, я решил выразить их с комментариями.Вы всегда можете их урезать, однако реального выигрыша в производительности нет, так как они приведут к тому же скомпилированному выводу.

примеры теоретического использования:

Получатель 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" разрешается в ноль.если массив содержит 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];
...