Làm thế nào tôi có thể trì hoãn một cuộc gọi phương thức trong 1 giây?


164

Có cách nào dễ dàng trì hoãn một cuộc gọi phương thức trong 1 giây không?

Tôi có một UIImageViewphản ứng trên một sự kiện cảm ứng. Khi cảm ứng được phát hiện, một số hình ảnh động xảy ra trong ứng dụng. Sau một giây, tôi muốn gọi một phương thức khác. Trong trường hợp này, tôi không thể sử dụng animationDidStopbộ chọn.


Chắc chắn có một số cách để làm điều đó, một trong số đó có thể chỉ đơn giản là sử dụng chế độ ngủ () để tạm dừng chương trình / luồng trong một vài mili giây, tuy nhiên tôi nghĩ bạn có thể muốn cho chúng tôi biết chính xác bạn đang cố gắng thực hiện điều gì làm vậy Ý tôi là, vấn đề thực sự của bạn là gì? Ý tưởng trì hoãn một cuộc gọi phương thức có vẻ như là một "giải pháp", một điều không có vẻ quá tốt để thành thật. Vì vậy, chỉ cần cho chúng tôi biết thêm về kịch bản bạn có trong tâm trí.
không có

Câu trả lời:


254
performSelector:withObject:afterDelay:

Tài liệu tham khảo


7
Đây là câu trả lời chính xác. Vui lòng xem developer.apple.com/DOCUMENTATION/Cocoa/Reference/Foundation/iêu :
gây hại

Có cách nào để một cái gì đó với giá trị trả về của phương thức được gọi không? Hoặc tôi cần phải thiết lập nó để sửa đổi tham số nếu tôi muốn lấy lại một số thông tin từ nó?
Gordon Gustafson

nếu ai đó quan tâm làm thế nào để hủy cuộc gọi theo lịch trình: [NSObject CancPreinglyPerformRequestsWithTarget: yourTarget selector: aSelector object: anArgument];
vir chúng tôi

192

Bạn cũng có thể sử dụng một khối

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

Hầu hết thời gian bạn sẽ muốn sử dụng Clark_get_main_queue, mặc dù nếu không có UI trong phương thức bạn có thể sử dụng hàng đợi toàn cầu .

Biên tập:

Phiên bản Swift 3:

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

Tương tự, DispatchQueue.global().asyncAfter(...cũng có thể là một lựa chọn tốt.


Tìm thấy giải pháp này dễ dàng hơn PerformanceSelector khi trộn thẳng C và ObjC
Paul Slocum 17/07/13

1
Thật không may,
Clark_get_cản_queue

3
Đã cập nhật để sử dụng
Clark_get_main_queue

2
Xcode bây giờ sẽ tự động hoàn thành việc này, chỉ cần bắt đầu nhập dispatch_aftervà nhấn enter
mcfedr

1
Đặc biệt là bây giờ Xcode tự động hoàn thành việc này khi gõ dispatch_after, đây thực sự là một cách cực kỳ đơn giản để thực hiện, ngoài ra bạn có thể chuyển các thuộc tính cho phương thức bạn đang gọi, rất tuyệt vời.
Erik van der Neut

128

Cách tốt nhất để làm là:

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

bạn cũng có thể truyền nil dưới dạng tham số withObject.

thí dụ :

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

3
Tại sao bạn lại tự vượt qua chính mình?
Eric

2
Và tại sao bạn lại truyền một biến cho một phương thức không có đối số?
hellozimi

23

Đã có rất nhiều câu trả lời và tất cả đều đúng. Trong trường hợp bạn muốn sử dụng, dispatch_afterbạn nên tìm đoạn mã được bao gồm bên trong Code Snippet Libraryở dưới cùng bên phải (nơi bạn có thể chọn các UIyếu tố).

nhập mô tả hình ảnh ở đây

Vì vậy, bạn chỉ cần gọi đoạn mã này bằng cách viết công văn trong mã:

nhập mô tả hình ảnh ở đây


16

Bạn có thể sử dụng bộ chọn thực hiện sau khi phương thức trễ 0,1 giây được gọi cho đoạn mã sau để thực hiện việc này.

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

9

Bạn cũng có thể:

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

Trong trường hợp này, bạn phải giả mạo một số thay đổi đối với một số chế độ xem để hoạt hình hoạt động. Nó thực sự là hacky, nhưng tôi yêu các công cụ dựa trên khối. Hoặc gói lại câu trả lời @mcfedr bên dưới.


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(); });
}

