[objective-c] Cocoa의 기본 유형과 함께 performSelector : withObject : afterDelay :를 사용하는 방법?

NSObject메서드를 performSelector:withObject:afterDelay:사용하면 일정 시간 후에 개체 인수를 사용하여 개체에 대한 메서드를 호출 할 수 있습니다. 객체가 아닌 인수 (예 : 정수, 부동 소수점, 구조체, 객체가 아닌 포인터 등)가있는 메서드에는 사용할 수 없습니다.

객체가 아닌 인수가있는 메서드로 동일한 작업을 수행 하는 가장 간단한 방법 은 무엇입니까 ? 나는 regular performSelector:withObject:의 경우 해결책이 사용하는 것임을 알고 있습니다 NSInvocation(그런데 정말 복잡합니다). 하지만 “지연”부분을 처리하는 방법을 모르겠습니다.

감사,



답변

다음은 NSInvocation을 사용하여 변경할 수없는 것을 호출하는 데 사용 된 것입니다.

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


답변

float, boolean, int 또는 이와 유사한 것을 NSNumber로 감싸십시오.

구조체의 경우 편리한 솔루션을 모르지만 이러한 구조체를 소유하는 별도의 ObjC 클래스를 만들 수 있습니다.


답변

이 답변을 사용하지 마십시오. 나는 역사적 목적으로 만 남겨 두었습니다. 아래 설명을 참조하십시오.

BOOL 매개 변수 인 경우 간단한 트릭이 있습니다.

아니요에는 nil을 전달하고 YES에는 self를 전달하십시오. nil은 BOOL 값 NO로 캐스트됩니다. self는 YES의 BOOL 값으로 캐스트됩니다.

이 접근 방식은 BOOL 매개 변수가 아닌 경우 분류됩니다.

self가 UIView라고 가정합니다.

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


답변

아마도 NSValue , 지연 후에도 포인터가 여전히 유효한지 확인하십시오 (즉, 스택에 할당 된 객체가 없음).


답변

나는 이것이 오래된 질문이라는 것을 알고 있지만 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];
});


답변

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

같은 방법으로 [NSNumber numberWithInt :] 등을 사용할 수 있으며 수신 방법에서 숫자를 [number int] 또는 [number double] 형식으로 변환 할 수 있습니다.


답변

블록은 갈 길이다. 복잡한 매개 변수, 유형 안전성을 가질 수 있으며 여기에있는 대부분의 이전 답변보다 훨씬 간단하고 안전합니다. 예를 들어 다음과 같이 작성할 수 있습니다.

[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;
}

다른 예는 Michael의 대답 (+1)을 참조하십시오.