ฉันจะหน่วงเวลาการเรียกใช้เมธอดเป็นเวลา 1 วินาทีได้อย่างไร


164

มีวิธีที่ง่ายในการชะลอการเรียกเมธอดเป็นเวลา 1 วินาทีหรือไม่?

ฉันมีสิ่งUIImageViewที่ตอบสนองต่อเหตุการณ์แบบสัมผัส เมื่อตรวจพบการสัมผัสภาพเคลื่อนไหวบางอย่างเกิดขึ้นในแอพ หลังจากหนึ่งวินาทีฉันต้องการเรียกวิธีอื่น ในกรณีนี้ฉันไม่สามารถใช้animationDidStopตัวเลือกได้


มีหลายวิธีในการทำเช่นนั้นหนึ่งในนั้นอาจใช้เพียงแค่ sleep () เพื่อระงับโปรแกรม / เธรดสำหรับมิลลิวินาทีจำนวนหนึ่งอย่างไรก็ตามฉันคิดว่าคุณอาจต้องการบอกเราว่าคุณพยายามทำอะไรโดย ทำอย่างนั้น? ฉันหมายความว่าอะไรคือปัญหาที่แท้จริงของคุณ? แนวคิดของการหน่วงเวลาการเรียกใช้เมธอดดูเหมือนเป็น 'การแก้ปัญหา' ที่จะเป็นวิธีที่ไม่ฟังดูดีเกินไปที่จะซื่อสัตย์ ดังนั้นเพียงแค่บอกเราเพิ่มเติมเกี่ยวกับสถานการณ์ที่คุณมีอยู่ในใจ
ไม่มี

คำตอบ:


254
performSelector:withObject:afterDelay:

เอกสารอ้างอิง


7
นี่คือคำตอบที่ถูกต้อง โปรดดูdeveloper.apple.com/DOCUMENTATION/Cocoa/Reference/Foundation/
......

มีวิธีการบางอย่างกับค่าตอบแทนของวิธีการที่ได้รับเรียก? หรือฉันจำเป็นต้องตั้งค่าเพื่อแก้ไขพารามิเตอร์หากฉันต้องการรับข้อมูลกลับมาจากมัน?
Gordon Gustafson

หากมีใครสนใจวิธียกเลิกการโทรที่กำหนดไว้: [NSObject CancorePerformRequestsWithTarget: yourTarget selector: aSelector object: anArgument];
vir us

192

คุณสามารถใช้บล็อก

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
    [object method]; 
});

ส่วนใหญ่เวลาที่คุณจะต้องการใช้ dispatch_get_main_queue แต่ถ้ามี UI ที่ไม่มีในวิธีการที่คุณสามารถใช้คิวโลก

แก้ไข:

เวอร์ชั่น Swift 3:

DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
    object.method()
}

อย่างเท่าเทียมกันDispatchQueue.global().asyncAfter(...นอกจากนี้ยังอาจจะเป็นตัวเลือกที่ดี


พบว่าวิธีนี้จะง่ายกว่าตัวเลือกเมื่อผสมค่าตรง C และ ObjC
Paul Slocum

1
น่าเสียดายที่ dispatch_get_current_queue เลิกใช้แล้วตั้งแต่ iOS6
chrisben

3
อัปเดตเพื่อใช้ dispatch_get_main_queue แทน dispatch_get_current_queue
mcfedr

2
Xcode จะดำเนินการนี้โดยอัตโนมัติเพียงแค่เริ่มพิมพ์dispatch_afterและกด Enter
mcfedr

1
โดยเฉพาะอย่างยิ่งตอนนี้ Xcode เติมข้อความอัตโนมัติเมื่อพิมพ์dispatch_afterนี่เป็นวิธีที่ทำได้ง่ายมากและคุณสามารถส่งผ่านคุณสมบัติไปยังวิธีการที่คุณโทรหาซึ่งยอดเยี่ยมมาก
Erik van der Neut

128

วิธีที่ดีที่สุดที่จะทำคือ:

[self performSelector:@selector(YourFunctionName) 
           withObject:(can be Self or Object from other Classes) 
           afterDelay:(Time Of Delay)];

คุณยังสามารถผ่านศูนย์เช่นเดียวกับ withObject พารามิเตอร์

ตัวอย่าง:

[self performSelector:@selector(subscribe) withObject:self afterDelay:3.0 ];

3
ทำไมคุณต้องส่งตัวเองให้ตนเอง?
Eric

2
แล้วทำไมคุณต้องส่งตัวแปรไปยังวิธีการที่ใช้การขัดแย้งแบบไม่มีศูนย์
hellozimi

23

มีคำตอบมากมายอยู่แล้วและถูกต้องทั้งหมด ในกรณีที่คุณต้องการใช้งานdispatch_afterคุณควรมองหาตัวอย่างข้อมูลที่รวมอยู่Code Snippet Libraryในด้านล่างขวา (ซึ่งคุณสามารถเลือกUIองค์ประกอบ)

ป้อนคำอธิบายรูปภาพที่นี่

ดังนั้นคุณเพียงแค่ต้องเรียกตัวอย่างนี้โดยเขียนส่งในรหัส:

ป้อนคำอธิบายรูปภาพที่นี่


16

คุณสามารถใช้ตัวเลือกการดำเนินการสำหรับหลังจากวิธีการหน่วงเวลา 0.1 วินาทีถูกเรียกใช้สำหรับรหัสต่อไปนี้เพื่อทำสิ่งนี้

[self performSelector:@selector(InsertView)  withObject:nil afterDelay:0.1]; 

9

นอกจากนี้คุณยังสามารถ:

[UIView animateWithDuration:1.0
                 animations:^{ self.view.alpha = 1.1; /* Some fake chages */ }
                 completion:^(BOOL finished)
{
    NSLog(@"A second lapsed.");
}];

กรณีนี้คุณต้องปลอมการเปลี่ยนแปลงบางอย่างในมุมมองบางอย่างเพื่อให้ภาพเคลื่อนไหวทำงานได้ มันแฮ็คจริง ๆ แต่ฉันชอบเนื้อหาที่มีบล็อก หรือปิด @mcfedr คำตอบด้านล่าง


waitFor(1.0, ^
{
    NSLog(@"A second lapsed");
});

typedef void (^WaitCompletionBlock)();
void waitFor(NSTimeInterval duration, WaitCompletionBlock completion)
{
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, duration * NSEC_PER_SEC),
                   dispatch_get_main_queue(), ^
    { completion(); });
}

