मैं Apple से iBook से गुजरा हूँ , और इसकी कोई परिभाषा नहीं पा सका हूँ:
क्या कोई इसकी संरचना समझा सकता है dispatch_after
?
dispatch_after(<#when: dispatch_time_t#>, <#queue: dispatch_queue_t?#>, <#block: dispatch_block_t?#>)
मैं Apple से iBook से गुजरा हूँ , और इसकी कोई परिभाषा नहीं पा सका हूँ:
क्या कोई इसकी संरचना समझा सकता है dispatch_after
?
dispatch_after(<#when: dispatch_time_t#>, <#queue: dispatch_queue_t?#>, <#block: dispatch_block_t?#>)
जवाबों:
संरचना का एक स्पष्ट विचार:
dispatch_after(when: dispatch_time_t, queue: dispatch_queue_t, block: dispatch_block_t?)
dispatch_time_t
एक है UInt64
। dispatch_queue_t
वास्तव में एक के लिए उपनामित प्रकार है NSObject
, लेकिन आप केवल कतारों पाने के लिए अपने परिचित GCD तरीकों का उपयोग करना चाहिए। ब्लॉक एक स्विफ्ट क्लोजर है। विशेष dispatch_block_t
रूप से () -> Void
, के रूप में परिभाषित किया गया है , जो इसके बराबर है () -> ()
।
उदाहरण उपयोग:
let delayTime = dispatch_time(DISPATCH_TIME_NOW, Int64(1 * Double(NSEC_PER_SEC)))
dispatch_after(delayTime, dispatch_get_main_queue()) {
print("test")
}
संपादित करें:
मैं @ मैट वास्तव में अच्छा delay
कार्य का उपयोग करने की सलाह देता हूं ।
संपादित करें 2:
स्विफ्ट 3 में, जीसीडी के लिए नए रैपर होंगे। यहां देखें: https://github.com/apple/swift-evolution/blob/master/proposals/0088-libdispatch-for-swift3.md
मूल उदाहरण स्विफ्ट 3 में निम्नानुसार लिखा जाएगा:
let deadlineTime = DispatchTime.now() + .seconds(1)
DispatchQueue.main.asyncAfter(deadline: deadlineTime) {
print("test")
}
ध्यान दें कि आप के deadlineTime
रूप में घोषणा लिख सकते हैं DispatchTime.now() + 1.0
और एक ही परिणाम प्राप्त कर सकते हैं क्योंकि +
ऑपरेटर निम्नानुसार (जैसे के लिए -
) ओवरराइड किया गया है :
func +(time: DispatchTime, seconds: Double) -> DispatchTime
func +(time: DispatchWalltime, interval: DispatchTimeInterval) -> DispatchWalltime
इसका मतलब है कि यदि आप उपयोग नहीं करते हैं DispatchTimeInterval
enum
और सिर्फ एक नंबर लिखते हैं, तो यह माना जाता है कि आप सेकंड का उपयोग कर रहे हैं।
dispatch_after(1, dispatch_get_main_queue()) { println("test") }
1
में dispatch_after(1, ...
यहाँ भ्रम का एक बहुत हो सकती है। लोग सोचेंगे कि यह कितने सेकंड का है, जब यह वास्तव में नैनो-सेकंड है । मेरा सुझाव है कि इस संख्या को ठीक से बनाने के तरीके पर @brindy का उत्तर देखें।
1
के लिए dispatch_time(DISPATCH_TIME_NOW, Int64(1 * Double(NSEC_PER_SEC)))
है, क्योंकि यह भ्रम होता है। लोग सोच सकते हैं कि आपको Swift
Binary operator '+' cannot be applied to operands of type DispatchTime and '_'
लाइन परlet delayTime = DispatchTime.now() + .seconds(1.0)
DispatchTime.now() + 1.0
लगता है एक ही तरीका है यह काम (कोई जरूरत नहीं करने के लिए होने के लिए .seconds
)
मैं dispatch_after
इतनी बार उपयोग करता हूं कि मैंने सिंटैक्स को सरल बनाने के लिए एक शीर्ष-स्तरीय उपयोगिता फ़ंक्शन लिखा है:
func delay(delay:Double, closure:()->()) {
dispatch_after(
dispatch_time(
DISPATCH_TIME_NOW,
Int64(delay * Double(NSEC_PER_SEC))
),
dispatch_get_main_queue(), closure)
}
और अब आप इस तरह से बात कर सकते हैं:
delay(0.4) {
// do stuff
}
वाह, एक ऐसी भाषा जहाँ आप भाषा को बेहतर बना सकते हैं। इससे अच्छा क्या हो सकता है?
लगता है कि लगभग परेशान नहीं है, अब जब उन्होंने कॉलिंग सिंटैक्स में सुधार किया है:
func delay(_ delay:Double, closure:@escaping ()->()) {
let when = DispatchTime.now() + delay
DispatchQueue.main.asyncAfter(deadline: when, execute: closure)
}
func delayInSec(delay: Double) -> dispatch_time_t { return dispatch_time(DISPATCH_TIME_NOW, Int64(delay * Double(NSEC_PER_SEC))) }
return
) जोड़ें।
1.0 ~~ { code...}
स्विफ्ट 3+
यह स्विफ्ट 3+ में सुपर-आसान और सुरुचिपूर्ण है:
DispatchQueue.main.asyncAfter(deadline: .now() + 4.5) {
// ...
}
पुराना उत्तर:
सीज़री के उत्तर पर विस्तार करने के लिए, जो 1 नैनोसेकंड के बाद निष्पादित होगा, मुझे 4 और डेढ़ सेकंड के बाद निष्पादित करने के लिए निम्नलिखित करना था।
let delay = 4.5 * Double(NSEC_PER_SEC)
let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay))
dispatch_after(time, dispatch_get_main_queue(), block)
संपादित करें: मुझे पता चला कि मेरा मूल कोड थोड़ा गलत था। यदि आप NSEC_PER_SEC को किसी डबल में नहीं डालते हैं तो अवैध टाइपिंग एक संकलित त्रुटि का कारण बनता है।
अगर कोई और अधिक इष्टतम समाधान सुझा सकता है तो मैं इसे सुनने के लिए उत्सुक हूं।
dispatch_get_current_queue()
। मैं dispatch_get_main_queue()
इसके बजाय इस्तेमाल किया।
dispatch_get_main_queue()
निश्चित रूप से वह है जो आपको उपयोग करना चाहिए। अपडेट करूंगी।
मैट का सिंटैक्स बहुत अच्छा है और यदि आपको ब्लॉक को अमान्य करने की आवश्यकता है, तो आप इसका उपयोग करना चाहते हैं:
typealias dispatch_cancelable_closure = (cancel : Bool) -> Void
func delay(time:NSTimeInterval, closure:()->Void) -> dispatch_cancelable_closure? {
func dispatch_later(clsr:()->Void) {
dispatch_after(
dispatch_time(
DISPATCH_TIME_NOW,
Int64(time * Double(NSEC_PER_SEC))
),
dispatch_get_main_queue(), clsr)
}
var closure:dispatch_block_t? = closure
var cancelableClosure:dispatch_cancelable_closure?
let delayedClosure:dispatch_cancelable_closure = { cancel in
if closure != nil {
if (cancel == false) {
dispatch_async(dispatch_get_main_queue(), closure!);
}
}
closure = nil
cancelableClosure = nil
}
cancelableClosure = delayedClosure
dispatch_later {
if let delayedClosure = cancelableClosure {
delayedClosure(cancel: false)
}
}
return cancelableClosure;
}
func cancel_delay(closure:dispatch_cancelable_closure?) {
if closure != nil {
closure!(cancel: true)
}
}
अनुसरण के रूप में उपयोग करें
let retVal = delay(2.0) {
println("Later")
}
delay(1.0) {
cancel_delay(retVal)
}
ऊपर लिंक नीचे लगता है। जीथब से मूल ओब्जेक्ट कोड
performSelector:afterDelay:
अब स्विफ्ट 2 में उपलब्ध है, इसलिए आप इसे रद्द कर सकते हैं।
dispatch_source_t
, क्योंकि वह कुछ है जिसे आप रद्द कर सकते हैं) लिखकर इसके नुकसान की भरपाई की थी ।
ऑब्जेक्टिव-सी के लिए Apple के पास एक डिस्पैच_आफ्टर स्निपेट है :
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(<#delayInSeconds#> * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
<#code to be executed after a specified delay#>
});
यहाँ स्विफ्ट 3 के लिए एक ही स्निपेट रखा गया है :
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + <#delayInSeconds#>) {
<#code to be executed after a specified delay#>
}
एक और तरीका यह है कि डबल को इस तरह बढ़ाया जाए:
extension Double {
var dispatchTime: dispatch_time_t {
get {
return dispatch_time(DISPATCH_TIME_NOW,Int64(self * Double(NSEC_PER_SEC)))
}
}
}
तो आप इसे इस तरह से उपयोग कर सकते हैं:
dispatch_after(Double(2.0).dispatchTime, dispatch_get_main_queue(), { () -> Void in
self.dismissViewControllerAnimated(true, completion: nil)
})
मुझे मैट की देरी फ़ंक्शन पसंद है, लेकिन वरीयता के बाहर मैं बल्कि पास के क्लोजर को सीमित करना चाहता हूं।
स्विफ्ट 3.0 में
डिस्पैच कतारों
DispatchQueue(label: "test").async {
//long running Background Task
for obj in 0...1000 {
print("async \(obj)")
}
// UI update in main queue
DispatchQueue.main.async(execute: {
print("UI update on main queue")
})
}
DispatchQueue(label: "m").sync {
//long running Background Task
for obj in 0...1000 {
print("sync \(obj)")
}
// UI update in main queue
DispatchQueue.main.sync(execute: {
print("UI update on main queue")
})
}
5 सेकंड के बाद डिस्पैच करें
DispatchQueue.main.after(when: DispatchTime.now() + 5) {
print("Dispatch after 5 sec")
}
स्विफ्ट 3.0 संस्करण
मुख्य थ्रेड पर देरी के बाद क्लोजर फ़ंक्शन कुछ कार्य निष्पादित करता है।
func performAfterDelay(delay : Double, onCompletion: @escaping() -> Void){
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + delay, execute: {
onCompletion()
})
}
इस समारोह की तरह कॉल करें:
performAfterDelay(delay: 4.0) {
print("test")
}
1) इस विधि को UIViewController Extension के एक भाग के रूप में जोड़ें।
extension UIViewController{
func runAfterDelay(delay: NSTimeInterval, block: dispatch_block_t) {
let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay * Double(NSEC_PER_SEC)))
dispatch_after(time, dispatch_get_main_queue(), block)
}
}
इस तरीके को वीसी पर कॉल करें:
self.runAfterDelay(5.0, block: {
//Add code to this block
print("run After Delay Success")
})
2)
performSelector("yourMethod Name", withObject: nil, afterDelay: 1)
3)
override func viewWillAppear(animated: Bool) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2), dispatch_get_main_queue(), { () -> () in
//Code Here
})
// कॉम्पैक्ट फॉर्म
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2), dispatch_get_main_queue()) {
//Code here
}
}
हालांकि ओपी द्वारा मूल प्रश्न नहीं, कुछ NSTimer
संबंधित प्रश्नों को इस प्रश्न के डुप्लिकेट के रूप में चिह्नित किया गया है, इसलिए यह NSTimer
यहां एक उत्तर सहित लायक है।
NSTimer
बनाम dispatch_after
NSTimer
अधिक उच्च स्तर है जबकि dispatch_after
अधिक निम्न स्तर है।NSTimer
रद्द करना आसान है। रद्द करने के dispatch_after
लिए अधिक कोड लिखना आवश्यक है ।NSTimer
एक NSTimer
उदाहरण बनाएँ ।
var timer = NSTimer()
टाइमर को उस देरी से शुरू करें जिसकी आपको आवश्यकता है।
// invalidate the timer if there is any chance that it could have been called before
timer.invalidate()
// delay of 2 seconds
timer = NSTimer.scheduledTimerWithTimeInterval(2.0, target: self, selector: #selector(delayedAction), userInfo: nil, repeats: false)
देरी के बाद बुलाया जाने वाला फ़ंक्शन जोड़ें ( selector
ऊपर दिए गए पैरामीटर के लिए जो भी नाम आपने उपयोग किया है)।
func delayedAction() {
print("Delayed action has now started."
}
timer.invalidate()
।repeats: true
।यदि आपके पास एक समय की घटना है जिसे रद्द करने की आवश्यकता नहीं है, तो timer
उदाहरण चर बनाने की कोई आवश्यकता नहीं है । निम्नलिखित पर्याप्त होगा:
NSTimer.scheduledTimerWithTimeInterval(2.0, target: self, selector: #selector(delayedAction), userInfo: nil, repeats: false)
मेरा फुलर जवाब यहां देखें ।
कई कार्यों के लिए इस का उपयोग करें। यह स्थिर कार्यों या किसी भी UI अपडेट के लिए एनिमेशन या गतिविधि लोडर का उपयोग करने के लिए बहुत सहायक है।
DispatchQueue.main.asyncAfter(deadline: .now() + 0.9) {
// Call your function 1
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
// Call your function 2
}
}
उदाहरण के लिए - टेबल व्यू रीलोड से पहले एक एनीमेशन का उपयोग करें। या एनीमेशन के बाद कोई अन्य यूआई अपडेट।
*// Start your amination*
self.startAnimation()
DispatchQueue.main.asyncAfter(deadline: .now() + 0.9) {
*// The animation will execute depending on the delay time*
self.stopAnimation()
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
*// Now update your view*
self.fetchData()
self.updateUI()
}
}
इसने मेरे लिए काम किया।
स्विफ्ट 3:
let time1 = 8.23
let time2 = 3.42
// Delay 2 seconds
DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
print("Sum of times: \(time1 + time2)")
}
उद्देश्य सी:
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);
});
स्विफ्ट 3 और 4:
आप DispatchQueue पर एक एक्सटेंशन बना सकते हैं और फ़ंक्शन विलंब जोड़ सकते हैं जो DispatchQueue asyncAfter का उपयोग करके आंतरिक रूप से कार्य करता है
extension DispatchQueue {
static func delay(_ delay: DispatchTimeInterval, closure: @escaping () -> ()) {
let timeInterval = DispatchTime.now() + delay
DispatchQueue.main.asyncAfter(deadline: timeInterval, execute: closure)
}
}
उपयोग:
DispatchQueue.delay(.seconds(1)) {
print("This is after delay")
}
आपके कोड में देरी के लिए एक और सहायक जो 100% स्विफ्ट उपयोग में है और वैकल्पिक रूप से आपके विलंबित कोड को चलाने के लिए एक अलग धागा चुनने की अनुमति देता है:
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
}
यदि आप एक ऐसी फ्रेमवर्क पसंद करते हैं, जिसमें कुछ अधिक उपयोगी विशेषताएं हैं तो हैंडवाइस लिफ्ट चेकआउट करें । आप इसे Carthage के माध्यम से अपनी परियोजना में जोड़ सकते हैं, फिर इसे ऊपर दिए गए उदाहरणों की तरह उपयोग कर सकते हैं, जैसे:
import HandySwift
delay(bySeconds: 1.5) {
// delayed code
}
मैं हमेशा मुफ्त कार्यों के बजाय एक्सटेंशन का उपयोग करना पसंद करता हूं।
स्विफ्ट 4
public extension DispatchQueue {
private class func delay(delay: TimeInterval, closure: @escaping () -> Void) {
let when = DispatchTime.now() + delay
DispatchQueue.main.asyncAfter(deadline: when, execute: closure)
}
class func performAction(after seconds: TimeInterval, callBack: @escaping (() -> Void) ) {
DispatchQueue.delay(delay: seconds) {
callBack()
}
}
}
अनुसरण के रूप में उपयोग करें।
DispatchQueue.performAction(after: 0.3) {
// Code Here
}
विलंबित GCD कॉल का उपयोग तेज में asyncAfter का उपयोग कर
let delayQueue = DispatchQueue(label: "com.theappmaker.in", qos: .userInitiated)
let additionalTime: DispatchTimeInterval = .seconds(2)
हम ** माइक्रोसेकंड , मिलीसेकंड , नैनोसेकंड के रूप में देरी कर सकते हैं
delayQueue.asyncAfter(deadline: .now() + 0.60) {
print(Date())
}
delayQueue.asyncAfter(deadline: .now() + additionalTime) {
print(Date())
}
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// ...
});
dispatch_after(_:_:_:)
समारोह तीन पैरामीटर लेता है:
एक
प्रेषण एक देरी एक
ब्लॉक या बंद कतार
dispatch_after(_:_:_:)
समारोह ब्लॉक या प्रेषण कतार है कि किसी भी देरी के बाद समारोह को पारित कर दिया है पर बंद का आह्वान। ध्यान दें कि dispatch_time(_:_:)
फ़ंक्शन का उपयोग करके देरी बनाई गई है । इसे याद रखें क्योंकि हम स्विफ्ट में भी इस फ़ंक्शन का उपयोग करते हैं।
मैं ट्यूटोरियल रेवेंडरलिच डिस्पैच ट्यूटोरियल के माध्यम से जाने की सलाह देता हूं
स्विफ्ट 5 में, नीचे में उपयोग करें:
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2, execute: closure)
// time gap, specify unit is second
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(2)) {
Singleton.shared().printDate()
}
// default time gap is second, you can reduce it
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
// just do it!
}
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")
})
स्विफ्ट 3.0 संस्करण
मुख्य थ्रेड पर देरी के बाद क्लोजर फ़ंक्शन कुछ कार्य निष्पादित करता है।
func performAfterDelay(delay : Double, onCompletion: @escaping() -> Void){
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + delay, execute: {
onCompletion()
})
}
इस समारोह की तरह कॉल करें:
performAfterDelay(delay: 4.0) {
print("test")
}
अब स्विफ्ट में ग्रैंड सेंट्रल डिस्पैच (जीसीडी) में एसिंक्रोनस डिस्पैच के लिए सिंटैक्टिक शुगर से अधिक है।
पॉडफाइल जोड़ें
pod 'AsyncSwift'
फिर, आप इसे इस तरह से उपयोग कर सकते हैं।
let seconds = 3.0
Async.main(after: seconds) {
print("Is called after 3 seconds")
}.background(after: 6.0) {
print("At least 3.0 seconds after previous block, and 6.0 after Async code is called")
}
स्विफ्ट 4 में ऐसा करने का एक छोटा तरीका है:
Timer.scheduledTimer(withTimeInterval: 2, repeats: false) { (timer) in
// Your stuff here
print("hello")
}
यहाँ स्विफ्ट में asyncAfter का तुल्यकालिक संस्करण है:
let deadline = DispatchTime.now() + .seconds(3)
let semaphore = DispatchSemaphore.init(value: 0)
DispatchQueue.global().asyncAfter(deadline: deadline) {
dispatchPrecondition(condition: .onQueue(DispatchQueue.global()))
semaphore.signal()
}
semaphore.wait()
अतुल्यकालिक एक के साथ:
let deadline = DispatchTime.now() + .seconds(3)
DispatchQueue.main.asyncAfter(deadline: deadline) {
dispatchPrecondition(condition: .onQueue(DispatchQueue.global()))
}