Swift에서 x 분마다 작업 수행


113

매분 함수를 어떻게 실행할 수 있습니까? JavaScript에서 같은 setInterval일을 할 수 있습니다. Swift에 비슷한 것이 있습니까?

원하는 출력 :

1 분에 한 번씩 Hello World ...


Swift 2 : Swift Timer
JamesG

답변:


171
var helloWorldTimer = NSTimer.scheduledTimerWithTimeInterval(60.0, target: self, selector: Selector("sayHello"), userInfo: nil, repeats: true)

func sayHello() 
{
    NSLog("hello World")
}

Foundation을 가져 오는 것을 잊지 마십시오.

스위프트 4 :

 var helloWorldTimer = Timer.scheduledTimer(timeInterval: 60.0, target: self, selector: #selector(ViewController.sayHello), userInfo: nil, repeats: true)

 @objc func sayHello() 
 {
     NSLog("hello World")
 }

1
하지만보기간에 전환하려면 어떻게해야합니까? 코드가 멈출까요?
Cing

5
@Cing은 자기 참조가 무엇인지에 따라 다릅니다.
Antzi

1
NSTimer목표 를 유지한다는 것을 잊지 마십시오. 따라서이 설정을 사용하면 helloWorldTimer속성 selfself유지 helloWorldTimer되고 helloWorldTimer유지 되는 유지주기가 생깁니다 self.
MANIAK_dobrii

@MANIAK_dobrii 유지주기를 끊는 방법에 대해서도 언급 할 수 있습니까? VC가 해제되었지만 타이머가 취소되지 않은 경우 사이클은 여전히 ​​똑같습니까? 그렇다면 타이머를 취소 한 다음보기를 닫아주기를 중단해야합니까?
Dave G

1
Swift 4의 경우 선택기를 가져 오려는 메소드는 Objective-C에 노출되어야하므로 @objc 속성을 메소드 선언에 추가해야합니다. 예를 들어```@objc FUNC의 sayHello () {}```
인 Shamim의 Hossain

136

iOS 버전 10 이상을 대상으로하는 경우 Timer잠재적 인 강력한 참조주기를 단순화하는 의 블록 기반 변환을 사용할 수 있습니다. 예 :

weak var timer: Timer?

func startTimer() {
    timer?.invalidate()   // just in case you had existing `Timer`, `invalidate` it before we lose our reference to it
    timer = Timer.scheduledTimer(withTimeInterval: 60.0, repeats: true) { [weak self] _ in
        // do something here
    }
}

func stopTimer() {
    timer?.invalidate()
}

// if appropriate, make sure to stop your timer in `deinit`

deinit {
    stopTimer()
}

하지만 Timer완전성을 위해서, 일반적으로 최고입니다, 당신은 또한 배경 스레드에 예약 타이머에 유용 파견 타이머를 사용할 수 있음을 유의하십시오. 파견 타이머로,있는 거 블록 기반, 그것은 이전과 강한 참조주기 문제의 일부 방지 그들은 이후 target/의 selector패턴을 Timer오래 사용으로, weak참조.

그래서:

var timer: DispatchSourceTimer?

func startTimer() {
    let queue = DispatchQueue(label: "com.domain.app.timer")  // you can also use `DispatchQueue.main`, if you want
    timer = DispatchSource.makeTimerSource(queue: queue)
    timer!.schedule(deadline: .now(), repeating: .seconds(60))
    timer!.setEventHandler { [weak self] in
        // do whatever you want here
    }
    timer!.resume()
}

func stopTimer() {
    timer?.cancel()
    timer = nil
}

deinit {
    self.stopTimer()
}

자세한 내용 은 Concurrency Programming GuideDispatch Sources 섹션에있는 Dispatch Source ExamplesCreating a Timer 섹션을 참조하십시오.


Swift 2 의 경우이 답변의 이전 개정판을 참조하십시오 .


이 접근 방식 내에서 한 번만 실행되는 타이머를 어떻게 사용 하시겠습니까?
Juan Boero

@JuanPabloBoero-한 번의 화재 상황에서는이 접근 방식을 사용하지 않습니다. 당신은 dispatch_after. 또는 반복되지 않는 NSTimer.
Rob

@Rob 기능에서 매초마다 업데이트되는 카운터 레이블이 화면에 있으며 위의 코드를 사용하여 카운터를 늘리고 레이블 텍스트를 업데이트하고 있습니다. 그러나 내가 직면 한 문제는 내 카운터 변수가 매초 업데이트되지만 화면에 내 UILabel에 최신 카운터 값이 표시되지 않는다는 것입니다.
Nagendra Rao

Rao, 위의 내용은 백그라운드 스레드에서 일부 작업을 수행하는 데 유용합니다. 그러나 UI 업데이트는 기본 대기열에서 발생해야합니다. 따라서 메인 스레드에서이를 예약하거나 최소한 UI 업데이트를 메인 스레드로 다시 전달합니다.

1
이 질문은이 답변에 대한 의견에 여기에 속하지 않습니다. 위의 댓글을 삭제하고 질문을 게시하세요. 그러나 간단히 말해서 일반적으로 앱을 실제로 백그라운드에서 실행하지 않고 그대로 보이도록 만듭니다. stackoverflow.com/a/31642036/1271826을 참조하십시오 .
Rob

17

다음 은 명명 된 함수가 아닌 클로저를 사용하는 NSTimerSwift 3 ( NSTimer으로 이름이 변경됨 Timer) 에 대한 답변에 대한 업데이트입니다 .

var timer = Timer.scheduledTimer(withTimeInterval: 60, repeats: true) {
    (_) in
    print("Hello world")
}

6
iOS 10 전용입니다.
Glenn

하지 후 IOS 10 + 솔루션을 해 주시기 바랍니다
누만 Karaaslan

13

약간의 시간 드리프트를 허용 할 수 있다면 매분 코드를 실행하는 간단한 솔루션이 있습니다.

private func executeRepeatedly() {
    // put your code here

    DispatchQueue.main.asyncAfter(deadline: .now() + 60.0) { [weak self] in
        self?.executeRepeatedly()
    }
}

executeRepeatedly()한 번만 실행 하면 1 분마다 실행됩니다. 소유 개체 ( self)가 해제 되면 실행이 중지됩니다 . 플래그를 사용하여 실행을 중지해야 함을 나타낼 수도 있습니다.


이 결정은 모든 타이머를 사용하여 runloops에 추가하고 무효화하는 것보다 훨씬 편리합니다.
julia_v 2011

이것은 유효한 해결책으로 보이지만 웹 서비스 호출과 함께 사용할 때 유지주기를 생성하고 있습니다.
jayant rawat

11

사용할 수 있습니다 Timer(스위프트 3)

var timer = Timer.scheduledTimerWithTimeInterval(60, target: self, selector: Selector("function"), userInfo: nil, repeats: true)

selector ()에서 함수 이름을 입력합니다.


스위프트 3에서 어떻게 할 수 있습니까?
bibscy

1
사용은 Timer... NSTimer이름이 변경되었습니다
조셉

7

신속한 3.0에서 GCD는 리팩토링되었습니다.

let timer : DispatchSourceTimer = DispatchSource.makeTimerSource(flags: [], queue: DispatchQueue.main)

timer.scheduleRepeating(deadline: .now(), interval: .seconds(60))
timer.setEventHandler
{
    NSLog("Hello World")
}
timer.resume()

이것은 특정 큐를 디스패치해야 할 때 특히 유용합니다. 또한 사용자 인터페이스 업데이트에 이것을 사용할 계획이라면 CADisplayLinkGPU 새로 고침 빈도와 동기화되어 있는지 살펴 보는 것이 좋습니다 .

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