2012-04-04 33 views
12

Tôi đang cố tạo ứng dụng phát video từ một tệp bằng cách sử dụng AVFoundation. Các video được hiển thị trong một chế độ xem được truy cập bằng cách nhấn vào hàng trong chế độ xem bảng gốc. Ứng dụng thực sự sẽ có video cho mỗi hàng, nhưng hiện tại tôi chỉ sử dụng một video để thử nghiệm.AVPlayer bị treo sau nhiều lần phát lại-

Khi chạy trên trình mô phỏng ứng dụng là ok, nhưng khi chạy trên thiết bị (theo ios 5.1) video phát được khoảng 5 lần, sau đó gặp sự cố không thể đoán trước theo nhiều cách khác nhau. Phổ biến nhất, lượt xem video sẽ tải nhưng bản thân video không phát, nhưng đôi khi Tôi nhận được EXC_BAD_ACCESS trên chuỗi coremedia.remote, phàn nàn về các đối tượng được phân bổ không có hồ bơi autorelease tại chỗ. Tôi đã thêm một khối @autoreleasepool gói mã khởi chạy AVPlayer, nhưng điều này dường như không giúp ích gì.

Tôi tự hỏi liệu điều gì đang xảy ra là GCD đang tạo nhiều chuỗi trên hàng đợi chính để phát các mục, nhưng chúng không chấm dứt.

Vì vậy, câu hỏi chính là làm cách nào để xóa các chuỗi GCD thừa mà AVPlayer đang chạy trên nếu người dùng nhấn nút quay lại trong chế độ xem video Theo như tôi có thể đã làm theo mã mẫu được cung cấp trong Tài liệu AVFoundation của Apple here Tôi đã thêm một số ghi nhật ký và (như đã đề cập ở trên) một khối @autoreleasepool bên trong một trong các khối GCD- ngoài việc tôi chưa thay đổi mã.

Phương pháp viewDidLoad là như sau:

-(void)viewDidLoad{ 
[super viewDidLoad]; 

NSURL *fileURL = [[NSBundle mainBundle] URLForResource:@"TestLapCar2Vid" withExtension:@"m4v"]; 
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:fileURL options:nil]; 
NSString *tracksKey = @"tracks"; 

[asset loadValuesAsynchronouslyForKeys:[NSArray arrayWithObject:tracksKey] completionHandler: 
^{ 
    dispatch_async(dispatch_get_main_queue(), 
    ^{ 
     @autoreleasepool { 
     NSError *error = nil; 
      AVKeyValueStatus status = [asset statusOfValueForKey:tracksKey error:&error]; 

      if(status == AVKeyValueStatusLoaded){ 
       avPlayerItem = [AVPlayerItem playerItemWithAsset:asset]; 
       [avPlayerItem addObserver:self forKeyPath:@"status" 
            options:0 context:&ItemStatusContext]; 

       [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(playerItemDidReachEnd:) 
                  name:AVPlayerItemDidPlayToEndTimeNotification object:avPlayerItem]; 

       avPlayer = [AVPlayer playerWithPlayerItem:avPlayerItem]; 
       [videoView setPlayer:avPlayer]; 
       NSLog(@"Asset loaded"); 
       [avPlayer play]; 
      } 
      else{ 
       NSLog(@"The asset's tracks were not loaded"); 
      } 

     } 
    }); 
}];  

}

Phương pháp viewWillDisappear là:

-(void)viewWillDisappear:(BOOL)animated{ 
NSLog(@"view will disappear called"); 
[super viewWillDisappear:animated]; 
dispatch_async(dispatch_get_main_queue(), 
    ^{ 
     [avPlayer pause]; 
     [avPlayerItem removeObserver:self forKeyPath:@"status"]; 
     [[NSNotificationCenter defaultCenter]removeObserver:self]; 
     NSLog(@"Race timeline nav controller has %d sub controllers",self.navigationController.childViewControllers.count); 
     avPlayerItem = nil; 
     avPlayer = nil; 
     videoView = nil; 
     dataStore = nil; 
     pkReader = nil; 
     receivedData = nil; 
     revDial = nil; 
     speedDial = nil; 
     mapView = nil; 
     throttle = nil; 
     NSLog(@"releasing stuff"); 
    }); 

}

Tôi đã đấu tranh với điều này đối với hầu hết hôm nay- bất kỳ sự giúp đỡ nào sẽ được biết ơn một cách biết ơn

+0

thanx này cho hỏi! – headkit

Trả lời

14

Bạn nên xóa khỏi superview trước vì nó sẽ giảm số lần giữ lại bằng một và ARC sẽ xử lý việc đền bù cho bạn.

như

[videoView removeFromSuperview]; 
[self setVideoView:nil]; 
+0

CẢM ƠN BẠN! Điều này làm việc hoàn hảo cho tôi. – theDuncs

+0

Cảm ơn bạn rất nhiều!Tôi đã đấu tranh trong hơn 1 tuần với lỗi nhỏ này !! Bạn đã cứu ngày của tôi! – Anthony

+0

điều cần biết - Tôi bị điên với ARC ... – headkit

5

Có thể bạn rời khỏi videoView được giữ lại ở một số nơi? Bởi vì nếu bạn làm như vậy, avPlayerItem và avPlayer của bạn vẫn hoạt động và theo chủ đề this bạn đã đạt đến giới hạn iOS cho "hiển thị đường dẫn" với 4 video nằm trong bộ nhớ.

Hãy nhớ rằng cài đặt var thành 0 không thực sự giải phóng đối tượng bên dưới. Vì vậy,

videoView = nil; 

của bạn có thể không có hiệu lực.

+0

thú vị khi biết về giới hạn iOS cho "hiển thị đường dẫn" với 4 video lưu lại trong bộ nhớ! – headkit

+0

Chúng ta cần thêm dòng này ở đâu? Tôi đang thêm nó tại 'viewDidLoad' nhưng bây giờ nó không hiển thị video – CGR

+1

@CGR có thể là khi bạn đóng bạn xem bộ điều khiển với video? – faviomob

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