【问题标题】:SwiftUI - Determining Current Device and OrientationSwiftUI - 确定当前设备和方向
【发布时间】:2021-01-05 05:01:49
【问题描述】:

我正在尝试检测设备何时在 iPad 上和纵向模式。

目前我在 UIKit 中使用UIDevice API 并使用环境对象来观察变化。我使用这里找到的解决方案 - Determining Current Device and Orientation

但是,orientationInfo.orientation 最初始终等于 .portrait,直到旋转为纵向,然后再返回横向。

所以在执行以下操作时显示FABView

struct HomeView: View {

@EnvironmentObject var orientationInfo: OrientationInfo
let isPhone = UIDevice.current.userInterfaceIdiom == .phone

    var body: some View {
      ZStack(alignment: .bottom) {
          #if os(iOS)
          if isPhone == false && orientationInfo.orientation == .portrait {
            FABView()
          }
          #endif
      }
    }
}

当 iPad 最初处于横向时会加载视图,但在更改为纵向并返回横向时会被删除。为什么会发生这种情况?如何确保在首次加载时未加载视图?

完整代码

struct HomeTab: View {
    
    var body: some View {
        NavigationView {
            HomeView()
                .environmentObject(OrientationInfo())
        }
    }
}

struct HomeView: View {

@EnvironmentObject var orientationInfo: OrientationInfo
let isPhone = UIDevice.current.userInterfaceIdiom == .phone

    var body: some View {
      ZStack(alignment: .bottom) {
          #if os(iOS)
          if isPhone == false && orientationInfo.orientation == .portrait {
            FABView()
          }
          #endif
      }
    }
}

final class OrientationInfo: ObservableObject {
    enum Orientation {
        case portrait
        case landscape
    }
    
    @Published var orientation: Orientation
    
    private var _observer: NSObjectProtocol?
    
    init() {
        // fairly arbitrary starting value for 'flat' orientations
        if UIDevice.current.orientation.isLandscape {
            self.orientation = .landscape
        }
        else {
            self.orientation = .portrait
        }
        
        // unowned self because we unregister before self becomes invalid
        _observer = NotificationCenter.default.addObserver(forName: UIDevice.orientationDidChangeNotification, object: nil, queue: nil) { [unowned self] note in
            guard let device = note.object as? UIDevice else {
                return
            }
            if device.orientation.isPortrait {
                self.orientation = .portrait
            }
            else if device.orientation.isLandscape {
                self.orientation = .landscape
            }
        }
    }
    
    deinit {
        if let observer = _observer {
            NotificationCenter.default.removeObserver(observer)
        }
    }
}

【问题讨论】:

    标签: ios swiftui uikit


    【解决方案1】:

    您可以使用UIDevice.orientationDidChangeNotification 来检测方向变化,但您不应该在应用启动时依赖它。

    UIDevice.current.orientation.isValidInterfaceOrientation 在开头会是假的,因此两者都是

    • UIDevice.current.orientation.isLandscape

    • UIDevice.current.orientation.isPortrait

    将返回false

    您可以在第一个窗口场景中使用interfaceOrientation

    struct ContentView: View {
        @State private var isPortrait = false
        
        var body: some View {
            Text("isPortrait: \(String(isPortrait))")
                .onReceive(NotificationCenter.default.publisher(for: UIDevice.orientationDidChangeNotification)) { _ in
                    guard let scene = UIApplication.shared.windows.first?.windowScene else { return }
                    self.isPortrait = scene.interfaceOrientation.isPortrait
                }
        }
    }
    

    还要注意设备方向不等于界面方向。当设备在纵向模式下倒置时,设备方向是portrait,但界面方向也可以是landscape

    我认为在你的情况下依赖界面方向会更好。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-08-16
      • 1970-01-01
      • 2020-07-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多