在iOS 8中不推荐使用didRotateFromInterfaceOrientation

时间:2016-01-13 18:45:28

标签: ios objective-c ios8

自iOS 8.0起,函数didRotateFromInterfaceOrientation已弃用,我现在不知道如何正确更改AVCaptureVideoPreviewLayer的方向。

根据"interfaceOrientation" is deprecated in iOS 8, How to change this method Objective C,我有以下工作代码来根据AVCaptureVideoOrientation获取statusBarOrientation

- (AVCaptureVideoOrientation)getOrientation {
    // Translate the orientation
    switch ([[UIApplication sharedApplication] statusBarOrientation]) {
        case UIInterfaceOrientationPortrait:
            return AVCaptureVideoOrientationPortrait;
        case UIInterfaceOrientationPortraitUpsideDown:
            return AVCaptureVideoOrientationPortraitUpsideDown;
        case UIInterfaceOrientationLandscapeLeft:
            return AVCaptureVideoOrientationLandscapeLeft;
        case UIInterfaceOrientationLandscapeRight:
            return AVCaptureVideoOrientationLandscapeRight;
        default:
            return AVCaptureVideoOrientationPortrait;
    }
}

当方向改变时,我需要调用以下函数:

[self.videoPreviewLayer.connection setVideoOrientation:[self getOrientation]];

但我不知道在哪里放置它。

尝试1

由于didRotateFromInterfaceOrientation已被弃用且Apple建议使用viewWillTransitionToSize:withTransitionCoordinator:,因此尝试这似乎很自然:

- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
{
    [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
    [coordinator animateAlongsideTransition:nil completion:^(id<UIViewControllerTransitionCoordinatorContext>  _Nonnull context) {
        [self.videoPreviewLayer.connection setVideoOrientation:[self getOrientation]];
    }];
}

但是如果正在呈现UIViewController,则不会调用此函数(似乎是基于"viewWillTransitionToSize:" not called in iOS 9 when the view controller is presented modally的已知错误)。即使解决了这个问题,也存在另一个问题:方向更改 等同于大小更改。例如,如果视图显示UIModalPresentationFormSheet如下,

SecondViewController *vc = [[SecondViewController alloc] init];
vc.view.backgroundColor = [UIColor greenColor];
vc.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentViewController:vc animated:true completion:nil];

在iPad的横向和纵向模式下,呈现的视图大小相同:

因此,我不能简单地使用viewWillTransitionToSize

尝试2

我注意到UIDeviceOrientationDidChangeNotification未被弃用。大!我尝试注册一个通知:

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    // Some other code to set up the preview layer 
    // ...

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(deviceOrientationDidChange:)
                                                 name:UIDeviceOrientationDidChangeNotification
                                               object:nil];
    [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
}

- (void)viewWillDisappear:(BOOL)animated
{
    [[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIDeviceOrientationDidChangeNotification object:nil];
}

- (void)deviceOrientationDidChange:(NSNotification *)notification {
    [self.videoPreviewLayer.connection setVideoOrientation:[self getOrientation]];
}

几乎正在工作,它已经关闭了!问题是,当我获得设备方向更改通知时,可能会启动旋转视图的动画,也可能不会。换句话说,如果设备已经向上旋转但动画仍处于待处理状态,则返回值[[UIApplication sharedApplication] statusBarOrientation]可能不正确。

我不知道还有什么可以尝试:(有什么想法吗?

1 个答案:

答案 0 :(得分:2)

以下应该能够在swift 2.1中正确处理视频预览的方向:

import UIKit
import AVFoundation

class AgnesAudioViewController: UIViewController {

var audioPlayer = AVAudioPlayer()
var toggleState = 1
@IBOutlet var slider: UISlider!

@IBAction func done(sender: AnyObject) {
    dismissViewControllerAnimated(true, completion: nil)
}

@IBAction func play(sender: AnyObject) {
    audioPlayer.play()
}

@IBAction func pause(sender: AnyObject) {
    audioPlayer.pause()
}

@IBAction func stop(sender: AnyObject) {
    audioPlayer.stop()
}

@IBAction func scrubAudio(sender: AnyObject) {
    audioPlayer.stop()
    audioPlayer.currentTime = NSTimeInterval(slider.value)
    audioPlayer.prepareToPlay()
    audioPlayer.play()
}

@IBAction func playPauseButton(sender: AnyObject) {
    var playBtn = sender as! UIButton
    if toggleState == 1 {
        audioPlayer.play()
        toggleState = 2
        playBtn.setImage(UIImage(named:"pause.png"),forState:UIControlState.Normal)
    } else {
        audioPlayer.pause()
        toggleState = 1
        playBtn.setImage(UIImage(named:"play.png"),forState:UIControlState.Normal)
    }
}

override func viewDidLoad() {
    super.viewDidLoad()

    var timer = NSTimer.scheduledTimerWithTimeInterval(0.01, target: self, selector: Selector("updateSlider"), userInfo: nil, repeats: true)

    slider.maximumValue = Float(audioPlayer.duration)

    let pathString = NSBundle.mainBundle().pathForResource("agnes", ofType: "mp2")

    if let pathString = pathString {

        let pathURL = NSURL(fileURLWithPath: pathString)

        do {

            try audioPlayer = AVAudioPlayer(contentsOfURL: pathURL)

        } catch {

            print("error")
        }


    }

}

func updateSlider() {
    slider.value = Float(audioPlayer.currentTime)
}
}