簡體   English   中英

iOS 9中的強制視圖控制器方向

[英]Force View Controller Orientation in iOS 9

我正在制作一個攝影應用程序,允許以肖像或風景拍攝照片。 由於項目的要求,我不能讓設備方向自動旋轉,但確實需要支持旋轉。

使用以下定位方法時:

override func shouldAutorotate() -> Bool {
    return true
}

override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
    if self.orientation == .Landscape {
        return UIInterfaceOrientationMask.LandscapeRight
    } else {
        return UIInterfaceOrientationMask.Portrait
    }
}

override func preferredInterfaceOrientationForPresentation() -> UIInterfaceOrientation {
    if self.orientation == .Landscape {
        return UIInterfaceOrientation.LandscapeRight
    } else {
        return UIInterfaceOrientation.Portrait
    }
}

我可以在啟動時正確設置旋轉。 通過更改方向值並調用UIViewController.attemptRotationToDeviceOrientation()我能夠支持旋轉到新的所需接口。 但是,此旋轉僅在用戶實際移動其設備時發生。 我需要它自動發生。

我可以調用: UIDevice.currentDevice().setValue(targetOrientation.rawValue, forKey: "orientation")來強制更改,但這會導致其他副作用,因為UIDevice.currentDevice().orientation只返回從該點開始的setValue上。 (而且非常臟)

有什么我想念的嗎? 我已經研究過關閉並啟動一個新的視圖控制器,但這有其他問題,例如在解除並立即呈現新的視圖控制器時出現持續的UI故障。

編輯:

以下方法對我不起作用:

編輯2:

對潛在解決方案的思考

  1. 直接設置方向(使用setValue )並處理iOS 9上出現的所有副作用(不可接受)

  2. 我可以使用當前的解決方案並指示用戶需要旋轉設備。 設備物理旋轉后,UI會旋轉,然后正確鎖定到位。 (差的UI)

  3. 我可以找到一種解決方案,強制刷新方向並在沒有物理操作的情況下旋轉。 (我在問什么,並尋找)

  4. 手工完成所有工作。 我可以縱向或橫向鎖定界面,並手動旋轉和調整容器視圖的大小。 這是“臟”的,因為它放棄了所有大小類自動布局功能,並導致更重的代碼。 我試圖避免這種情況。

我以前遇到過這個問題,我自己。 我能夠使用簡單的解決方法(和GPUImage )來解決它。 我的代碼在Objective-C中,但我確定你將它轉換為Swift沒有問題。

我首先將項目支持的旋轉設置為我希望支持的所有內容,然后覆蓋相同的UIViewController方法:

-(BOOL)shouldAutorotate { 
    return TRUE; 
}

-(NSUInteger)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskPortrait;
}

這允許設備旋轉但在縱向模式下將保持不變。 然后開始觀察設備旋轉:

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(adjustForRotation:)
                                             name:UIDeviceOrientationDidChangeNotification
                                           object:nil];

如果設備處於縱向模式或橫向,則更新UI:

-(void)adjustForRotation:(NSNotification*)notification
{
    UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];

    switch (orientation) {
        case UIDeviceOrientationLandscapeLeft:
        {
            // UPDATE UI
        }
            break;
        case UIDeviceOrientationLandscapeRight:
        {
            // UPDATE UI
        }
            break;
        default: // All other orientations - Portrait, Upside Down, Unknown
        {
            // UPDATE UI
        }
            break;
    }
} 

最后,GPUImage根據設備的方向渲染圖像。

[_gpuImageStillCamera capturePhotoAsImageProcessedUpToFilter:last_f
                                              withCompletionHandler:^(UIImage *processedImage, NSError *error) { 
    // Process the processedImage 
}];

我能夠在這個答案的幫助下找到解決方案: 程序化界面方向改變不適用於iOS

我的基本定位邏輯如下:

// Local variable to tracking allowed orientation. I have specific landscape and
// portrait targets and did not want to remember which I was supporting
enum MyOrientations {
    case Landscape
    case Portrait
}
var orientation: MyOrientations = .Landscape

// MARK: - Orientation Methods

override func shouldAutorotate() -> Bool {
    return true

}

override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
    if self.orientation == .Landscape {
        return UIInterfaceOrientationMask.LandscapeRight
    } else {
        return UIInterfaceOrientationMask.Portrait
    }
}

override func preferredInterfaceOrientationForPresentation() -> UIInterfaceOrientation {
    if self.orientation == .Landscape {
        return UIInterfaceOrientation.LandscapeRight
    } else {
        return UIInterfaceOrientation.Portrait
    }
}

// Called on region and delegate setters
func refreshOrientation() {
    if let newOrientation = self.delegate?.getOrientation() {
        self.orientation = newOrientation
    }
}

然后,當我想刷新方向時,我會執行以下操作:

// Correct Orientation
let oldOrientation = self.orientation
self.refreshOrientation()
if self.orientation != oldOrientation {
    dispatch_async(dispatch_get_main_queue(), {
        self.orientationRefreshing = true

        let vc = UIViewController()

        UIViewController.attemptRotationToDeviceOrientation()

        self.presentViewController(vc, animated: false, completion: nil)

        UIView.animateWithDuration(0.3, animations: {
            vc.dismissViewControllerAnimated(false, completion: nil)
        })
    })
}

此解決方案具有導致view[Will/Did]Appearview[Will/Did]Disappear的副作用。 我正在使用本地orientationRefreshing變量來管理再次調用這些方法的哪些方面。

所以我查看了UIDevice的私有頭文件,看起來有兩個setter和兩個屬性定義,用於定位,目前令人困惑。 這就是我所看到的......

@property (nonatomic) int orientation;
@property (nonatomic, readonly) int orientation; 

- (void)setOrientation:(int)arg1;
- (void)setOrientation:(int)arg1 animated:(BOOL)arg2;

所以,當我看到你使用了setValue:forKey: ,我想看到有一個合成的setter和getter,老實說,不是100%確定哪一個被設置,哪一個被設備承認..我試圖在一個演示應用程序中使用setValue:forKey:無濟於事,但是從我過去的一個應用程序中使用了這個技巧,它立刻就完成了這個技巧:)我希望這會有所幫助

UIDevice.currentDevice().performSelector(Selector("setOrientation:"), withObject: UIInterfaceOrientation.Portrait.rawValue)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM