কীভাবে সুইফটে বিলম্ব তৈরি করবেন?


262

আমি আমার অ্যাপটিকে একটি নির্দিষ্ট পয়েন্টে থামাতে চাই। অন্য কথায়, আমি চাই আমার অ্যাপটি কোডটি কার্যকর করুক, তবে তারপরে একটি নির্দিষ্ট সময়ে 4 সেকেন্ডের জন্য বিরতি দিন এবং তারপরে বাকী কোডটি দিয়ে চালিয়ে যান। কিভাবে আমি এটি করতে পারব?

আমি সুইফট ব্যবহার করছি।


উত্তর:


270

ঘুমের পরিবর্তে, যা ইউআই থ্রেড থেকে ফোন করা হলে আপনার প্রোগ্রামটি লক হয়ে যায়, ব্যবহার বিবেচনা করুন NSTimer বা প্রেরণের টাইমার বিবেচনা করুন।

তবে, যদি আপনার বর্তমান থ্রেডে সত্যই বিলম্ব হয়:

do {
    sleep(4)
}

এটি sleepইউনিক্স থেকে ফাংশনটি ব্যবহার করে ।


4
ডারউইন আমদানি না করে ঘুম কাজ করে, নিশ্চিত এটি নিশ্চিত না যে এটি পরিবর্তন কিনা
ড্যান বিউলিউ

17
ইউএসপ ()ও কাজ করে, আপনার যদি আরও 1 সেকেন্ড রেজোলিউশনের আরও কিছু সুনির্দিষ্ট প্রয়োজন হয়।
প্রিভিট

18
ইউএসএল () এক সেকেন্ডের মিলিয়নতম সময় নেয় তাই ইউএসপ (1000000) 1 সেকেন্ডের জন্য ঘুমাবে
হ্যারিস

40
"এই কাজটি করবেন না" উপস্থাপনাটি সংক্ষিপ্ত রাখার জন্য ধন্যবাদ।
ড্যান রোজনস্টার্ক

2
দীর্ঘ-চলমান ব্যাকগ্রাউন্ড প্রক্রিয়াগুলি অনুকরণ করতে আমি ঘুম () ব্যবহার করি।
উইলিয়াম টি। ম্যালার্ড

345

dispatch_afterব্লক ব্যবহার করা বেশিরভাগ ক্ষেত্রে sleep(time)থ্রেড হিসাবে ঘুম করা হয় সে হিসাবে ব্যবহার করা আরও ভাল হয় অন্য কাজ করা থেকে বিরত থাকে। dispatch_afterযে থ্রেডটিতে কাজ করা হয় তা ব্যবহার করার সময় অবরুদ্ধ হয়ে যায় না তাই এর মধ্যে এটি অন্য কাজ করতে পারে।
আপনি যদি আপনার অ্যাপ্লিকেশনের মূল থ্রেডে কাজ করছেন তবে আপনার অ্যাপ্লিকেশনটির sleep(time)ব্যবহারকারীর অভিজ্ঞতার জন্য ব্যবহার করা খারাপ কারণ ইউআই সেই সময় প্রতিক্রিয়াহীন।

থ্রেড হিমায়িত করার পরিবর্তে কোডের ব্লক কার্যকর করার সময়সূচির পরে প্রেরণ:

সুইফট ≥ 3.0

let seconds = 4.0
DispatchQueue.main.asyncAfter(deadline: .now() + seconds) {
    // Put your code which should be executed with a delay here
}

সুইফট <3.0

let time = dispatch_time(dispatch_time_t(DISPATCH_TIME_NOW), 4 * Int64(NSEC_PER_SEC))
dispatch_after(time, dispatch_get_main_queue()) {
    // Put your code which should be executed with a delay here
}

1
পর্যায়ক্রমিক ক্রিয়া সম্পর্কে কি?
কিয়েড

1
পর্যায়ক্রমে কাজের জন্য জিসিডি ব্যবহারের সম্ভাবনা রয়েছে যা আপেল বিকাশকারী ডকুমেন্টেশন থেকে এই নিবন্ধে বর্ণিত হয়েছে তবে আমি তার জন্য একটি এনএসটিমিকার ব্যবহার করার পরামর্শ দেব। এই উত্তরটি দ্রুতগতিতে ঠিক কীভাবে করা যায় তা দেখায়।
পলে

