我一直在阅读GOTW102,并且想知道为什么class VideoMediaViewController: NSViewController {
weak var mainView : DTMainViewController?
@IBOutlet weak var aVPlayerView: AVPlayerView!
var url:NSURL?{
didSet{
// this is the setter
}
}
var observer:AnyObject?
var player:AVPlayer?
var videoOutput:AVPlayerItemVideoOutput?
var ciContext:CIContext?
var loadStatus:NSNumber?
override func viewDidLoad() {
aVPlayerView.controlsStyle = AVPlayerViewControlsStyle.None
}
func loadMedia() {
unloadMedia()
//Create AVPlayerItem
player = AVPlayer.playerWithURL(url) as? AVPlayer
//Create VideoOutput
videoOutput = AVPlayerItemVideoOutput(pixelBufferAttributes: [kCVPixelBufferPixelFormatTypeKey:kCVPixelFormatType_32ARGB])
//Get notifications for status
player?.addObserver(self, forKeyPath: "status", options:.New, context: nil)
//looping logic start
player?.actionAtItemEnd = AVPlayerActionAtItemEnd.None
NSNotificationCenter.defaultCenter().addObserver(self,
selector: "playerItemDidReachEnd:",
name: AVPlayerItemDidPlayToEndTimeNotification,
object: player?.currentItem)
//looping logic end
observer = player?.addPeriodicTimeObserverForInterval(CMTimeMake(150, 600),
queue: dispatch_get_main_queue(),
usingBlock: {[unowned self](CMTime) in
self.updateSliderProgress()
self.updateStartAndEndTimes()
})
//Set videoOutput to player
player?.currentItem.addOutput(videoOutput)
aVPlayerView.player = player
aVPlayerView.player.play()
}
func playerItemDidReachEnd(notification: NSNotification) {
let aVPlayerItem: AVPlayerItem = notification.object as! AVPlayerItem
aVPlayerItem.seekToTime(kCMTimeZero)
}
func scrubberSliderChanged(sender: AnyObject){
var duration:Float64 = CMTimeGetSeconds(player!.currentItem.duration)
var sliderValue:Float64 = Float64(mainView!.scrubberSlider!.floatValue)
var seekToTime = CMTimeMakeWithSeconds(((sliderValue * duration)/100.00), 1)
player?.seekToTime(seekToTime, completionHandler: { (Bool) -> Void in
})
}
func secondsToHoursMinutesSeconds (seconds : Int) -> (Int, Int, Int) {
return (seconds / 3600, (seconds % 3600) / 60, (seconds % 3600) % 60)
}
func getStringFromHoursMinutesSeconds(h:Int, m:Int, s:Int) -> (String){
let formatter = NSNumberFormatter()
formatter.minimumIntegerDigits = 2
let hours = formatter.stringFromNumber(h) //"00"
let minutes = formatter.stringFromNumber(m) //"01"
let seconds = formatter.stringFromNumber(s) //"10"
var timerString = hours! + ":" + minutes! + ":" + seconds!
return timerString
}
func updateStartAndEndTimes(){
var time = CMTimeGetSeconds(player!.currentItem.duration) - CMTimeGetSeconds(player!.currentItem.currentTime())
var (hours,minutes,seconds) = secondsToHoursMinutesSeconds(Int(time))
let timeRemainingString = getStringFromHoursMinutesSeconds(hours, m: minutes, s: seconds)
mainView!.videoTimeRemaing.stringValue = timeRemainingString
time = CMTimeGetSeconds(player!.currentItem.currentTime())
(hours,minutes,seconds) = secondsToHoursMinutesSeconds(Int(time))
let timePassedString = getStringFromHoursMinutesSeconds(hours, m: minutes, s: seconds)
mainView?.videoTimePassed.stringValue = timePassedString
// mainView!.videoTimeRemaing.stringValue = "\(CMTimeGetSeconds(player!.currentItem.duration) - CMTimeGetSeconds(player!.currentItem.currentTime()))!"
// mainView?.videoTimePassed.stringValue = "\(CMTimeGetSeconds(player!.currentItem.currentTime()))!"
}
func updateSliderProgress(){
var currentTime = CMTimeGetSeconds(player!.currentItem.currentTime())
var duration = CMTimeGetSeconds(player!.currentItem.duration)
var progress = currentTime/duration*100
mainView!.scrubberSlider!.doubleValue = progress
}
func unloadMedia() {
//Cancel Prerolls and Notifications
player?.cancelPendingPrerolls
player?.removeTimeObserver(observer)
player?.removeObserver(self, forKeyPath: "status")
NSNotificationCenter.defaultCenter().removeObserver(self, name: AVPlayerItemDidPlayToEndTimeNotification, object: nil)
//dispose of assets and players, etc
//...
}
override func viewWillDisappear() {
unloadMedia()
}
//Get Status updates and log success or failure
override func observeValueForKeyPath(keyPath: String, ofObject object: AnyObject, change: [NSObject : AnyObject], context: UnsafeMutablePointer<Void>) {
if ( (object as! NSObject) == player && keyPath == "status") {
if (player?.status == .ReadyToPlay) {
NSLog("Status - Loaded")
} else if (player?.status == .Failed) {
NSLog("Status - Failed")
} else {
NSLog("Status - Unknown")
}
}
}
比其他情况更安全,或详细说明为什么make_unique
比f(new T(...))
更安全。
博客中的f(new T1(...), new T2(...))
实施内容如下:
make_unique
现在我想知道template<typename T, typename ...Args>
std::unique_ptr<T> make_unique( Args&& ...args )
{
return std::unique_ptr<T>( new T( std::forward<Args>(args)... ) );
}
是否一般异常安全(无泄漏),或者f(new T(...))
是否只是异常安全,因为{{1}的构造函数增加了知识不扔? (根据我的理解,无论如何,新建的make_unique
都会被泄露。
答案 0 :(得分:10)
原因是在函数调用或类似函数中,参数不会引发序列点(不是“之前排序”)。例如:
do_work(unique_ptr<A>(new A), unique_ptr<B>(new B));
允许编译器生成如下代码:
new A
new B
//可能会扔!unique_ptr<A>
unique_ptr<B>
do_work
如果new B
抛弃,那么您已泄露了A
,因为没有构建unique_ptr
。
将unique_ptr
构造放入其自己的函数中可以消除此问题,因为不允许编译器同时执行函数体(因此“new”和“construct unique_ptr
步骤需要一起完成)。
即,给定:
do_work(make_unique<A>(), make_unique<B>())
编译器必须生成如下代码:
make_unique<A>
make_unique<B>
do_work
或
make_unique<B>
make_unique<A>
do_work
在新的对象浮动的情况下进行泄漏而不能拥有unique_ptr
。