2011-10-17 49 views
7

Đây là câu hỏi ít hơn và nhiều hơn nữa về bản ghi những gì tôi tìm thấy xung quanh mã mẫu AVCam do Apple cung cấp cho iOS4 và 5 thao tác máy ảnh. Các triệu chứng của vấn đề đối với tôi là ứng dụng của tôi sẽ gặp sự cố khi khởi chạy AVCamViewController sau khi chụp khoảng 5-10 ảnh.Cảnh báo cảnh báo AVCam thấp

Tôi chạy ứng dụng thông qua trình tiết lộ rò rỉ bộ nhớ và không có rò rỉ rõ ràng nhưng khi kiểm tra với Activity Monitor tôi phát hiện ra rằng một cái gì đó gọi là mediaserverd đã tăng 17Mb mỗi khi máy ảnh được khởi chạy và khi nó đạt ~ 100Mb ứng dụng bị lỗi với nhiều cảnh báo bộ nhớ thấp.

+0

Cảm ơn! Vui lòng chia câu trả lời thành câu trả lời, sau đó bạn có thể chấp nhận: [Nghi thức trả lời câu hỏi của riêng bạn] (http://meta.stackexchange.com/questions/17845/etiquette-for-answering-your-own-question) và [Đăng và trả lời các câu hỏi mà bạn đã tìm thấy câu trả lời] (http://meta.stackexchange.com/questions/2706/posting-and-answering-questions-you-have-already-found-the-answer-to) – sehe

+0

Đã cố gắng nhưng vì tôi không phải là người dùng cao cấp nên nó sẽ không cho phép tôi trả lời câu hỏi của mình trong vòng 24 giờ ... không có thời gian để làm phiền nó (hoặc quên những gì tôi muốn ghi lại) ... Tôi sẽ xem nếu tôi có thể làm điều đó ngay bây giờ. –

Trả lời

4

của Apple sửa đổi mã mẫu trên 17 Tháng 10 năm 2013, sửa chữa các chu kỳ giữ lại. Vấn đề là do sử dụng không đúng cách self trong các khối được xác định trong init.

Dưới đây là mô tả phiên bản

cố định duy trì chu kỳ trong AVCaptureManager dẫn đến rò rỉ. LƯU Ý - nếu bạn đã điều chỉnh mã AVCam trong ứng dụng của mình, bạn nên áp dụng các bản sửa lỗi được thực hiện ở đây theo phương pháp init của AVCaptureManager.m. Nếu không có các bản sửa lỗi này, bạn có thể bị rò rỉ AVCaptureManager trường hợp và để máy ảnh chạy liên tục trong khi ứng dụng của bạn ở nền trước.


Tuy nhiên, sửa chữa họ giới thiệu chỉ hoạt động trong trường hợp của tay Giữ lại Count. Nếu bạn đang sử dụng ARC trên dự án, ngoài việc loại bỏ các cuộc gọi release/retain và những điều hiển nhiên khác, bộ định mức lưu trữ cho weakSelf phải được thay đổi từ __block thành __weak, như sau.

__weak AVCamCaptureManager *weakSelf = self; 

Trên thực tế, ngữ nghĩa của __block đã thay đổi bằng ARC. Trong MRC nó gây ra biến được tham chiếu yếu, trong ARC nó không và __weak phải được sử dụng cho mục đích này.

biết thêm thông tin về chủ đề này có thể được tìm thấy ở đây: How do I avoid capturing self in blocks when implementing an API?

Sử dụng init thực hiện mới từ phiên bản cuối cùng và sử dụng __weak thay vì __block, cuối cùng gây ra các phương pháp dealloc được gọi là đúng.


Cuối cùng, đối với những người ghét phải mang theo mã di sản cũ, đây là một phiên bản hiện đại của dự án AVCam: https://github.com/Gabro/AVCam

Các tính năng:

  • rò rỉ bộ nhớ miễn phí
  • sử dụng ARC
  • Cú pháp Mục tiêu-C hiện đại
  • Giao diện người dùng nhỏ bản sửa lỗi cho iOS 7
+0

Xin chào Gabriele, tôi đã xem dự án AVCam của bạn. Bạn có thể thay đổi nhận xét 'tương thích ARC' thành 'độc quyền ARC'? Tôi đã thêm nó vào dự án không phải ARC của tôi và có một số lỗi biên dịch liên quan đến việc sử dụng chức năng độc quyền ARC. –

+0

@RedNightingale Tuyệt đối, sự lựa chọn khủng khiếp của các từ thực sự. Bằng cách này, bạn có thể bật ARC một cách có chọn lọc trên các tệp cụ thể ngay cả trong một dự án không phải ARC, nếu bạn muốn. Hy vọng nó giúp. –

+0

Tôi sẽ xem xét điều đó. Đã thử các phiên bản mới của mã Apple và chúng dường như cuối cùng hoạt động bình thường nên tôi sẽ quảng bá điều này để trở thành câu trả lời. –

16

Điều đầu tiên tôi đã làm là đăng nhập vào các phương thức dealloc của tất cả các tệp AVCam. Tôi nhanh chóng phát hiện ra rằng AVCamCaptureManager và AVCamRecorder đã không được deallocated khi AVCamViewController được. Tôi đã kiểm tra các cuộc gọi giữ lại và phát hành và chúng xuất hiện để cân bằng vì vậy tôi đặt một điểm ngắt trên [captureManager release] và phát hiện ra rằng nó có một điểm giữ lại 2 SAU bản phát hành (và vì thế thỏa thuận AVCamCaptureManager không được gọi).

Tiếp theo, tôi đã thực hiện quy trình tạo cho trình quản lý chụp và phát hiện ra rằng nó có số lần giữ lại là 3 ngay sau khi phương thức init được gọi.

Đẩy mạnh thông qua các phương pháp init và kiểm tra giữ lại đếm trên mỗi dòng tôi phát hiện ra hai dòng sau đây đã được cả hai incrementing giữ count:

[self setDeviceConnectedObserver=[notificationCenter addObserverForName:AVCaptureDeviceWasConnectedNotification object:nil queue:nil usingBlock:deviceConnectedBlock]]; 
[self setDeviceDisconnectedObserver=[notificationCenter addObserverForName:AVCaptureDeviceWasDisconnectedNotification object:nil queue:nil usingBlock:deviceDisconnectedBlock]]; 

Nhìn qua tôi thấy rằng các đối tác removeObserver là INSIDE phương pháp dealloc của AVCamCaptureManager (mà đã không được gọi) và do đó giữ lại đếm không bao giờ giảm xuống còn 0.

để khắc phục nó tôi đã tạo ra một removeObservers công phương pháp mới:

-(void)removeObservers { 
    NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; 
    [notificationCenter removeObserver:[self deviceConnectedObserver]]; 
    [notificationCenter removeObserver:[self deviceConnectedObserver]]; 
} 

và lấy cùng các dòng OUT của phương thức dealcam của AVCamCaptureManager.

Gọi [captureManager removeObservers]; và THEN gọi [captureManager release]; trong phương pháp dealloc AVCamViewController giảm thành công số lượng lưu giữ xuống 0.

Thử nghiệm với Trình giám sát hoạt động hiện có quy trình mediaserverd chỉ rung ở mức 5-17Mb và các điểm dừng bị dừng!

Hy vọng điều này sẽ giúp bất kỳ ai khác gặp sự cố này!

+1

Tốt hơn ... các vị thần SO hùng mạnh đã cho phép tôi trả lời câu hỏi của chính mình ngay bây giờ;) –

