উত্তর:
আমি আপনি যা খুঁজছেন মনে 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/docamentation/dispatch/1452876-dispatch_ after
dispatch_time(DISPATCH_TIME_NOW, 10ull * NSEC_PER_SEC)
স্নিপেট কদর্য এর জন্য কি কোনও পরিষ্কার উপায় নেই?
dispatch_get_current_queue()
সর্বদা যে সারিটি কোডটি চালানো হচ্ছে তা ফিরিয়ে দেয়। সুতরাং যখন এই কোডটি মূল থ্রেড থেকে চালানো হবে, তখন ব্লকটি মূল থ্রেডেও কার্যকর করা হবে।
dispatch_get_current_queue()
এখন
আপনি dispatch_after
পরে কোনও ব্লক কল করতে ব্যবহার করতে পারেন । এক্সকোডে, টাইপিং শুরু করুন dispatch_after
এবং নীচে Enter
স্বতঃপূরণে হিট করুন :
দুটি যুক্তি হিসাবে "আর্গুমেন্ট" হিসাবে এখানে একটি উদাহরণ। আপনাকে কোনও ধরণের ম্যাক্রোর উপর নির্ভর করতে হবে না এবং কোডটির উদ্দেশ্যটি স্পষ্ট:
let time1 = 8.23
let time2 = 3.42
// Delay 2 seconds
DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
print("Sum of times: \(time1 + time2)")
}
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)")
}
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);
});
NSEC_PER_SEC * 0.5
একই হিসাবে কাজ করবে NSEC_PER_MSEC * 500
। আপনি যদি মনে রাখবেন যে ঠিক dispatch_time
a৪-বিট পূর্ণসংখ্যার প্রত্যাশা করে, তবে এটির মানটি ন্যানোসেকেন্ডে রয়েছে। NSEC_PER_SEC
হিসাবে সংজ্ঞায়িত করা হয় 1000000000ull
এবং ভাসমান-পয়েন্ট ধ্রুবক দিয়ে গুণ 0.5
করলে 500000000.0
স্পষ্টভাবে একটি 64-বিট পূর্ণসংখ্যায় ফিরে কাস্ট করার পূর্বে ফলনকারী পয়েন্ট গণিত সম্পাদন করে would সুতরাং এর একটি ভগ্নাংশটি ব্যবহার করা পুরোপুরি গ্রহণযোগ্য NSEC_PER_SEC
।
এক্সকোড অন্তর্নির্মিত কোড স্নিপেট লাইব্রেরি ব্যবহার সম্পর্কে কীভাবে?
সুইফটের জন্য আপডেট:
অনেকগুলি ভোট আমাকে এই উত্তরটি আপডেট করতে অনুপ্রাণিত করেছিল।
বিল্ট-ইন এক্সকোড কোড স্নিপেট লাইব্রেরিতে dispatch_after
কেবলমাত্র objective-c
ভাষার জন্য রয়েছে। লোকেরা এর জন্য নিজস্ব কাস্টম কোড স্নিপেটও তৈরি করতে পারে Swift
।
এটি এক্সকোডে লিখুন।
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 পূরণ করুন Completion Shortcut
।
আরও তথ্যের জন্য ক্রিয়েটিং কাস্টমকোডসনিপেট দেখুন ।
এই কোডটি টানুন এবং কোড স্নিপেট লাইব্রেরি এরিয়ায় ফেলে দিন।
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(<#delayInSeconds#>)) {
<#code to be executed after a specified delay#>
}
জাইমে চমের উত্তরের উপর প্রসারিত করে আমি নীচের মতো একটি এনএসবজেক্ট + ব্লক বিভাগ তৈরি করেছি। আমি অনুভব করেছি যে এই পদ্ধতিগুলি বিদ্যমান performSelector:
এনএসবজেক্টের পদ্ধতির সাথে আরও ভালভাবে মেলে
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];
delay
হওয়া উচিত NSTimeInterval
(যা একটি হল double
)। #import <UIKit/UIKit.h>
প্রয়োজন হয় না। এবং, আমি দেখতে পাচ্ছি না কেন কার্যকর - (void)performBlock:(void (^)())block;
হতে পারে, তাই শিরোলেখ থেকে সরানো যেতে পারে।
কোথাও কোথাও ক্লাসে (যেমন "ইউটিল"), বা অবজেক্টের কোনও বিভাগে: সম্ভবত জিসিডির মাধ্যমে সহজতর:
+ (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!");
}];
সুইফটের জন্য আমি 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)
after
। তারপরে আপনি লিখতে পারেন:after(2.0){ print("do somthing") }
এখানে আমার 2 সেন্ট = 5 পদ্ধতি রয়েছে;)
আমি এই বিবরণগুলি সজ্জিত করতে পছন্দ করি এবং অ্যাপকোড আমাকে কীভাবে আমার বাক্যগুলি সমাপ্ত করতে হয় তা জানান।
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);
}
পারফর্মসিলিেক্টর: উইওবজেক্ট সর্বদা একটি অবজেক্ট নেয়, যাতে ইন / ডাবল / ফ্লোট ইত্যাদি যুক্তিগুলি পাস করার জন্য ..... আপনি এর মতো কিছু ব্যবহার করতে পারেন।
// এনএস নাম্বার একটি অবজেক্ট ..
[self performSelector:@selector(setUserAlphaNumber:)
withObject: [NSNumber numberWithFloat: 1.0f]
afterDelay:1.5];
-(void) setUserAlphaNumber: (NSNumber*) number{
[txtUsername setAlpha: [number floatValue] ];
}
একইভাবে আপনি [এনএসএন নাম্বারবিহীন আইটেম:] ইত্যাদি ব্যবহার করতে পারেন .... এবং প্রাপ্ত পদ্ধতিতে আপনি নম্বরটি [বিন্যাস] বা [সংখ্যা দ্বিগুণ] হিসাবে আপনার বিন্যাসে রূপান্তর করতে পারেন।
প্রেরণ_পরিবর্তন ফাংশন একটি নির্দিষ্ট সময়ের পরে একটি প্রেরণ সারিতে একটি ব্লক অবজেক্ট প্রেরণ করে। ২.০ সেকেন্ডের পরে কিছু 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:
let dispatchTime: DispatchTime = DispatchTime.now() + Double(Int64(2.0 * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)
DispatchQueue.main.asyncAfter(deadline: dispatchTime, execute: {
})
mainQueue,
পরিবর্তেmainQueue)
বার বার বিরক্তিকর জিসিডি কল করা রোধ করার জন্য এক সহায়ক সহায়ক :
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
}
আপনি যদি এমন কোনও ফ্রেমওয়ার্ক পছন্দ করেন যাতে আরও কিছু সুবিধাজনক বৈশিষ্ট্য রয়েছে তবে হ্যান্ডি সুইফট চেকআউট করুন । আপনি এটি কার্থেজের মাধ্যমে আপনার প্রকল্পে যুক্ত করতে পারেন তবে উপরের উদাহরণগুলির মতো একে একে ব্যবহার করুন:
import HandySwift
delay(bySeconds: 1.5) {
// delayed code
}
সুইফ্ট 3-তে, আমরা 'এন' সেকেন্ডের বিলম্বের পরে কোনও ক্রিয়া বা ক্রিয়া ট্রিগার করতে কেবল DispatchQueue.main.asyncAfter ফাংশনটি ব্যবহার করতে পারি। এখানে কোডে আমরা 1 সেকেন্ড পরে বিলম্ব স্থির করেছি। আপনি এই ফাংশনটির শরীরে এমন কোনও ফাংশন কল করেছেন যা 1 সেকেন্ডের বিলম্বের পরে ট্রিগার করবে।
let when = DispatchTime.now() + 1
DispatchQueue.main.asyncAfter(deadline: when) {
// Trigger the function/action after the delay of 1Sec
}
আপনি হয় নিজের ক্লাসে যুক্তি মোড়ানো করতে পারেন, বা পদ্ধতি কলটি এমন পদ্ধতিতে মোড়ানো করতে পারেন যা আদিম ধরণের পাস করার প্রয়োজন হয় না। তারপরে আপনার বিলম্বের পরে সেই পদ্ধতিটি কল করুন এবং সেই পদ্ধতির মধ্যে আপনি যে নির্বাচকটি সম্পাদন করতে চান তা সম্পাদন করুন।
সুইফটে বিলম্বের পরে আপনি কীভাবে একটি ব্লক ট্রিগার করতে পারেন তা এখানে:
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)
}
এটি আমার রেপোতে একটি স্ট্যান্ডার্ড ফাংশন হিসাবে অন্তর্ভুক্ত ।
সুইফট 3 এবং এক্সকোড 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 :)
}
}
}
আমি বিশ্বাস করি যে লেখক কীভাবে একটি ভগ্নাংশের (দেরি) জন্য অপেক্ষা করবেন তা জিজ্ঞাসা করছেন না, পরিবর্তে নির্বাচকটির যুক্তি হিসাবে একটি স্কেলারটি কীভাবে পাস করবেন (ওজেক্ট :) সহ এবং আধুনিক উদ্দেশ্য সি এর দ্রুততম উপায়টি হ'ল:
[obj performSelector:... withObject:@(0.123123123) afterDelay:10]
আপনার নির্বাচককে তার প্যারামিটারটি এনএসএনম্বারে পরিবর্তন করতে হবে এবং ফ্লোটভ্যালু বা ডাবলভ্যালুর মতো নির্বাচক ব্যবহার করে মানটি পুনরুদ্ধার করতে হবে