關於UIInterfaceOrientation的一個bug

流火行者發表於2015-03-09

在ios中獲取裝置當前方向的列舉有UIInterfaceOrientation和UIDeviceOrientation

,前者包含列舉

Unknown//未知

Portrait//螢幕豎直,home鍵在下面

PortraitUpsideDown//螢幕豎直,home鍵在上面

LandscapeLeft//螢幕水平,home鍵在左邊

LandscapeRight//螢幕水平,home鍵在右邊

後者的裝置方向列舉為:

Unknown//未知

Portrait//螢幕豎直,home鍵在下面

PortraitUpsideDown//螢幕豎直,home鍵在上面

LandscapeLeft//螢幕水平,home鍵在左邊

LandscapeRight //螢幕水平,home鍵在右邊

FaceUp //螢幕向上擺放在桌面

FaceDown//螢幕向下擺放在桌面

兩者都包含了相關方向,一般情況下使用前者的四個方向即可,但是在使用前者UIInterfaceOrientation的時候,發現存在一個bug。如,我要通過監聽來獲得螢幕的當前方向,程式碼是這樣的

1 NSNotificationCenter.defaultCenter().addObserver(self, selector: "orientChange:", name: UIDeviceOrientationDidChangeNotification, object: nil)
    func orientChange(noti:NSNotification){
        switch  self.interfaceOrientation{
        case .LandscapeLeft:
            println("LandscapeLeft")
        case .LandscapeRight:
            println("LandscapeRight")
        case .Portrait:
            println("Portrait")
        case .PortraitUpsideDown:
            println("PortraitUpsideDown")
        case .Unknown:
            println("Unknown")
        default:
            println("default")
        }

    }

此時螢幕旋轉,控制檯就會列印出當前的裝置方向,一般情況下,列印的都是正確的,但是如果旋轉的過快,比如我的旋轉方向順序為

Portrait->LandscapeRight->PortraitUpsideDown
控制檯列印的順序應該是
Portrait->LandscapeRight->PortraitUpsideDown

但是裝置在旋轉過快的時候列印的結果是

Portrait->LandscapeRight->LandscapeRight
這會導致UI變的不可接受。雖然這種情況一般不出現,但是如果被使用者發現,卻是不可饒恕的錯誤
於是我拿UIDeviceOrientation進行了測試,
UIDeviceOrientation不管旋轉的速度多快,都能很好的識別出裝置的真實方向。
所以由此得出建議,在能使用
UIDeviceOrientation的情況下,不要去使用UIInterfaceOrientation

是不是就完了呢?就這一個bug嗎

不是的,還有一個問題
不管在使用
UIDeviceOrientation 和UIInterfaceOrientation,如果旋轉速度過快,還會導致一個致命的問題。那就是裝置的長寬取出來是錯誤的

我使用的ipad是1024X768,這個可以通過view.bounds得到也可以通過UIScreen.mainScreen().bounds得到
我同樣是從
Portrait->LandscapeRight->PortraitUpsideDown,我在每一個方向下列印出獲得的螢幕長寬,
理論上應該是(768,1024)->(1024,768)->(768,1024),但是旋轉過快會導致這樣的結果,你可能已經猜到:(768,1024)->(1024,768)->(1024,768)

也就是說我們可以得到正確的螢幕方向,但是有時候卻得不到正確的螢幕長寬,為此我想到的辦法是手動去設定螢幕的長寬。因為螢幕的尺寸的大小不會變,所以不管是長還是寬,數字大的肯定是裝置橫放時候的寬度,較小的是高度,於是:
    //獲取當前狀態實際的螢幕尺寸
    func getRealScreenSize(orientation:UIDeviceOrientation)->CGSize{
        var size = UIScreen.mainScreen().bounds.size
        var w = size.width,h = size.height
        if size.width < size.height{
            w = size.height
            h = size.width
        }
        switch orientation{
        case .LandscapeLeft,.LandscapeRight:
            size = CGSize(width: w, height: h)
  
        case .Portrait,.PortraitUpsideDown:
            size = CGSize(width: h, height: w)
        default:
            println("a")
        }
        return size
    }

我用getRealScreenSize方法來替代view.bounds或UIScreen.mainScreen().bounds

通過這種方式便解決了以上的bug。可能還有很方便的底層api能做到,暫時我還沒有發現

 

 


 




相關文章