2015-01-22 16 views
24

Có cách nào để hủy dispatch_after() được lên lịch một thời gian trong tương lai và chưa bắn cho đến nay không? Tôi đang cố gắng tạo một thứ gì đó giống như một bộ lập lịch để cập nhật từ máy chủ và phương pháp này cũng giống như tôi muốn, nhưng tôi rất muốn hủy và lên lịch lại vào một thời điểm nào đó. Tôi có thể dự phòng và sử dụng NSTimer không?hủy phương thức dispatch_after()?

+0

yup. có vẻ như chúng tôi có bản sao. Tự hỏi liệu có thể hợp nhất các câu hỏi này không? –

Trả lời

1

Sử dụng nguồn bộ hẹn giờ công văn (đó là những gì dispatch_after sử dụng nội bộ anyway).

Có thể hủy nguồn hẹn giờ công văn hoặc thay đổi thông số bộ đếm thời gian sau khi tạo.

19

Không có cách nào để ngăn dispatch_block thực hiện khi nó đã được gửi đến hàng đợi của nó, có nghĩa là dispatch_after của bạn không thể bị hủy bỏ. Chỉ có tùy chọn là thêm vào khối của bạn một điều kiện để được kiểm tra trong thời gian chạy để ngăn chặn thực thi. tức là.

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 10 * NSEC_PER_SEC), dispatch_get_main_queue(),^{ 
if(self.shouldExecuteDispatchBlock) 
{ // do your stuff } }); 
+0

Hmmm vì vậy cho đến khi thời gian tiếp theo để thực hiện khối này xuất hiện (và nó được thiết lập để được hủy bỏ), tôi đoán nó sẽ hog tất cả các bộ nhớ/đối tượng cho đến khi đó. Có thể một vấn đề nếu chu kỳ của bạn là như 60 phút? :-) – Jonny

+0

Có và không. Khối sao chép bộ nhớ, có nghĩa là nếu bạn yêu cầu giá trị int trong khối của mình, khối này sẽ được sao chép và sẽ nằm trong bộ nhớ dưới dạng bản sao miễn là khối đó hoạt động. Nhưng đối với đối tượng, nó không sao chép chúng, nó sao chép địa chỉ. Nếu bạn muốn một hình ảnh, bạn sẽ có một đối tượng UIImage trong heap nhưng khối sẽ chỉ giữ lại một giá trị con trỏ (8 byte trong arch64) vì vậy, không có biggie. Tất nhiên hình ảnh sẽ được giữ lại trong bộ nhớ cho đến khi khối này biến mất, vì vậy nó sẽ không được sạch bởi vòng cung. –

+0

Tôi đã biến điều này thành phần mở rộng cho DispatchQueue: https://github.com/nrbrook/DispatchAfterCancellable – Nick

11

OK, vì vậy, với tất cả các câu trả lời thu được, và giải pháp khả thi, có vẻ như tốt nhất cho trường hợp này (bảo quản đơn giản) đang kêu gọi performSelector:withObject:afterDelay: và hủy bỏ nó với cancelPreviousPerformRequestsWithTarget: cuộc gọi khi mong muốn. Trong trường hợp của tôi - ngay trước khi lên kế hoạch tiếp theo trì hoãn cuộc gọi:

[NSObject cancelPreviousPerformRequestsWithTarget: self selector:@selector(myDelayedMethod) object: self]; 

[self performSelector:@selector(myDelayedMethod) withObject: self afterDelay: desiredDelay]; 
+0

Tôi bắt đầu xuống đường dẫn này, nhưng làm thế nào để làm điều đó với các phương thức lớp (đó là lý do tại sao tôi chuyển sang 'dispatch_after')? – Olie

+0

@Olie tốt nhất. Sau đó, bạn phải bao bọc các cuộc gọi đó, hoặc sử dụng dispatch + flag (đoán, giây sẽ đơn giản hơn) –

Các vấn đề liên quan