2
কোড এক্সকোড 8.2.1 এর জন্য আপডেট হয়েছে। পূর্বে .now() + .seconds(4)ত্রুটি দেয়:expression type is ambiguous without more context
রিচার্ডস

কীভাবে আমি সারি থেকে আহবান করা অনুষ্ঠানটি স্থগিত করতে পারি? @ প্যালে
মুকুল আরও

14
আপনার আর .now() + .seconds(5)এটি সহজভাবে যুক্ত করার দরকার নেই.now() + 5
cnzac

45

দ্রুততম 3.0 এ বিভিন্ন পদ্ধতির মধ্যে তুলনা

1. ঘুম

এই পদ্ধতির কোনও কল ফিরে নেই। 4 সেকেন্ডের মধ্যে এই লাইনটি কার্যকর করার জন্য সরাসরি কোডগুলি রাখুন। সময় শেষ না হওয়া পর্যন্ত এটি পরীক্ষার বোতামের মতো ইউআই উপাদানগুলির সাথে পুনরাবৃত্তি করা বন্ধ করবে। যদিও ঘুম কিক করার সময় বোতামটি একধরনের হিমায়িত হয়, তত্ক্ষণাত ক্রিয়াকলাপের সূচকগুলির মতো অন্যান্য উপাদান এখনও হিমায়িত ছাড়াই ঘুরছে। ঘুমের সময় আপনি এই ক্রিয়াটি আবার ট্রিগার করতে পারবেন না।

sleep(4)
print("done")//Do stuff here

এখানে চিত্র বর্ণনা লিখুন

2. প্রেরণ, সম্পাদন এবং টাইমার

এই তিনটি পদ্ধতি একইভাবে কাজ করে, এগুলি সমস্ত কল ব্যাক সহ ব্যাকগ্রাউন্ড থ্রেডে চলছে, কেবলমাত্র বিভিন্ন সিনট্যাক্স এবং কিছুটা পৃথক বৈশিষ্ট্য সহ।

প্রেরণটি সাধারণত ব্যাকগ্রাউন্ড থ্রেডে কিছু চালাতে ব্যবহৃত হয়। এটি ফাংশন কল অংশ হিসাবে কলব্যাক আছে

DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(4), execute: {
    print("done")
})

পারফর্ম আসলে একটি সরল টাইমার। এটি বিলম্বের সাথে একটি টাইমার সেট আপ করে এবং তারপরে নির্বাচক দ্বারা ফাংশনটি ট্রিগার করে।

perform(#selector(callback), with: nil, afterDelay: 4.0)

func callback() {
    print("done")
}}

এবং পরিশেষে, টাইমার কলব্যাক পুনরাবৃত্তি করার ক্ষমতাও সরবরাহ করে, যা এই ক্ষেত্রে কার্যকর নয়

Timer.scheduledTimer(timeInterval: 4, target: self, selector: #selector(callback), userInfo: nil, repeats: false)


func callback() {
    print("done")
}}

এই তিনটি পদ্ধতির জন্য, আপনি যখন এগুলি ট্রিগার করতে বাটনে ক্লিক করবেন তখন ইউআই হিমায়িত হবে না এবং আপনাকে আবার এটিতে ক্লিক করার অনুমতি দেওয়া হবে। আপনি যদি আবার বোতামটিতে ক্লিক করেন তবে আরেকটি টাইমার সেট আপ হয়ে যাবে এবং কলব্যাকটি দু'বার ট্রিগার হবে।

এখানে চিত্র বর্ণনা লিখুন

উপসংহারে

চারটি পদ্ধতির কোনওটিই কেবল নিজের দ্বারা যথেষ্ট ভাল কাজ করে না। sleepব্যবহারকারীর মিথস্ক্রিয়া অক্ষম করবে, সুতরাং স্ক্রিনটি " হিমশীতল " (আসলে নয়) এবং খারাপ ব্যবহারকারীর অভিজ্ঞতার ফলস্বরূপ। অন্য তিনটি পদ্ধতি স্ক্রিনকে হিমায়িত করবে না, তবে আপনি এগুলি একাধিকবার ট্রিগার করতে পারেন এবং বেশিরভাগ সময় ব্যবহারকারীকে আবার কল দেওয়ার অনুমতি দেওয়ার আগে আপনি কলটি ফিরে না আসা পর্যন্ত অপেক্ষা করতে চান।