Không chắc chắn, nhưng tôi nghĩ tùy chọn đầu tiên bạn đề xuất có thể có tác dụng phụ mà người dùng nên biết, ví dụ: chặn tương tác người dùng trên các phần của giao diện người dùng. Bản năng của tôi là nó cũng sẽ gây ra một số CPU không cần thiết hoặc tài nguyên khác, nhưng tôi đã không kiểm tra.
Bjorn Roche

8

Bạn có thể làm được việc này

[self performSelector:@selector(MethodToExecute) withObject:nil afterDelay:1.0 ];

4

Swift 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")
}

hoặc vượt qua một escaping closure

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

1

Có một giải pháp Swift 3 từ giải pháp đã kiểm tra:

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

Và có phương pháp

@objc fileprivate func targetMethod(){

}


-34

LƯU Ý: điều này sẽ tạm dừng toàn bộ chủ đề của bạn, không chỉ một phương thức.
Thực hiện cuộc gọi để ngủ / chờ / tạm dừng 1000 ms ngay trước khi gọi phương thức của bạn?

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

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

Chỉnh sửa: Câu trả lời trên áp dụng cho câu hỏi chung "Làm cách nào tôi có thể trì hoãn cuộc gọi phương thức trong 1 giây?", Đó là câu hỏi được hỏi tại thời điểm trả lời (thực hiện câu trả lời được đưa ra trong vòng 7 phút của câu hỏi ban đầu: - )). Không có thông tin nào được đưa ra về ngôn ngữ tại thời điểm đó, vì vậy vui lòng ngừng chê bai về cách sử dụng giấc ngủ hợp lý i XCode vì thiếu lớp học ...


Chỉ trong luồng hiện tại, các luồng khác sẽ tiếp tục chạy.
Marc Charbonneau

4
Trời ạ. Tôi hiểu tại sao điều này đã được bỏ phiếu một vài lần, nhưng ai đã nhìn thấy điều này ở -27 và quyết định nó cần một thứ khác? Có -3 hoặc một cái gì đó không nhận được điểm. Tại sao không chỉnh sửa câu trả lời để nói "điều này sẽ tạm dừng toàn bộ chủ đề của bạn" hoặc một cái gì đó thay vì hạ thấp nó mọi người?
Albert Renshaw

Vì vậy, nếu bạn chỉ muốn tạm dừng toàn bộ chủ đề? Có vẻ như là một lựa chọn hợp lệ nếu nó đi kèm với một cảnh báo tốt.
Departamento B

@AlbertRenshaw Tôi hoàn toàn đồng ý với bạn. Tôi ở đây và 35 điểm hạ gục và tôi đã cho anh ta lên. Tôi thấy giống như tấn công vào người dùng có uy tín thấp rất tệ. Không ai sẽ làm bất kỳ chỉnh sửa hoặc chỉ định bất cứ điều gì. Tôi đã thấy một câu trả lời ngày hôm nay rằng đã thực sự bị chết đuối. Sai lầm duy nhất mà người đó đã làm là anh ấy / cô ấy đã trả lời dưới một câu hỏi nhanh với ngôn ngữ c khách quan. Nếu đó là một sai lầm lớn, tôi muốn hiển thị rất nhiều câu trả lời nhanh chóng dưới các câu hỏi c khách quan.
soorej babu
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.