programing

-performSelector:withObject:afterDelay:와 같이 지연 후에 블록을 트리거하려면 어떻게 해야 합니까?

javajsp 2023. 4. 9. 20:59

-performSelector:withObject:afterDelay:와 같이 지연 후에 블록을 트리거하려면 어떻게 해야 합니까?

?를 들어, "Delay"를 사용합니다.performSelector:withObject:afterDelay: '아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아,int/double/float

것 같은데요dispatch_after()이 파라미터를 할 수 할 수 있습니다 블록이 파라미터를 받아들이지 않아도 되지만 블록이 로컬스코프에서 이러한 변수를 캡처할 수 있도록 할 수 있습니다.

int parameter1 = 12;
float parameter2 = 144.1;

// Delay execution of my block for 10 seconds.
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 10 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
    NSLog(@"parameter1: %d parameter2: %f", parameter1, parameter2);
});

상세: https://developer.apple.com/documentation/dispatch/1452876-dispatch_after

하시면 됩니다.dispatch_after★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★에 Xcode 라고 합니다.dispatch_afterEnter하다

여기에 이미지 설명 입력

여기 두 개의 플로트를 "인수"로 하는 예가 있습니다.어떤 종류의 매크로에도 의존할 필요가 없으며, 코드의 의도는 매우 명확합니다.

스위프트 3, 스위프트 4

let time1 = 8.23
let time2 = 3.42

// Delay 2 seconds
DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
    print("Sum of times: \(time1 + time2)")
}

스위프트 2

let time1 = 8.23
let time2 = 3.42

// Delay 2 seconds
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(2.0 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) { () -> Void in
        println("Sum of times: \(time1 + time2)")
}

목표 C

CGFloat time1 = 3.49;
CGFloat time2 = 8.13;

// Delay 2 seconds
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    CGFloat newTime = time1 + time2;
    NSLog(@"New time: %f", newTime);
});

Xcode 내장 코드 스니펫 라이브러리를 사용하는 것은 어떻습니까?

여기에 이미지 설명 입력

Swift 업데이트:

많은 찬성표가 이 답변을 업데이트하도록 영감을 주었습니다.

코드 에는 Xcode가 .dispatch_after을을 에 한해서objective-c언어.또, 다음의 커스텀 코드 스니펫을 작성할 수도 있습니다.Swift.

이것을 X코드로 써라.

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(<#delayInSeconds#> * Double(NSEC_PER_SEC))), dispatch_get_main_queue(), {
        <#code to be executed after a specified delay#>
    })

이 코드를 끌어 코드 조각 라이브러리 영역에 놓습니다.여기에 이미지 설명 입력

맨 아래에 .My Code Snippet. 제목으로 편집합니다.Xcode 를 입력할 때 힌트를 얻으려면 , 를 입력합니다.

자세한 내용은 CreatingaCodeSnippet을 참조하십시오.

업데이트 Swift 3

이 코드를 끌어 코드 조각 라이브러리 영역에 놓습니다.

DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(<#delayInSeconds#>)) {
    <#code to be executed after a specified delay#>
}

Jaime Cham은 NSObject+Blocks를 사용합니다.는 이 의 방법들과 더 잘 .performSelector: 메서드 NSObject

NSObject+Blocks.h

#import <Foundation/Foundation.h>

@interface NSObject (Blocks)

- (void)performBlock:(void (^)())block afterDelay:(NSTimeInterval)delay;

@end

NSObject+Blocks.m

#import "NSObject+Blocks.h"

@implementation NSObject (Blocks)

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

- (void)performBlock:(void (^)())block afterDelay:(NSTimeInterval)delay
{
    void (^block_)() = [block copy]; // autorelease this if you're not using ARC
    [self performSelector:@selector(performBlock:) withObject:block_ afterDelay:delay];
}

@end

다음과 같이 사용합니다.

[anyObject performBlock:^{
    [anotherObject doYourThings:stuff];
} afterDelay:0.15];

아마도 GCD를 통과하는 것보다 더 간단할 것입니다. 클래스 어딘가에서(예: "Util") 또는 오브젝트에 대한 범주:

+ (void)runBlock:(void (^)())block
{
    block();
}
+ (void)runAfterDelay:(CGFloat)delay block:(void (^)())block 
{
    void (^block_)() = [[block copy] autorelease];
    [self performSelector:@selector(runBlock:) withObject:block_ afterDelay:delay];
}

사용 방법:

[Util runAfterDelay:2 block:^{
    NSLog(@"two seconds later!");
}];

Swift를 기능을 .dispatch_after가 읽기 쉽고 사용하기 때문에 더 마음에 .읽기 쉽고 사용하기 쉽기 때문에 더 마음에 듭니다.

func performBlock(block:() -> Void, afterDelay delay:NSTimeInterval){
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(delay * Double(NSEC_PER_SEC))), dispatch_get_main_queue(), block)
}

다음과 같이 사용할 수 있습니다.

performBlock({ () -> Void in
    // Perform actions
}, afterDelay: 0.3)