সুতরাং আরও ভাল ডিজাইন স্ক্রিন ব্লকিংয়ের সাথে তিনটি অ্যাসিঙ্ক পদ্ধতির একটি ব্যবহার করবে। ব্যবহারকারী যখন বোতামটিতে ক্লিক করেন, উপরে একটি স্পিনিং ক্রিয়াকলাপ সূচকটি দিয়ে কিছুটা স্বচ্ছ ভিউ দিয়ে পুরো স্ক্রিনটি কভার করুন, ব্যবহারকারীকে বলুন যে বোতামটি ক্লিক করা হচ্ছে। তারপরে কল ব্যাক ফাংশনে ভিউ এবং ইন্ডিকেটরটি সরান, ব্যবহারকারীকে বলবেন যে ক্রিয়াটি সঠিকভাবে পরিচালনা করা হয়েছে ইত্যাদি etc.


1
নোট করুন যে সুইফট 4-এ, অবজেক্ট ইনফারেন্স বন্ধ @objcহয়ে গেলে, perform(...)বিকল্পটির জন্য আপনাকে কলব্যাক ফাংশনের সামনে যুক্ত করতে হবে । ভালো লেগেছে তাই হয়:@objc func callback() {
লিয়ান

32

আমি পেলের সাথে একমত যে এখানে ব্যবহার dispatch_afterকরা ভাল পছন্দ । আপনি সম্ভবত জিসিডি কল পছন্দ করেন না কারণ তারা লিখতে বেশ বিরক্তিকর । পরিবর্তে আপনি এই সহায়ক সহায়ক যুক্ত করতে পারেন :

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, dispatchLevel: .background) { 
    // delayed code that will run on background thread
}

মূল থ্রেডে বিলম্বিত কোডটি আরও সহজ:

delay(bySeconds: 1.5) { 
    // delayed code, by default run in main thread
}

আপনি যদি এমন কোনও ফ্রেমওয়ার্ক পছন্দ করেন যাতে আরও কিছু সুবিধাজনক বৈশিষ্ট্য রয়েছে তবে হ্যান্ডি সুইফট চেকআউট করুন । তুমি তোমার প্রকল্পে যোগ করতে পারেন মাধ্যমে কার্থেজের বা Accio তারপর এটি ঠিক উপরের উদাহরণগুলোতে মত ব্যবহার করুন:

import HandySwift    

delay(by: .seconds(1.5)) { 
    // delayed code
}

এটি খুব সহায়ক বলে মনে হচ্ছে। আপনি এটি একটি সুইফ্ট 3.0 সংস্করণ দিয়ে আপডেট করার আপত্তি নেই? ধন্যবাদ
গ্রাহামক্র্যাকার 1234

আমি হ্যান্ডি সুইফটটিকে সুইফট 3 এ স্থানান্তরিত করতে শুরু করেছি এবং পরের সপ্তাহে একটি নতুন সংস্করণ প্রকাশের পরিকল্পনা করছি। তারপরে আমি উপরের স্ক্রিপ্টটিও আপডেট করব। সাথে থাকুন.
জিহুত

হ্যান্ডিউইফ্টকে সুইফট 3-এ স্থানান্তরিত করা এখন সম্পূর্ণ এবং সংস্করণ 1.3.0 এ প্রকাশিত হয়েছে। আমি সুইফট 3 এর সাথে কাজ করার জন্য উপরের কোডটিও সদ্য আপডেট করেছি! :)
Jeehut

1
আপনি কেন এনএসইসি_পি.এস.সি.সি দিয়ে আবার গুণ করছেন? তা কি অপ্রয়োজনীয় নয়? (যেমন ডাবল (Int64 (সেকেন্ডস * ডাবল (NSEC_PER_SEC)))) / ডাবল (NSEC_PER_SEC)) আপনি কি কেবল 'DispatchTime.now () + Double (সেকেন্ড) লিখতে পারবেন না?
মার্ক এ। ডোনোহো

