ProximityMonitoring может не работать должным образом

для моего приложения iOS я хочу реализовать функцию, в которой экран должен отключиться (например, когда вы отвечаете на телефонный звонок), когда устройство сталкивается. поэтому я начал с определения ориентации устройства:

//in my ViewDidLoad
    NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(self.rotated(_:)), name: UIDeviceOrientationDidChangeNotification, object: nil)

//called when the device changes orientation
    func rotated(notification: NSNotification){
        if UIDevice.currentDevice().orientation == UIDeviceOrientation.FaceDown{
            print("device = faced down")
        }else{
            print("device != faced down")
        }
    }

Когда устройство выключено, я позвонил

UIDevice.currentDevice().proximityMonitoringEnabled = true

еще

UIDevice.currentDevice().proximityMonitoringEnabled = false

проблема UIDeviceOrientationDidChangeNotification кажется немного запоздалой, поэтому, когда вызывается функция rotated(), устройство уже обращено вниз, и оказывается, что для proximityMonitoringEnabled = true отключить экран близость датчик не должен быть уже закрыт! Я уверен, что это ограничение Apple, но, возможно, кто-то там нашел решение или наткнулся на обходное решение! спасибо заранее.

Ответ 1

Подход:

Так как iOS не предоставляет перед изменением ориентации, мы не можем полагаться на 'UIDeviceOrientationDidChangeNotification'. Вместо этого мы можем использовать CoreMotion Framework и получить доступ к аппаратным гироскопам для обнаружения возможных ориентаций FaceDown и установить proximityMonitoringEnabled соответствующим образом.

Данные гироскопа:

Использование наблюдений гироскопа ниже значений может, возможно, определять ориентацию FaceDown.

let gyroData = (minX:-3.78, minY:-3.38, minZ:-5.33, maxX:3.29, maxY:4.94, maxZ:3.36)

Решение в Swift:

class ProximityViewController: UIViewController {

    let cmManager = CMMotionManager(), gyroData = (minX:-3.78, minY:-3.38, minZ:-5.33, maxX:3.29, maxY:4.94, maxZ:3.36)

    override func viewDidLoad() {
        super.viewDidLoad()

        //Using GyroMotion
        experimentCoreMotion()
    }

    //MARK: - Using Core Motion
    func experimentCoreMotion() {

        if cmManager.gyroAvailable {

            //Enable device orientation notification
            UIDevice.currentDevice().beginGeneratingDeviceOrientationNotifications()

            cmManager.gyroUpdateInterval = 0.1

            handleFaceDownOrientation()

        }

    }

    func handleFaceDownOrientation() {

        cmManager.startGyroUpdatesToQueue(NSOperationQueue.currentQueue()!, withHandler: { (data:CMGyroData?, error: NSError?) in

            if self.isGyroDataInRange(data!) {

                UIDevice.currentDevice().proximityMonitoringEnabled = (UIDevice.currentDevice().orientation == .FaceDown)

                if UIDevice.currentDevice().orientation == .FaceDown {  print("FaceDown detected") }
                else { print("Orientation is not facedown") }
            }
        })
    }

    func isGyroDataInRange(val: CMGyroData) -> Bool {
        return ((val.rotationRate.x > gyroData.minX && val.rotationRate.x < gyroData.maxX) &&
            (val.rotationRate.y > gyroData.minY && val.rotationRate.y < gyroData.maxY) &&
            (val.rotationRate.z > gyroData.minZ && val.rotationRate.z < gyroData.maxZ))
    }
}

Надеюсь, мое решение решает ваш запрос. Позвольте мне знать, что решение отлично работает для вашего требования.

Наблюдения за гироскопом и акселерометром:

Я экспериментировал с возможными значениями ориентации FaceDown с помощью гироскопа и акселерометра. IMO, данные гироскопа кажутся прекрасными, но они открыты для изучения других аппаратных датчиков для определения ориентации FaceDown.