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
thanx này cho hỏi! – headkit