1
আপনাকে ধন্যবাদ! মারকেইভ, আপনি অবশ্যই ঠিক আছেন। আমি সবেমাত্র কোড আপডেট করেছি। এটি কেবল এক্সকোড 8 থেকে স্বয়ংক্রিয় রূপান্তরকরণের ফলাফল DispatchTimeছিল এবং সুইফট ২-তে উপলব্ধ ছিল না আগে টাইপ রূপান্তরটি আগে প্রয়োজন ছিল It এটি let dispatchTime = dispatch_time(DISPATCH_TIME_NOW, Int64(seconds * Double(NSEC_PER_SEC)))আগে ছিল ।
জেহুত

24

আপনি সুইফট 3 দিয়েও এটি করতে পারেন।

মত বিলম্ব পরে ফাংশন সঞ্চালন।

override func viewDidLoad() {
    super.viewDidLoad()

    self.perform(#selector(ClassName.performAction), with: nil, afterDelay: 2.0)
}


     @objc func performAction() {
//This function will perform after 2 seconds
            print("Delayed")
        }

23

সুইফটে 4.2 এবং এক্সকোড 10.1

আপনার কাছে বিলম্বের মোট 4 টি উপায় রয়েছে। এই বিকল্পের মধ্যে 1 টি কিছু সময়ের পরে কোনও ফাংশন কল করা বা সম্পাদন করা ভাল। ঘুম () ব্যবহারে অন্তত ক্ষেত্রে দেখা যায়।

বিকল্প 1.

DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
    self.yourFuncHere()
}
//Your function here    
func yourFuncHere() {

}

বিকল্প 2।

