首页 > 解决方案 > 状态更改后 AnyView 不重新渲染

问题描述

我有下面的函数,它返回 AnyView 并且应该根据设备方向给出不同的结果。当方向改变时,它会被检测并打印,但不会重新渲染视图。知道如何解决这个问题吗?

func getView() -> AnyView {
    @State var isPortrait = UIDevice.current.orientation.isPortrait

    let a =
        HStack {
            if isPortrait {
                VStack {
                    Text("text inside VStack")
                }
            } else {
                HStack {
                    Text("text inside HStack")
                }
            }
        }
        .onReceive(NotificationCenter.default.publisher(for: UIDevice.orientationDidChangeNotification)) { _ in
            print("notification isPortrait: \(UIDevice.current.orientation.isPortrait)")
            isPortrait = UIDevice.current.orientation.isPortrait
        }
        .onAppear() {
            isPortrait = UIDevice.current.orientation.isPortrait
        }
    return AnyView(a)
}

标签: swiftswiftuiswift5

解决方案


这是我的测试代码,显示了方向的变化。在 ios 15、iPhone 设备上测试。

import SwiftUI

@main
struct TestApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
} 

struct ContentView: View {
    @State var isPortrait = UIDevice.current.orientation.isPortrait  // <--- here

    var body: some View {
        VStack (spacing: 40) {
            Text("testing orientations")
            // getView()  // works just as well
            myView        // alternative without AnyView
        }
    }
    
    var myView: some View {
        Text(isPortrait ? "should be Portrait" : "should be Landscape")
            .onReceive(NotificationCenter.default.publisher(for: UIDevice.orientationDidChangeNotification)) { _ in
                isPortrait = UIDevice.current.orientation.isPortrait
            }
            .onAppear() {
                isPortrait = UIDevice.current.orientation.isPortrait
            }
    }
    
    func getView() -> AnyView {
        let a =
            HStack {
                if isPortrait {
                    VStack {
                        Text("should be Portrait")
                    }
                } else {
                    HStack {
                        Text("should be Landscape")
                    }
                }
            }
            .onReceive(NotificationCenter.default.publisher(for: UIDevice.orientationDidChangeNotification)) { _ in
                    print("notification isPortrait: \(UIDevice.current.orientation.isPortrait)")
                    isPortrait = UIDevice.current.orientation.isPortrait
            }
            .onAppear() {
                isPortrait = UIDevice.current.orientation.isPortrait
            }
        return AnyView(a)
    }
}

编辑1:

正如@Rob所说,最好的方法是制作一个单独的自定义视图,例如:

struct GetView: View {
    @State var isPortrait = UIDevice.current.orientation.isPortrait
    
    var body: some View {
        VStack {
            HStack {
                if isPortrait {
                    VStack {
                        Text("should be Portrait")
                    }
                } else {
                    HStack {
                        Text("should be Landscape")
                    }
                }
            }
            .onReceive(NotificationCenter.default.publisher(for: UIDevice.orientationDidChangeNotification)) { _ in
                print("notification isPortrait: \(UIDevice.current.orientation.isPortrait)")
                isPortrait = UIDevice.current.orientation.isPortrait
            }
            .onAppear() {
                isPortrait = UIDevice.current.orientation.isPortrait
            }
        }
    }
} 

推荐阅读