2012-11-23 42 views
9

Khi tôi thực thi mã này:NSTimer bộ nhớ quản lý

[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(showButtons) userInfo:nil repeats:NO]; 

Tôi cần tới bằng không nó hay phát hành nó, ot bất cứ điều gì cho việc quản lý bộ nhớ?

Tôi đang sử dụng ARC

Trả lời

27

Có, NSTimer sẽ duy trì tham chiếu mạnh mẽ đến target, điều này có thể gây ra (đặc biệt là trong các bộ đếm thời gian lặp) các chu kỳ tham chiếu mạnh mẽ (chu kỳ giữ nguyên). Trong ví dụ của bạn, mặc dù, bộ đếm thời gian không lặp lại, và bị trì hoãn chỉ 0,5, kịch bản trường hợp xấu nhất, bạn sẽ có một chu kỳ tham chiếu mạnh mẽ sẽ tự động giải quyết chính nó trong 0,5 giây.

Nhưng một ví dụ phổ biến của một chu kỳ tài liệu tham khảo mạnh mẽ chưa được giải quyết sẽ có một UIViewController với một tài sản mà lặp đi lặp lại NSTimer, nhưng vì NSTimer có một tham chiếu mạnh mẽ đối với UIViewController, bộ điều khiển sẽ kết thúc được giữ lại.

Vì vậy, nếu bạn đang giữ NSTimer làm biến mẫu, thì, có, bạn nên invalidate nó, để giải quyết chu kỳ tham chiếu mạnh mẽ. Nếu bạn chỉ đang gọi số scheduledTimerWithTimeInterval, nhưng không lưu nó vào một biến mẫu (như có thể suy ra từ ví dụ của bạn), thì chu kỳ tham chiếu mạnh mẽ của bạn sẽ được giải quyết khi NSTimer hoàn tất.

Và, bằng cách này, nếu bạn đang làm việc với lặp lại NSTimers, đừng cố gắng invalidate chúng trong dealloc của chủ sở hữu của NSTimerdealloc rõ ràng sẽ không được gọi cho đến khi chu kỳ tài liệu tham khảo mạnh mẽ được giải quyết. Ví dụ: trong trường hợp của UIViewController, bạn có thể làm điều đó trong viewDidDisappear.

Nhân tiện, số Advanced Memory Management Programming Guide giải thích chu kỳ tham chiếu mạnh mẽ là gì. Rõ ràng, đây là một phần mà chúng mô tả việc sử dụng đúng các tham chiếu yếu, không được áp dụng ở đây (vì bạn không kiểm soát được thực tế là NSTimer sử dụng tham chiếu mạnh mẽ cho đích), nhưng nó giải thích các khái niệm các chu kỳ tham chiếu mạnh mẽ độc đáo.


Nếu bạn không muốn NSTimer của bạn để giữ một tham chiếu mạnh để self, trong hệ điều hành MacOS 10.12 và iOS 10, hay muộn, bạn có thể sử dụng rendition khối và sau đó sử dụng mô hình weakSelf:

typeof(self) __weak weakSelf = self; 
[NSTimer scheduledTimerWithTimeInterval:0.5 repeats:false block:^(NSTimer * _Nonnull timer) { 
    [weakSelf showButtons]; 
}]; 

Nhân tiện, tôi nhận thấy bạn đang gọi showButtons. Nếu bạn đang cố gắng để chỉ hiển thị một số điều khiển trên quan điểm của bạn, bạn có thể loại bỏ việc sử dụng các NSTimer hoàn toàn và làm điều gì đó như:

self.button1.alpha = 0.0; 
self.button2.alpha = 0.0; 

[UIView animateWithDuration:0.25 
         delay:0.5 
        options:UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionAllowUserInteraction 
       animations:^{ 
        self.button1.alpha = 1.0; 
        self.button2.alpha = 1.0; 
       } 
       completion:nil]; 

này không bị các vấn đề giữ của NSTimer đối tượng, và thực hiện cả hai sự chậm trễ cũng như hiển thị duyên dáng của nút (s) tất cả trong một tuyên bố.Nếu bạn đang thực hiện xử lý bổ sung trong phương thức showButtons của mình, bạn có thể đặt phương thức đó trong khối completion.

+0

Câu trả lời hay, nhưng có lẽ tôi không nói rõ rằng tôi không thực sự khai báo nó trong tệp .h với bộ hẹn giờ NSTimer *, tôi chỉ thêm mã đó vào tệp .m, vì vậy tôi không thể làm mất hiệu lực hoặc không . Trong trường hợp này là nó vẫn ok nếu tôi sử dụng bộ đếm thời gian của tôi, hoặc là nó tốt hơn để sử dụng mã bạn cung cấp cho tôi? – Alessandro

+0

@Alessandro Tôi thực sự cho rằng bạn đã không duy trì một chiếc ngà cho bộ hẹn giờ. Nhưng, rõ ràng, nếu bạn muốn 'invalidate' trong' viewWillDisappear', bạn sẽ phải làm như vậy. (Là một sang một bên, bạn không cần phải đặt tư nhân ivars trong của bạn .h; mở rộng lớp học tư nhân là tốt hơn.) Và một vài lần bạn đã đề cập về việc thiết lập một 'NSTimer' để' nil'. Xin lưu ý rằng điều này không giải quyết được chu kỳ tham chiếu mạnh mẽ. Bộ hẹn giờ cần phải hoàn thành (và không lặp lại) hoặc bạn cần 'invalidate' (sử dụng ivar mới của bạn). – Rob

1

Nếu bạn đang lưu nó trong một tài sản, sau đó có, bạn cần phải đặt nó là con số không sau khi bị sa thải bộ chọn.

Nó cũng an toàn để lưu nó trong trường hợp lớp học của bạn được deallocated vì lý do gì, để bạn có thể [timer invalidate] nếu bạn cần.

+0

Nếu bạn thực hiện điều đó bất động sản 'weak', bạn không cần phải' nil' nó cho mình. Nó sẽ tự động tự giải phóng sau khi nó cháy (giả sử nó không lặp lại). – Rob

1

Có, bạn có thể sử dụng: myTimer=[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(showButtons) userInfo:nil repeats:NO]; Và sau đó trong viewDidDisappear bạn [myTimer invalidate]

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