SwiftUI Navigation Bar Title in Reusable Cross-Platform (iOS & macOS) View

会有一股神秘感。 提交于 2020-01-25 08:13:16

问题


I'm attempting to create reusable SwiftUI View for a framework, which can then be used across both iOS/iPadOS and macOS.

This generally works fine; however, because macOS views don't have navigation bars, including a navigation bar title (important for iOS) causes an error when the view's included in a macOS target:

.navigationBarTitle(Text("Page Title"))

Value of type '...' has no member 'navigationBarTitle'

Any suggestions on a conditional compilation (or any other) approach that can allow the same view to build for both platforms?

The closest I've come is the following. Including the extra Text view is easy enough, but because the bar title's a modifier, wrapping just that part in conditional compilation produces other errors:

public struct ExampleView: View {

    private let pageTitle = "Page Title"

    public var body: some View {

        VStack(alignment: .center) {

            #if os(macOS)
            Text(pageTitle)
                .font(.title)
            #endif

            Spacer()           
            Text("This is the view content")
            Spacer()
        }

        #if !os(macOS)
        .navigationBarTitle(Text(pageTitle))
        #endif
    }
}

Unexpected platform condition (expected 'os', 'arch', or 'swift')

Function declares an opaque return type, but has no return statements in its body from which to infer an underlying type


回答1:


I established one approach: Move the main content to another View property, then modify it to add the navbar title (if needed) before returning it as body. When it's separated this way, conditional compilation can be used.

It's a bit inelegant, but it works. It can also be used to set macOS-specific things, such as the view's overall frame size. Suggestions on a better approach are welcome!

Swift v5.1

public struct ExampleView: View {

    private let pageTitle = "Page Title"

    #if !os(macOS)
    public var body: some View {
        main.navigationBarTitle(Text(pageTitle))
    }
    #else
    public var body: some View {
        main.frame(
            minWidth: 500,
            minHeight: 500
        )
    }
    #endif
    public var main: some View {

        VStack(alignment: .center) {

            #if os(macOS)
            Text(pageTitle)
                .font(.title)
            #endif

            Spacer()           
            Text("This is the view content")
            Spacer()
        }
    }
}


来源:https://stackoverflow.com/questions/59359791/swiftui-navigation-bar-title-in-reusable-cross-platform-ios-macos-view

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!