最新消息:20210816 当前crifan.com域名已被污染,为防止失联,请关注(页面右下角的)公众号

【已解决】iOS中屏幕方向警告:Cannot convert value of type UIDeviceOrientation to type UIInterfaceOrientation in coercion

iOS crifan 2498浏览 0评论

之前已经写了关于iOS中屏幕方向的函数:

import UIKit
extension UIDevice {
    static func rotateTo(newDirection:UIInterfaceOrientation) {
        self.current.setValue(newDirection.rawValue, forKey: “orientation”)
    }
    static func rotateToIfNeed(newDirection:UIInterfaceOrientation) {
        if !self.isOrientation(toCmpOrientation: newDirection) {
            self.rotateTo(newDirection: newDirection)
        }
    }
    static func isOrientation(toCmpOrientation:UIInterfaceOrientation) -> Bool {
        return self.current.orientation.rawValue == toCmpOrientation.rawValue
    }
}

但是在调试期间,用其他函数传入之前的设备方向时:

                let reportDetailsVC = ReportDetailsViewController(url: url as! String, title:titleC, prevOrientation: UIDevice.current.orientation)

结果报错:

ReportViewController.swift:111:132: Cannot convert value of type ‘UIDeviceOrientation’ to type ‘UIInterfaceOrientation’ in coercion

-》

然后才注意到自己之前写的:

return self.current.orientation.rawValue == toCmpOrientation.rawValue

其实好像不对:

self.current.orientation是UIDeviceOrientation

而toCmpOrientation是UIInterfaceOrientation

两个不是一个类型

定义分别是:

public enum UIDeviceOrientation : Int {
    case unknown
    case portrait // Device oriented vertically, home button on the bottom
    case portraitUpsideDown // Device oriented vertically, home button on the top
    case landscapeLeft // Device oriented horizontally, home button on the right
    case landscapeRight // Device oriented horizontally, home button on the left
    case faceUp // Device oriented flat, face up
    case faceDown // Device oriented flat, face down
}

// Note that UIInterfaceOrientationLandscapeLeft is equal to UIDeviceOrientationLandscapeRight (and vice versa).
// This is because rotating the device to the left requires rotating the content to the right.
public enum UIInterfaceOrientation : Int {
    case unknown
    case portrait
    case portraitUpsideDown
    case landscapeLeft
    case landscapeRight
}

很明显是:

UIDeviceOrientation和UIInterfaceOrientation的基本的定义是一样的

UIDeviceOrientation比UIInterfaceOrientation多了两个faceUp和faceDown

所以:

如果把UIInterfaceOrientation的rawValue强制转换为UIDeviceOrientation则是行得通的

反过来就不行。

-》所以刚以为:

return self.current.orientation.rawValue == toCmpOrientation.rawValue

是有问题的,实际上是可行的。至少是可以达到此处的基本目的的:判断设备方向是否一致。

而对于此处,设置设备方向用代码:

    static func rotateTo(newDirection:UIInterfaceOrientation) {

        self.current.setValue(newDirection.rawValue, forKey: “orientation”)

    }

其中用的是UIInterfaceOrientation,而不是UIDeviceOrientation,的诡异之处

ios UIDevice set  Orientation

ios – How do I programmatically set device orientation in iOS7? – Stack Overflow

中提到了:

// Set device orientation
// Important:
// • Passing a UIDeviceOrientation here doesn’t work, but passing a UIInterfaceOrientation does
// • This is a hack, and could stop working at any moment
UIDevice.current.setValue(interfaceOrientation.rawValue, forKey: “orientation”)

iOS屏幕旋转学习笔记 – 王中周的技术博客

中的“②系统横竖屏开关关闭时

如果关闭了系统的横竖屏切换开关,即系统层级只允许竖屏时,再通过上述方式获取到的设备方向将永远是UIDeviceOrientationUnknown。可以通过Core Motion中的CMMotionManager来获取当前设备方向。”

需要后续注意是否有此问题。

【总结】

所以此处暂时可以用:

                let prevInterfaceOrientation:UIInterfaceOrientation = UIInterfaceOrientation(rawValue: UIDevice.current.orientation.rawValue)!

去实现,从UIDeviceOrientation强制转换为UIInterfaceOrientation

当前也要确保前提是:此处UIDeviceOrientation不会出现faceUp和faceDown

否则转换是会出错的。

这样的话,就可以继续用之前的:

//
//  CrifanDevice.swift
//  Crifan Li
//  Updated: 2017/11/09
//
import UIKit
extension UIDevice {
    static func rotateTo(newDirection:UIInterfaceOrientation) {
        self.current.setValue(newDirection.rawValue, forKey: “orientation”)
    }
    static func rotateToIfNeed(newDirection:UIInterfaceOrientation) {
        if !self.isOrientation(toCmpOrientation: newDirection) {
            self.rotateTo(newDirection: newDirection)
        }
    }
    static func isOrientation(toCmpOrientation:UIInterfaceOrientation) -> Bool {
        //Note:
        // self.current.orientation is UIDeviceOrientation
        // toCmpOrientation is UIInterfaceOrientation
        // but first 5 type: unknown/portrait/portraitUpsideDown/landscapeLeft/landscapeRight
        // of enum value is equal
        return self.current.orientation.rawValue == toCmpOrientation.rawValue
    }
}

了,调用举例:

let DeviceDirectionAppDefault = UIInterfaceOrientation.portrait
let DeviceDirectionReportDetail = UIInterfaceOrientation.landscapeLeft
UIDevice.rotateToIfNeed(newDirection: DeviceDirectionReportDetail)

完整库函数请参考:

https://github.com/crifan/crifanLib/blob/master/swift/Device/CrifanDevice.swift

转载请注明:在路上 » 【已解决】iOS中屏幕方向警告:Cannot convert value of type UIDeviceOrientation to type UIInterfaceOrientation in coercion

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
85 queries in 0.167 seconds, using 22.11MB memory