perform(#selector(yourFuncHere2), with: nil, afterDelay: 5.0)

//Your function here  
@objc func yourFuncHere2() {
    print("this is...")
}

বিকল্প 3।

Timer.scheduledTimer(timeInterval: 5.0, target: self, selector: #selector(yourFuncHere3), userInfo: nil, repeats: false)

//Your function here  
@objc func yourFuncHere3() {

}

বিকল্প 4।

sleep(5)

কিছুক্ষণ চালানোর জন্য যদি আপনি কোনও ফাংশন কল করতে চান তবে ঘুম ব্যবহার করবেন না ।


19

NSTimer

@Nneonneo এর উত্তর ব্যবহারের পরামর্শ দিয়েছে NSTimerতবে কীভাবে এটি করা যায় তা দেখায় নি। এটি হল বেসিক সিনট্যাক্স:

let delay = 0.5 // time in seconds
NSTimer.scheduledTimerWithTimeInterval(delay, target: self, selector: #selector(myFunctionName), userInfo: nil, repeats: false)

এটি কীভাবে ব্যবহৃত হতে পারে তা দেখানোর জন্য এখানে একটি খুব সাধারণ প্রকল্প। একটি বোতাম টিপলে এটি একটি টাইমার শুরু করে যা আধ সেকেন্ডের বিলম্বের পরে একটি ফাংশন কল করবে।

import UIKit
class ViewController: UIViewController {

    var timer = NSTimer()
    let delay = 0.5
    
    // start timer when button is tapped
    @IBAction func startTimerButtonTapped(sender: UIButton) {

        // cancel the timer in case the button is tapped multiple times
        timer.invalidate()

        // start the timer
        timer = NSTimer.scheduledTimerWithTimeInterval(delay, target: self, selector: #selector(delayedAction), userInfo: nil, repeats: false)
    }

    // function to be called after the delay
    func delayedAction() {
        print("action has started")
    }
}

ব্যবহার dispatch_time(হিসাবে Palle এর উত্তর ) অন্য বৈধ বিকল্প। তবে এটি বাতিল করা শক্ত । এর সাথে NSTimer, বিলম্বিত ইভেন্টটি হওয়ার আগে বাতিল করতে, আপনাকে যা করতে হবে তা হ'ল কল

timer.invalidate()

sleepবিশেষত মূল থ্রেডে ব্যবহার করার পরামর্শ দেওয়া হয় না, যেহেতু এটি থ্রেডে সমস্ত কাজ করা বন্ধ করে দেয়।

আমার পূর্ণ উত্তর জন্য এখানে দেখুন ।


7

সুইফট 3.0 এ নিম্নলিখিত প্রয়োগের চেষ্টা করুন

func delayWithSeconds(_ seconds: Double, completion: @escaping () -> ()) {
    DispatchQueue.main.asyncAfter(deadline: .now() + seconds) { 
        completion()
    }
}

ব্যবহার

delayWithSeconds(1) {
   //Do something
}

7

আপনি সহজেই বিলম্বের ক্রিয়াটি ব্যবহার করতে এক্সটেনশন তৈরি করতে পারেন (সিনট্যাক্স: সুইফট ৪.২+)

extension UIViewController {
    func delay(_ delay:Double, closure:@escaping ()->()) {
        DispatchQueue.main.asyncAfter(
            deadline: DispatchTime.now() + Double(Int64(delay * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC), execute: closure)
    }
}

ইউআইভিউউকন্ট্রোলারে কীভাবে ব্যবহার করবেন

self.delay(0.1, closure: {
   //execute code
})

6

আপনার যদি এক সেকেন্ডের চেয়ে কম বিলম্ব সেট করতে হয় তবে .সেকেন্ডস পরামিতিটি সেট করা প্রয়োজন হয় না। আমি আশা করি এটি কারও কাজে লাগবে।

DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute: {
        // your code hear
})

5
DispatchQueue.global(qos: .background).async {
    sleep(4)
    print("Active after 4 sec, and doesn't block main")
    DispatchQueue.main.async{
        //do stuff in the main thread here
    }
}

4
করা DispatchQueue.main.asyncAfter(deadline: .now() + 4) {/*Do stuff*/}সম্ভবত আরও সঠিক ✌️
ইনিস্ট

5

যদি আপনার কোডটি ইতিমধ্যে একটি পটভূমি থ্রেডে চলমান থাকে তবে ফাউন্ডেশনে এই পদ্ধতিটি ব্যবহার করে থ্রেডটি বিরতি দিন :Thread.sleep(forTimeInterval:)

উদাহরণ স্বরূপ:

DispatchQueue.global(qos: .userInitiated).async {

    // Code is running in a background thread already so it is safe to sleep
    Thread.sleep(forTimeInterval: 4.0)
}

(যখন আপনার কোডটি মূল থ্রেডে চলছে তখন পরামর্শের জন্য অন্যান্য উত্তর দেখুন))


3

একটি সাধারণ সময়ের বিলম্ব তৈরি করতে, আপনি ডারউইন আমদানি করতে পারেন এবং তারপরে দেরি করতে ঘুম (সেকেন্ড) ব্যবহার করতে পারেন। এটি কেবল পুরো সেকেন্ডে সময় নেয়, তবে আরও সুনির্দিষ্ট পরিমাপের জন্য আপনি ডারউইন আমদানি করতে পারেন এবং খুব সুনির্দিষ্ট পরিমাপের জন্য ইউএসপ (এক সেকেন্ডের মিলিয়নতম) ব্যবহার করতে পারেন। এটি পরীক্ষা করতে, আমি লিখেছি:

import Darwin
print("This is one.")
sleep(1)
print("This is two.")
usleep(400000)
print("This is three.")

কোন মুদ্রণগুলি, তারপরে 1 সেকেন্ড এবং প্রিন্টের জন্য অপেক্ষা করে, তারপরে 0.4 সেকেন্ডের পরে প্রিন্টের জন্য অপেক্ষা করে। সবাই প্রত্যাশার মতো কাজ করেছিল।


-3

এটি সহজতম

    delay(0.3, closure: {
        // put her any code you want to fire it with delay
        button.removeFromSuperview()   
    })

2
এটি ফাউন্ডেশনের অংশ নয়, এটি আমি যেমন ধরে নিয়েছি, 'হ্যান্ডি সুইফট' কোকোপোডের অন্তর্ভুক্ত। আপনার উত্তরে আপনার এটি পরিষ্কার করা উচিত।
জান ন্যাশ

সুইফ্টের এমন কিছু আছে যা কিছু হওয়ার জন্য অপেক্ষা করে বা না?
সাইদ রহমতলাহী
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.