다음 두 줄 실행 사이에 지연 추가


81

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

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

예 :

line 1: [executing first operation];

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

line 3: [executing second operation];

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

답변:


215

다른 방법을 만들지 않고도 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");
});

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


2
사람들에게 이것에 대해 경고하는 것이 옳지 만 고정 된 처리 시간으로 외부 장치를 기다려야하는 컨트롤러를 코딩하는 것은 말도 안됩니다.
user2161301

3
검색 창에 쓰는 동안 HTTP 요청을 지연시키는 것은 어떻습니까? 입력하는 동안 결과를 필터링 하시겠습니까? 사용자가 탭하는 모든 키에 대해 서버에 쿼리하는 대신 필터링 된 목록을 요청하기 전에 1 초를 기다리는 것은 나에게 말도 안되는 소리처럼 들리지 않습니다.
Alejandro Iván

26

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

[NSThread sleepForTimeInterval: delay];

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


또는 Swift에서

NSThread.sleepForTimeInterval(delay)

Swift 3에서

Thread.sleep(forTimeInterval: delay)

2
나는 이것이 질문의 요구 사항에 따라 받아 들여진 대답이어야한다고 생각합니다.
ACLima 2016-04-05

1
@ACLima : 죄송합니다. 'sleepForTimeInterval'은 주어진 시간 간격 동안 스레드를 휴면하므로 다른 동시 함수 실행에 영향을 미칠 수 있습니다.
Krishna Raj Salim

두 번째 또는 monute?
시바

20

이 행은 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);
}

6
OP는 두 번째 방법을 원하지 않는다고 명시 적으로 명시합니다. S
Paul.s

그는 함께 블록을 사용할 수 있도록 카테고리를 추가 할 수 있습니다 performSelector: stackoverflow.com/questions/4007023/...
Sunkas

@ Sunkas : 답변 주셔서 감사합니다. 그러나 두 번째 기능을 추가하고 싶지 않다고 이미 언급했습니다.
Krishna Raj Salim

3
그 대답을 사용하면 두 번째 방법없이 지연 후 코드를 실행하는 아주 깨끗한 방법을 얻을 수 있습니다. [self performBlock:^{ your_code } afterDelay:0.1];
Sunkas 2014 년

4
OP가 다른 방법을 추가하지 않으려는 경우 이유를 설명해야합니다. 이는 작동하도록 설계된 도구를 사용하는 매우 좋은 방법이기 때문입니다. 방법이 나쁜가요? 그들은 (무효)로 지불하고 있습니까?
tooluser 2014 년

8

나는 차례를 시작하기 전에 (그리고 차례의 단계 사이) 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 호출이 다른지 확인하기 위해 방금 여기로 돌아 왔습니다 (저도 이것도 추가해야합니다).


4

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


4

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

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

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

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


1

@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 : 메소드를 사용하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.