여기 2센트 = 5가지 방법이 있습니다.)

나는 이러한 세부사항을 캡슐화하는 것을 좋아하고 AppCode가 내 문장을 어떻게 끝내는지 알려주길 원한다.

void dispatch_after_delay(float delayInSeconds, dispatch_queue_t queue, dispatch_block_t block) {
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
    dispatch_after(popTime, queue, block);
}

void dispatch_after_delay_on_main_queue(float delayInSeconds, dispatch_block_t block) {
    dispatch_queue_t queue = dispatch_get_main_queue();
    dispatch_after_delay(delayInSeconds, queue, block);
}

void dispatch_async_on_high_priority_queue(dispatch_block_t block) {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), block);
}

void dispatch_async_on_background_queue(dispatch_block_t block) {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), block);
}

void dispatch_async_on_main_queue(dispatch_block_t block) {
    dispatch_async(dispatch_get_main_queue(), block);
}

Perform Selector(퍼포먼스 셀렉터WithObject는 항상 객체를 취하기 때문에 int/double/float 등의 인수를 전달하기 위해...이런 거 써도 돼요.

//NS Number는 객체입니다.

[self performSelector:@selector(setUserAlphaNumber:)
     withObject: [NSNumber numberWithFloat: 1.0f]       
     afterDelay:1.5];



-(void) setUserAlphaNumber: (NSNumber*) number{

     [txtUsername setAlpha: [number floatValue] ];

}

[NS Number number ]를 사용하는 방법과 동일합니다.Int:] etc....를 사용하여 수신 방법에서는 숫자를 [number int] 또는 [number double] 형식으로 변환할 수 있습니다.

dispatch_after 함수는 블록오브젝트를 일정시간 경과 후 디스패치큐에 디스패치합니다.2.0초 후에 몇 가지 UI 관련 작업을 수행하려면 다음 코드를 사용합니다.

            let delay = 2.0
            let delayInNanoSeconds = dispatch_time(DISPATCH_TIME_NOW, Int64(delay * Double(NSEC_PER_SEC)))
            let mainQueue = dispatch_get_main_queue()

            dispatch_after(delayInNanoSeconds, mainQueue, {

                print("Some UI related task after delay")
            })

swift 3.0의 경우:

            let dispatchTime: DispatchTime = DispatchTime.now() + Double(Int64(2.0 * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)
            DispatchQueue.main.asyncAfter(deadline: dispatchTime, execute: {

          })

Xcode 10.2 및 Swift 5 이상

DispatchQueue.main.asyncAfter(deadline: .now() + 2, execute: {
   // code to execute                 
})

ObjC 버전

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
    //code to execute
});

지연 후 작업을 대기열에 넣는 Swift 3가지 방법이 있습니다.

DispatchQueue.main.asyncAfter(
  DispatchTime.now() + DispatchTimeInterval.seconds(2)) {
    // do work
}

귀찮은 GCD 콜을 몇 번이고 반복하는 것을 막기 위한 편리한 도우미가 있습니다.

public func delay(bySeconds seconds: Double, dispatchLevel: DispatchLevel = .main, closure: @escaping () -> Void) {
    let dispatchTime = DispatchTime.now() + seconds
    dispatchLevel.dispatchQueue.asyncAfter(deadline: dispatchTime, execute: closure)
}

public enum DispatchLevel {
    case main, userInteractive, userInitiated, utility, background
    var dispatchQueue: DispatchQueue {
        switch self {
        case .main:                 return DispatchQueue.main
        case .userInteractive:      return DispatchQueue.global(qos: .userInteractive)
        case .userInitiated:        return DispatchQueue.global(qos: .userInitiated)
        case .utility:              return DispatchQueue.global(qos: .utility)
        case .background:           return DispatchQueue.global(qos: .background)
        }
    }
}

이제 메인 스레드에서 코드를 다음과 같이 지연시킵니다.

delay(bySeconds: 1.5) { 
    // delayed code
}

코드를 다른 스레드로 지연시키는 경우:

delay(bySeconds: 1.5, dispatchLevel: .background) { 
    // delayed code that will run on background thread
}

보다 편리한 기능을 갖춘 프레임워크를 원하신다면 HandySwift를 확인해 보십시오.카르타고를 통해 프로젝트에 추가한 후 위의 예시와 동일하게 사용할 수 있습니다.

import HandySwift    

delay(bySeconds: 1.5) { 
    // delayed code
}

Cmd + Shift + L을 눌러 Xcode 내장 코드 스니펫 라이브러리를 표시합니다.

여기에 이미지 설명 입력

디스패치를 검색한 후 코드로 드래그 앤 드롭하면 됩니다.

BlocksKit 프레임워크에는 멋진 것이 있습니다.

블록 키트

(및 클래스)

BBlocksKit.m

swift 3에서는 Dispatch Queue.main.async After 함수를 사용하여 'n'초 지연 후 기능 또는 액션을 트리거할 수 있습니다.여기 코드에서는 1초 후에 지연을 설정했습니다.이 함수의 본문 내부에 있는 함수를 호출하면 1초 지연 후 트리거됩니다.

