代码之家  ›  专栏  ›  技术社区  ›  user102008

如何在Cocoa中使用performSelector:withObject:afterDelay:与基本类型一起使用?

  •  97
  • user102008  · 技术社区  · 16 年前

    NSObject performSelector:withObject:afterDelay: 允许我在一段时间后使用对象参数调用对象的方法。它不能用于具有非对象参数的方法(例如int、floats、structs、非对象指针等)。

    用一个带有非对象参数的方法来实现同样的事情的方法是什么?我知道这是正常的 performSelector:withObject: ,解决方案是使用 NSInvocation

    13 回复  |  直到 16 年前
        1
  •  69
  •   Ovesh    14 年前

    SEL theSelector = NSSelectorFromString(@"setOrientation:animated:");
    NSInvocation *anInvocation = [NSInvocation
                invocationWithMethodSignature:
                [MPMoviePlayerController instanceMethodSignatureForSelector:theSelector]];
    
    [anInvocation setSelector:theSelector];
    [anInvocation setTarget:theMovie];
    UIInterfaceOrientation val = UIInterfaceOrientationPortrait;
    BOOL anim = NO;
    [anInvocation setArgument:&val atIndex:2];
    [anInvocation setArgument:&anim atIndex:3];
    
    [anInvocation performSelector:@selector(invoke) withObject:nil afterDelay:1];
    
        2
  •  35
  •   Sabby    9 年前

        3
  •  13
  •   user349819    13 年前

    //nil will be cast to NO when the selector is performed
    [self performSelector:@selector(setHidden:) withObject:nil afterDelay:5.0];
    
    //self will be cast to YES when the selector is performed
    [self performSelector:@selector(setHidden:) withObject:self afterDelay:10.0];
    
        4
  •  8
  •   Remus Rusanu    16 年前

    或许 NSValue

        5
  •  8
  •   Sorin Antohi    12 年前

    我知道这是一个老问题,但如果你正在构建iOS SDK 4+,那么你可以使用块来实现这一点,只需付出很少的努力,并使其更具可读性:

    double delayInSeconds = 2.0;
    int primitiveValue = 500;
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
        [self doSomethingWithPrimitive:primitiveValue];     
    });
    
        6
  •  5
  •   justin    12 年前

    PerformSelector:WithObject总是接受一个对象,所以为了传递int/double/float等参数……你可以使用这样的东西。

    //NSNumber is an object..
    
        [self performSelector:@selector(setUserAlphaNumber:) withObject: [NSNumber numberWithFloat: 1.0f]
        afterDelay:1.5];
    
        -(void) setUserAlphaNumber: (NSNumber*) number{
    
         [txtUsername setAlpha: [number floatValue] ];
        }
    

        7
  •  5
  •   Avijit Nagare    9 年前

    [MONBlock performBlock:^{[obj setFrame:SOMETHING];} afterDelay:2];
    

    @interface MONBlock : NSObject
    
    + (void)performBlock:(void(^)())pBlock afterDelay:(NSTimeInterval)pDelay;
    
    @end
    
    @implementation MONBlock
    
    + (void)imp_performBlock:(void(^)())pBlock
    {
     pBlock();
    }
    
    + (void)performBlock:(void(^)())pBlock afterDelay:(NSTimeInterval)pDelay
    {
      [self performSelector:@selector(imp_performBlock:)
                 withObject:[pBlock copy]
                 afterDelay:pDelay];
    }
    
    @end
    

    例子:

    int main(int argc, const char * argv[])
    {
     @autoreleasepool {
      __block bool didPrint = false;
      int pi = 3; // close enough =p
    
      [MONBlock performBlock:^{NSLog(@"Hello, World! pi is %i", pi); didPrint = true;} afterDelay:2];
    
      while (!didPrint) {
       [NSRunLoop.currentRunLoop runUntilDate:[NSDate dateWithTimeInterval:0.1 sinceDate:NSDate.date]];
      }
    
      NSLog(@"(Bye, World!)");
     }
     return 0;
    }
    

        8
  •  3
  •   Odd-Arne    11 年前

    我总是建议你使用NSMutableArray作为传递的对象。这是因为你可以传递多个对象,比如按下的按钮和其他值。NSNumber、NSInteger和NSString只是一些有价值的容器。确保从数组中获取对象时

    #define DELAY_TIME 5
    
    -(void)changePlayerGameOnes:(UIButton*)sender{
        NSNumber *nextPlayer = [NSNumber numberWithInt:[gdata.currentPlayer intValue]+1 ];
        NSMutableArray *array = [[NSMutableArray alloc]initWithObjects:sender, nil];
        [array addObject:nextPlayer];
        [self performSelector:@selector(next:) withObject:array afterDelay:DELAY_TIME];
    }
    -(void)next:(NSMutableArray*)nextPlayer{
        if(gdata != nil){ //if game choose next player
           [self nextPlayer:[nextPlayer objectAtIndex:1] button:[nextPlayer objectAtIndex:0]];
        }
    }
    
        9
  •  2
  •   GeneCode    14 年前

    我也想这样做,但使用一个接收BOOL参数的方法。用NSNumber包裹bool值,传递值失败。我不知道为什么。

    [self performSelector:@selector(dummyCaller:) withObject:nil afterDelay:5.0];
    
    -(void)dummyCaller {
    
    [self myFunction:YES];
    
    }
    
        10
  •  2
  •   Jason Harris    13 年前

    #import <objc/message.h>
    
    
    SEL theSelector = @selector(integerDidChange:);
    if ([self.delegate respondsToSelector:theSelector])
    {
        typedef void (*IntegerDidChangeFuncPtrType)(id, SEL, NSInteger);
        IntegerDidChangeFuncPtrType MyFunction = (IntegerDidChangeFuncPtrType)objc_msgSend;
        MyFunction(self.delegate, theSelector, theIntegerThatChanged);
    }
    

        11
  •  1
  •   Unis    15 年前

    [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(yourMethod:) userInfo:nil repeats:NO]
    
        12
  •  1
  •   Anomie    14 年前

    指针 转换为int、float或其他类型,并使用它。

    但解决方案简单明了。创建NSInvocation并调用

    [invocation performSelector:@selector(invoke) withObject:nil afterDelay:delay]

        13
  •  0
  •   Jim Hillhouse    15 年前

    CGFloat myFloat = 2.0; 
    NSNumber *myNumber = [NSNumber numberWithFloat:myFloat];
    
    [self performSelector:@selector(MyCalculatorMethod:) withObject:myNumber afterDelay:5.0];