From ec21dc711fad3e1b339f54c3b34d089c193b3632 Mon Sep 17 00:00:00 2001 From: duguyihou Date: Sun, 17 Mar 2024 16:04:05 +1100 Subject: [PATCH] 5 refactor (#6) * refactor: extension * refactor: withLock --- ios/NeoOrientation.swift | 157 ++++++++------------ ios/UIDeviceOrientation+Extensions.swift | 20 +++ ios/UIInterfaceOrientation+Extensions.swift | 16 ++ 3 files changed, 97 insertions(+), 96 deletions(-) create mode 100644 ios/UIDeviceOrientation+Extensions.swift create mode 100644 ios/UIInterfaceOrientation+Extensions.swift diff --git a/ios/NeoOrientation.swift b/ios/NeoOrientation.swift index d3a58b4..9aada20 100644 --- a/ios/NeoOrientation.swift +++ b/ios/NeoOrientation.swift @@ -9,28 +9,28 @@ class NeoOrientation: RCTEventEmitter { } private var lastOrientation: UIInterfaceOrientation? private var lastDeviceOrientation: UIDeviceOrientation? - private var isLocking = false + private let lock: os_unfair_lock_t = .allocate(capacity: 1) private static var orientationMask: UIInterfaceOrientationMask = .all - + private var deviceOrientation: UIDeviceOrientation { return UIDevice.current.orientation } - - private var orientation: UIInterfaceOrientation? { + + private var orientation: UIInterfaceOrientation { let windowScene = UIApplication.shared.windows.first?.windowScene - let orientation = windowScene?.interfaceOrientation + let orientation = windowScene?.interfaceOrientation ?? .unknown return orientation } - + private func setOrientation(_ orientationMask: UIInterfaceOrientationMask) { NeoOrientation.orientationMask = orientationMask } - + @objc static func getOrientation() -> UIInterfaceOrientationMask { return orientationMask } - + override func supportedEvents() -> [String] { return [ Constants.orientationDidChange, @@ -38,7 +38,7 @@ class NeoOrientation: RCTEventEmitter { Constants.lockDidChange ] } - + override init() { super.init() lastOrientation = orientation @@ -49,94 +49,86 @@ class NeoOrientation: RCTEventEmitter { object: nil) addListener(Constants.orientationDidChange) } - + deinit { NotificationCenter.default.removeObserver(self) removeListeners(1) } - - + + @objc func getOrientation(callback: @escaping RCTResponseSenderBlock) { OperationQueue.main.addOperation { [self] in - let orientationStr = getOrientationStr(orientation) - callback([orientationStr]) + callback([orientation.toString]) } } - + @objc func getDeviceOrientation(callback: @escaping RCTResponseSenderBlock) { OperationQueue.main.addOperation { [self] in - let deviceOrientationStr = getDeviceOrientationStr(deviceOrientation) - callback([deviceOrientationStr]) + callback([deviceOrientation.toString]) } } - + @objc func lockToPortrait() { OperationQueue.main.addOperation { [self] in lockToOrientation(.portrait, withMask: .portrait) } } - + @objc func lockToPortraitUpsideDown() { OperationQueue.main.addOperation { [self] in lockToOrientation(.portraitUpsideDown, withMask: .portraitUpsideDown) } } - + @objc func lockToLandscape() { - OperationQueue.main.addOperation { [self] in - isLocking = true - let orientationStr = getOrientationStr(orientation) - - UIDevice.current.setValue(UIInterfaceOrientation.unknown.rawValue, forKey: "orientation") - - if orientationStr == "landscapeRight" { - - setOrientation(.landscape) - UIDevice.current.setValue(UIInterfaceOrientation.landscapeLeft.rawValue, forKey: "orientation") - } else { + withLock { + OperationQueue.main.addOperation { [self] in + UIDevice.current.setValue(UIInterfaceOrientation.unknown.rawValue, + forKey: "orientation") + + let landscape = orientation == .landscapeRight ? UIInterfaceOrientation.landscapeLeft.rawValue : UIInterfaceOrientation.landscapeRight.rawValue setOrientation(.landscape) - UIDevice.current.setValue(UIInterfaceOrientation.landscapeRight.rawValue, forKey: "orientation") + UIDevice.current.setValue(landscape, forKey: "orientation") + + UIViewController.attemptRotationToDeviceOrientation() + sendEvent(withName: Constants.lockDidChange, + body: ["orientation": "landscapeLeft"]) } - - UIDevice.current.setValue(lastDeviceOrientation, forKey: "orientation") - UIViewController.attemptRotationToDeviceOrientation() - sendEvent(withName: Constants.lockDidChange, - body: ["orientation": "landscapeLeft"]) - isLocking = false + } } - + @objc func lockToLandscapeRight() { OperationQueue.main.addOperation { [self] in lockToOrientation(.landscapeLeft, withMask: .landscapeLeft) } } - + @objc func lockToLandscapeLeft() { OperationQueue.main.addOperation { [self] in lockToOrientation(.landscapeRight, withMask: .landscapeRight) } } - + @objc func unlockAllOrientations() { OperationQueue.main.addOperation { [self] in lockToOrientation(.unknown, withMask: .all) } } - + @objc override func constantsToExport() -> [AnyHashable : Any]! { - return ["initialOrientation": getOrientationStr(orientation)] + return ["initialOrientation": orientation.toString] } - + override class func requiresMainQueueSetup() -> Bool { return true } @@ -146,68 +138,41 @@ extension NeoOrientation { @objc private func deviceOrientationDidChange() { guard deviceOrientation != .unknown else { return } - + if orientation != .unknown && orientation != lastOrientation { sendEvent(withName: Constants.orientationDidChange, - body: ["orientation" : getOrientationStr(orientation)]) + body: ["orientation" : orientation.toString]) lastOrientation = orientation } - - if !isLocking && deviceOrientation != lastDeviceOrientation { + + if deviceOrientation != lastDeviceOrientation { sendEvent(withName: Constants.deviceOrientationDidChange, - body: ["orientation": getDeviceOrientationStr(deviceOrientation)]) + body: ["orientation": deviceOrientation.toString]) lastDeviceOrientation = deviceOrientation } } private func lockToOrientation(_ newOrientation: UIInterfaceOrientation, withMask mask: UIInterfaceOrientationMask) { - isLocking = true - setOrientation(mask) - let currentDevice = UIDevice.current - currentDevice.setValue(newOrientation, forKey: "orientation") - - if #available(iOS 16.0, *) { - let windowScene = UIApplication.shared.connectedScenes.first as! UIWindowScene - windowScene.requestGeometryUpdate(.iOS(interfaceOrientations: mask)) - windowScene.keyWindow?.rootViewController?.setNeedsUpdateOfSupportedInterfaceOrientations() - } else { - UIViewController.attemptRotationToDeviceOrientation() - } - sendEvent(withName: Constants.lockDidChange, - body: ["orientation": getOrientationStr(newOrientation)]) - isLocking = false - } - - private func getOrientationStr(_ orientation: UIInterfaceOrientation?) -> String { - switch orientation { - case .portrait: - return "portrait" - case .landscapeLeft: - return "landscapeLeft" - case .landscapeRight: - return "landscapeRight" - case .portraitUpsideDown: - return "portraitUpsideDown" - default: - return "unknown" + withLock { + setOrientation(mask) + let currentDevice = UIDevice.current + currentDevice.setValue(newOrientation, forKey: "orientation") + + if #available(iOS 16.0, *) { + let windowScene = UIApplication.shared.connectedScenes.first as! UIWindowScene + windowScene.requestGeometryUpdate(.iOS(interfaceOrientations: mask)) + windowScene.keyWindow?.rootViewController?.setNeedsUpdateOfSupportedInterfaceOrientations() + } else { + UIViewController.attemptRotationToDeviceOrientation() + } + sendEvent(withName: Constants.lockDidChange, + body: ["orientation": newOrientation.toString]) } } - - private func getDeviceOrientationStr(_ orientation: UIDeviceOrientation?) -> String { - switch orientation { - case .portrait: - return "portrait" - case .landscapeLeft: - return "landscapeLeft" - case .landscapeRight: - return "landscapeRight" - case .portraitUpsideDown: - return "portraitUpsideDown" - case .faceUp: - return "faceUp" - case .faceDown: - return "faceDown" - default: - return "unknown" - } + + private func withLock(_ closure: () -> T) -> T { + os_unfair_lock_lock(lock) + defer { os_unfair_lock_unlock(lock) } + return closure() } } + diff --git a/ios/UIDeviceOrientation+Extensions.swift b/ios/UIDeviceOrientation+Extensions.swift new file mode 100644 index 0000000..b366fcb --- /dev/null +++ b/ios/UIDeviceOrientation+Extensions.swift @@ -0,0 +1,20 @@ +extension UIDeviceOrientation { + var toString: String { + switch self { + case .portrait: + return "portrait" + case .landscapeLeft: + return "landscapeLeft" + case .landscapeRight: + return "landscapeRight" + case .portraitUpsideDown: + return "portraitUpsideDown" + case .faceUp: + return "faceUp" + case .faceDown: + return "faceDown" + default: + return "unknown" + } + } +} diff --git a/ios/UIInterfaceOrientation+Extensions.swift b/ios/UIInterfaceOrientation+Extensions.swift new file mode 100644 index 0000000..ea24a97 --- /dev/null +++ b/ios/UIInterfaceOrientation+Extensions.swift @@ -0,0 +1,16 @@ +extension UIInterfaceOrientation { + var toString: String { + switch self { + case .portrait: + return "portrait" + case .landscapeLeft: + return "landscapeLeft" + case .landscapeRight: + return "landscapeRight" + case .portraitUpsideDown: + return "portraitUpsideDown" + default: + return "unknown" + } + } +}