ไม่แน่ใจ แต่ฉันคิดว่าตัวเลือกแรกที่คุณแนะนำอาจมีผลข้างเคียงที่ผู้ใช้ควรทราบเช่นการบล็อกการโต้ตอบกับผู้ใช้ในส่วนของ UI สัญชาตญาณของฉันคือมันอาจทำให้เกิด CPU ที่ไม่จำเป็นหรือการระบายทรัพยากรอื่น ๆ แต่ฉันไม่ได้ตรวจสอบ
Bjorn Roche


4

สวิฟท์ 2.x

let delayTime = dispatch_time(DISPATCH_TIME_NOW, Int64(1 * Double(NSEC_PER_SEC)))
 dispatch_after(delayTime, dispatch_get_main_queue()) {
 print("do some work")
}

Swift 3.x - & - Swift 4

DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
    print("do some work")
}

หรือผ่าน escaping closure

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

1

มีโซลูชัน Swift 3 จากโซลูชันที่ตรวจสอบ:

self.perform(#selector(self.targetMethod), with: self, afterDelay: 1.0)

และมีวิธีการคือ

@objc fileprivate func targetMethod(){

}


-34

หมายเหตุ: สิ่งนี้จะหยุดกระทู้ทั้งหมดของคุณชั่วคราวไม่ใช่เพียงวิธีการเดียว
โทรหา sleep / wait / halt 1000 ms ก่อนเรียกวิธีการของคุณใช่ไหม

Sleep(1000); // does nothing the next 1000 mSek

Methodcall(params); // now do the real thing

แก้ไข: คำตอบข้างต้นนำไปใช้กับคำถามทั่วไป "ฉันจะหน่วงเวลาการเรียกวิธีการเป็นเวลา 1 วินาทีได้อย่างไร" ซึ่งเป็นคำถามที่ถามเมื่อเวลาตอบ (infact คำตอบที่ได้รับภายใน 7 นาทีจากคำถามเดิม: - )) ไม่มีข้อมูลเกี่ยวกับภาษาในขณะนั้นดังนั้นโปรดหยุดการพูดจาเกี่ยวกับวิธีการใช้ sleep ที่เหมาะสมใน XCode และการขาดคลาส ...


เฉพาะในเธรดปัจจุบันเท่านั้นเธรดอื่น ๆ จะยังคงทำงานต่อไป
Marc Charbonneau

4
โธ่ ฉันเข้าใจว่าทำไมสิ่งนี้ถึงถูกโหวตไม่กี่ครั้ง แต่ใครจะเห็นสิ่งนี้ที่ -27 และตัดสินใจว่ามันจำเป็นต้องมีอีก -3 หรืออะไรที่ไม่เข้าใจ ทำไมไม่เพียงแค่แก้ไขคำตอบเพื่อพูดว่า "สิ่งนี้จะหยุดกระทู้ทั้งหมดของคุณ" หรือบางสิ่งบางอย่างแทนการ downvoting มันคน?
Albert Renshaw

แล้วถ้าคุณต้องการหยุดกระทู้ทั้งหมดชั่วคราว? ดูเหมือนว่าตัวเลือกที่ถูกต้องหากมันมาพร้อมกับคำเตือนที่ดี
Departamento B

@AlbertRenshaw ฉันเห็นด้วยกับคุณโดยสิ้นเชิง ฉันอยู่ที่นี่และลง 35 และฉันให้เขาขึ้น ฉันเห็นว่าชอบโจมตีผู้ใช้ที่มีชื่อเสียงต่ำมาก ๆ ไม่มีใครจะแก้ไขหรือระบุอะไรก็ได้ ฉันเห็นคำตอบหนึ่งข้อวันนี้ว่าการจมน้ำจริงๆ ข้อผิดพลาดเพียงอย่างเดียวที่คนทำนั่นคือเขา / เธอตอบภายใต้คำถามที่รวดเร็วด้วยภาษา c วัตถุประสงค์ หากเป็นความผิดพลาดครั้งใหญ่ฉันต้องการแสดงคำตอบที่รวดเร็วจำนวนมากภายใต้คำถาม c ตามวัตถุประสงค์
soorej babu
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.