let when = DispatchTime.now() + 1
DispatchQueue.main.asyncAfter(deadline: when) {

    // Trigger the function/action after the delay of 1Sec

}

122021 4월4 x Xcode 12.4 데 x x로 . 방법은 유효하지만, 않습니다.+버튼은 보기 라이브러리 및 수정자 라이브러리(아래 참조)를 포함하여 더 많은 아이콘을 표시하며, 보기가 기본일 수 있습니다.보기 및 수정자 라이브러리 아이콘 포함 따라서 아래 그림과 같이 스니펫 라이브러리를 선택하십시오.


(2020년 6월 Xcode 11.3.1에서 확인)

Xcode는 이를 위한 코드 스니펫을 제공합니다.지연값과 지연 후 실행할 코드를 입력하기만 하면 됩니다.

  1. 합니다.+오른쪽 (를 들어 의 다른 일부 (Project Navigator에서) (Project Navigator와 같은 다른 라이브러리가 표시되는 경우
  2. 사용 가능한 아이콘 중에서 스니펫 라이브러리(스크린샷, { }이(가) 있는 아이콘 참조)가 선택되었는지 확인합니다.
  3. 을 찾다after
  4. 검색 결과는 원하는 스니펫인 1개만 반환됩니다(스크린샷 참조).두 번 클릭하면 준비가 완료됩니다.

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

인수를 자체 클래스로 랩하거나 메서드 호출을 원시 유형으로 전달할 필요가 없는 메서드로 랩할 수 있습니다.그런 다음 지연 후 해당 메서드를 호출하고 해당 메서드 내에서 수행할 셀렉터를 수행합니다.

다음은 Swift에서 지연된 후 블록을 트리거하는 방법입니다.

runThisAfterDelay(seconds: 2) { () -> () in
    print("Prints this 2 seconds later in main queue")
}

/// EZSwiftExtensions
func runThisAfterDelay(seconds seconds: Double, after: () -> ()) {
    let time = dispatch_time(DISPATCH_TIME_NOW, Int64(seconds * Double(NSEC_PER_SEC)))
    dispatch_after(time, dispatch_get_main_queue(), after)
}

리포트에 표준 기능으로 포함되어 있습니다.

Swift 3 및 X코드 8.3.2

이 코드가 도움이 될 것입니다. 설명도 덧붙입니다.

// Create custom class, this will make your life easier
class CustomDelay {

    static let cd = CustomDelay()

    // This is your custom delay function
    func runAfterDelay(_ delay:Double, closure:@escaping ()->()) {
        let when = DispatchTime.now() + delay
        DispatchQueue.main.asyncAfter(deadline: when, execute: closure)
    }
}


// here how to use it (Example 1)
class YourViewController: UIViewController {

    // example delay time 2 second
    let delayTime = 2.0

    override func viewDidLoad() {
        super.viewDidLoad()

        CustomDelay.cd.runAfterDelay(delayTime) {
            // This func will run after 2 second
            // Update your UI here, u don't need to worry to bring this to the main thread because your CustomDelay already make this to main thread automatically :)
            self.runFunc()
        }
    }

    // example function 1
    func runFunc() {
        // do your method 1 here
    }
}

// here how to use it (Example 2)
class YourSecondViewController: UIViewController {

    // let say you want to user run function shoot after 3 second they tap a button

    // Create a button (This is programatically, you can create with storyboard too)
    let shootButton: UIButton = {
        let button = UIButton(type: .system)
        button.frame = CGRect(x: 15, y: 15, width: 40, height: 40) // Customize where do you want to put your button inside your ui
        button.setTitle("Shoot", for: .normal)
        button.translatesAutoresizingMaskIntoConstraints = false
        return button
    }()

    override func viewDidLoad() {
        super.viewDidLoad()

        // create an action selector when user tap shoot button
        shootButton.addTarget(self, action: #selector(shoot), for: .touchUpInside)   
    }

    // example shoot function
    func shoot() {
        // example delay time 3 second then shoot
        let delayTime = 3.0

        // delay a shoot after 3 second
        CustomDelay.cd.runAfterDelay(delayTime) {
            // your shoot method here
            // Update your UI here, u don't need to worry to bring this to the main thread because your CustomDelay already make this to main thread automatically :)
        }
    }   
}

필자는 어떻게 분수 시간을 기다리는가(지연)가 아니라 어떻게 스칼라를 셀렉터의 인수(withObject:)로 전달하는지 묻고 있으며, 현대 목표 C에서 가장 빠른 방법은 다음과 같습니다.

[obj performSelector:...  withObject:@(0.123123123) afterDelay:10]

셀렉터는 파라미터를 NSNumber로 변경하고 floatValue 또는 doubleValue와 같은 셀렉터를 사용하여 값을 취득해야 합니다.

언급URL : https://stackoverflow.com/questions/4139219/how-do-you-trigger-a-block-after-a-delay-like-performselectorwithobjectafter