I was getting a lot of crash reports with deallocated AVPlayerItem's while a KVO was still active. It was hard to manually remove the KVO when the AVPlayerItem was randomly deallocated from inside a UITableViewCell.
ACRObservingPlayerItem is a simple wrapper class for AVPlayerItem which handles the observing of some common playback events and safely releases the KVO on deallocation.
Install with CocoaPods
pod "ACRObservingPlayerItem"
Or copy the .m and .h files into your project.
Import the header file in your desired view.
#import "ACRObservingPlayerItem.h"
Add the delegate to your class/controller:
@interface YourViewController () <ACRObservingPlayerItemDelegate>
@end
Then implement the desired delegate methods (all optional):
- (void)playerItemReachedEnd;
- (void)playerItemStalled;
- (void)playerItemReadyToPlay;
- (void)playerItemPlayFailed;
- (void)playerItemRemovedObservation;
Create the player item and assign the delegate:
ACRObservingPlayerItem *playerItem = [[ACRObservingPlayerItem alloc] initWithAsset:self.videoAsset];
playerItem.delegate = self;
If the object is deallocated/deinit it will attempt to call playerItemRemovedObservation
on the delegate.
The entire point of the object is to automatically release the KVO when deallocated/deinit but to be safe you should nil out the delegate when your view or delegate is removed:
- (void)dealloc {
playerItem.delegate = nil;
// or
playerItem = nil;
}
Version 1.1 was changed to support Swift through an Obj-C Bridging-Header file. Read this excellent tutorial to get started with Swift and CocoaPods: CocoaPods with Swift
In your bridging header put:
#import "ACRObservingPlayerItem.h"
Full Swift example:
import UIKit
import AVFoundation
class VideoPlayerController: UIViewController, ACRObservingPlayerItemDelegate {
var playerItem : ACRObservingPlayerItem?
init {
self.playerItem = ACRObservingPlayerItem(asset: self.video)
self.playerItem!.delegate = self
}
deinit {
playerItem?.delegate = nil
// or
playerItem = nil
}
// MARK: ACRObservingPlayerItemDelegate
func playerItemReachedEnd() {
// rewind and play?
}
func playerItemReadyToPlay() {
// play!
}
func playerItemPlayFailed() { }
func playerItemStalled() { }
func playerItemRemovedObservation() { }
}
MIT
There may be some. I wrote this late at night but it seems to be doing the trick for me.
Submit an issue or pull-request. Please. I don't like doing bug fixes over email or Github messages.
Let me know if you find this library helpful. I'm @acr on Twitter or ping me here on Github.