2013-06-06 27 views
8

tham khảo:IOS - performSelector: withObject: afterDelay: KHÔNG LÀM VIỆC

https://stackoverflow.com/a/14741253/1749293

Giống như liên kết ở trên đã nói, nhưng có vẻ như nó không giải thích lý do.

Trong mã của tôi, sau đây sẽ làm việc:

dispatch_async(dispatch_get_main_queue(), ^{ 
     [self performSelector: @selector(helloWorld) withObject:nil afterDelay:0.5]; 
}); 

nhưng, khi tôi bình luận một cái gì đó như thế này, (và tôi thực sự chắc chắn rằng tôi chạy nó trong các chủ đề chính !!) mã không công việc:

// dispatch_async(dispatch_get_main_queue(), ^{ 
     [self performSelector: @selector(helloWorld) withObject:nil afterDelay: 0.5]; 
// }); 

Ai đó có thể cho tôi biết lý do không? 'tự', sẽ nerver phát hành/deallocated, tôi giữ nó cho đến khi ứng dụng kết thúc.

"không làm việc", có nghĩa là, (không sụp đổ) nó không nhảy vào phương pháp "HelloWorld":

-(void) helloWorld { 
    NSLog(@"hello world");  // I set a break point here for debug , it wouldn't pause forever 
} 

Tôi nghĩ là Run Vòng nguyên nhân vấn đề này. Giống như this link đã nói, nhưng tôi cần thêm chi tiết hoặc giải thích rõ ràng hơn.

+1

Điều đó thật kỳ quặc nếu bạn thực sự là chủ đề chính. Bất kỳ lý do cụ thể nào khiến bạn không sử dụng 'dispatch_after()'? –

+0

BROKER.actors.event là gì? – manujmv

+0

Trong mã đầu tiên của bạn, bạn đang sử dụng 'self' trong khi trong seconde bạn đang sử dụng' BROKER.actors.event'. Vì vậy, bạn có chắc chắn họ đang đề cập đến cùng một điều? – sunkehappy

Trả lời

21

Khi tôi có loại điều này xảy ra, tôi đã gọi performSelector từ một công văn GCD. Vì vậy, nó đã được thiết lập bộ đếm thời gian trong chuỗi công nhân GCD mà đi trước khi bộ đếm thời gian bắn. Khi GCD loại bỏ chuỗi công nhân, bộ hẹn giờ bị mất, do đó bộ chọn không bao giờ được gọi.

+2

OP: "thực sự chắc chắn rằng tôi chạy nó trong chủ đề chính". – Mar0ux

+1

+1 để có giải thích tốt – onmyway133

1

EDIT Như đã đề cập trong các ý kiến, performSelector: withObject: afterDelay: cũng vẫn giữ được đối tượng của bạn, vì vậy bỏ qua câu trả lời của tôi. END EDIT

Tôi cho rằng bạn đang sử dụng ARC. Khối của bạn đang giữ lại đối tượng của bạn.

dispatch_async(dispatch_get_main_queue(), ^{ 
     [self performSelector: @selector(helloWorld) withObject:nil afterDelay:aTimeUnit]; 
}); 

Đây là lý do tại sao bộ chọn được kích hoạt. Khi bạn nhận xét khối, không ai giữ lại một tham chiếu đến đối tượng của bạn, vì vậy nó sẽ tự động được phát hành.

// dispatch_async(dispatch_get_main_queue(), ^{ 
     [self performSelector: @selector(helloWorld) withObject:nil afterDelay: aTimeUnit]; 
// }); 

Khi thời gian aTimeUnit đã trôi qua, tự có thể đã được phát hành, do đó cuộc gọi chọn bị mất. Đó là vấn đề của bạn.

Bạn nên tránh chụp tự bên trong một khối, bởi vì nếu bạn lưu trữ khối trong một thanh ngang, bạn có thể kết thúc với một chu kỳ giữ lại, khiến cho đối tượng không được giải phóng. Ở đây họ nói về điều đó: How do I avoid capturing self in blocks when implementing an API?

+0

Cuộc gọi chọn đối tượng được giải phóng thường kết thúc bằng một sự cố, phải không? –

+7

Và tôi khá chắc chắn rằng performSelector cũng giữ lại mọi thứ. –

+0

tôi cũng nghĩ rằng, như w.sellers, rằng performSelector trở thành chủ sở hữu của đối tượng quan tâm, giữ lại nó cho đến khi nó thực hiện bộ chọn, do đó, không thực sự cần phải lo lắng cho bản thân được deallocated trong khi đó – meronix

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