[objective-c] 다음 두 줄 실행 사이에 지연 추가

(동일한) 함수에서 두 줄의 실행 사이에 지연을 추가해야합니다. 이를 수행하는 데 유리한 옵션이 있습니까?

참고 : 이를 위해 두 가지 다른 함수가 필요하지 않으며 지연이 다른 함수의 실행에 영향을주지 않아야합니다.

예 :

line 1: [executing first operation];

line 2: Delay                        /* I need to introduce delay here */

line 3: [executing second operation];

어떤 도움이라도 감사합니다. 미리 감사드립니다 …



답변

다른 방법을 만들지 않고도 gcd를 사용하여이 작업을 수행 할 수 있습니다.

double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
  NSLog(@"Do some work");
});

코드를 복잡하게 만들고 경쟁 조건을 유발할 수 있으므로 “정말 지연을 추가해야합니까?”라고 자문해야합니다.


답변

다음 NSThread방법을 사용할 수 있습니다 .

[NSThread sleepForTimeInterval: delay];

그러나 메인 스레드에서이 작업을 수행하면 앱이 차단되므로 백그라운드 스레드에서만 수행하십시오.


또는 Swift에서

NSThread.sleepForTimeInterval(delay)

Swift 3에서

Thread.sleep(forTimeInterval: delay)


답변

이 행은 3 초 후에 선택기 secondMethod를 호출합니다.

[self performSelector:@selector(secondMethod) withObject:nil afterDelay:3.0 ];

원하는 지연으로 두 번째 작업에 사용하십시오. 코드가 많은 경우 자체 메서드에 배치하고 performSelector:. UI를 차단하지 않습니다.sleep

편집 : 두 번째 방법을 원하지 않는 경우 performSelector에서 블록을 사용할 수 있도록 카테고리를 추가 할 수 있습니다.

@implementation NSObject (PerformBlockAfterDelay)

- (void)performBlock:(void (^)(void))block
          afterDelay:(NSTimeInterval)delay
{
    block = [block copy];
    [self performSelector:@selector(fireBlockAfterDelay:)
               withObject:block
               afterDelay:delay];
}

- (void)fireBlockAfterDelay:(void (^)(void))block
{
    block();
}

@end

또는 더 깔끔하게 :

void RunBlockAfterDelay(NSTimeInterval delay, void (^block)(void))
{
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC*delay),
      dispatch_get_current_queue(), block);
}


답변

나는 차례를 시작하기 전에 (그리고 차례의 단계 사이) AI가 일시 중지 해야하는 몇 가지 턴 기반 게임을 가지고 있습니다. 지연이 최선의 해결책 인 다른 더 유용한 상황이 있다고 확신합니다. Swift에서 :

        let delay = 2.0 * Double(NSEC_PER_SEC)
        let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay))
        dispatch_after(time, dispatch_get_main_queue()) { self.playerTapped(aiPlayView) }

Objective-C 호출이 다른지 확인하기 위해 방금 여기로 돌아 왔습니다 (저도 이것도 추가해야합니다).


답변

iOS 4.0 이상을 대상으로하는 경우 다음을 수행 할 수 있습니다.

[executing first operation];
double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
    [executing second operation];
});


답변

[2020 년 11 월 27 일 확인 및 Xcode 12.1에서 여전히 정확한 것으로 확인 됨]

요즘 가장 편리한 방법 : Xcode는 지연 값과 지연 후 실행할 코드를 입력하기 만하면되는 코드 스 니펫을 제공합니다.

  1. +Xcode의 오른쪽 상단 에있는 버튼을 클릭하십시오 .
  2. 검색하다 after
  3. 원하는 스 니펫 인 1 개의 검색 결과 만 반환합니다 (스크린 샷 참조). 두 번 클릭하면 갈 수 있습니다.

Xcode 자체에서 스 니펫을 가져 오는 방법을 보여주는 스크린 샷


답변

@Sunkas가 쓴 것처럼, 그것이 더 짧고 정상적인 구문 을 가지고 있다는 것만으로 performSelector:withObject:afterDelay:펜던트 입니다. 지연하려는 블록에 인수를 전달해야하는 경우 매개 변수를 통해 전달하기 만하면 호출 에서 인수 를받을 수 있습니다.dispatch_afterobjective-cwithObjectselector

[self performSelector:@selector(testStringMethod:)
           withObject:@"Test Test"
           afterDelay:0.5];

- (void)testStringMethod:(NSString *)string{
    NSLog(@"string  >>> %@", string);
}

메인 스레드 또는 현재 스레드에서 실행하는 경우 여전히 자신을 선택하고 싶다면이를 지정할 수있는 특정 메서드가 있습니다. Apples Documentation은 다음과 같이 말합니다.

실행 루프가 기본 모드가 아닌 모드에있을 때 메시지를 대기열에서 빼려면 performSelector : withObject : afterDelay : inModes : 메서드를 대신 사용하세요. 현재 스레드가 기본 스레드인지 확실하지 않은 경우 performSelectorOnMainThread : withObject : waitUntilDone : 또는 performSelectorOnMainThread : withObject : waitUntilDone : modes : 메소드를 사용하여 선택기가 기본 스레드에서 실행되도록 할 수 있습니다. 대기중인 메시지를 취소하려면 cancelPreviousPerformRequestsWithTarget : 또는 cancelPreviousPerformRequestsWithTarget : selector : object : 메소드를 사용하십시오.