+0

Các vị thần SO hùng mạnh đã cho phép tôi nói lời cảm ơn bằng cách tặng +1 của tôi;) – sehe

+0

Mô tả hay. Tôi tin rằng chúng tôi đã gặp phải vấn đề tương tự này. –

2

Đã khắc phục sự cố này gần đây. Tôi thấy rằng vấn đề gốc thực sự là deviceConnectedBlock và deviceDisconnectedBlock đã ngầm ám chỉ đến bản thân, dẫn đến giữ lại các chu kỳ. Để sửa chữa nó, thay đổi tất cả các tài liệu tham khảo ivar trong các khối để sử dụng weakSelf.

Bằng cách này, bạn sẽ không cần phải nhớ gọi phương thức teardown một cách rõ ràng.

Hy vọng điều này sẽ giúp người khác.

REF: View controller dealloc not called when using NSNotificationCenter code block method with ARC

+0

Tôi đã có một tham chiếu đến tự trong khối.Tôi đã thay thế bằng weakSelf và hoàn nguyên về mã phát hành AVCAM 'bình thường'. CaptureManager vẫn không gọi dealloc. Bài viết bạn đã liên kết đề cập đến __weak cho tham chiếu tuy nhiên điều này chỉ áp dụng cho mã ARC (mà tôi hiện không sử dụng). Tôi cần phải sử dụng __block nhưng không hiểu đủ về 'khối' để có thể đưa ra giải pháp tương đương hoạt động. –