Swift 协议和返回“某些视图”的方法

Jus*_*808 7 swift swiftui

所以协议不支持some View作为返回类型......我正在尝试这个:

public extension View {
    func popSheet(isPresented: Binding<Bool>, arrowEdge: Edge = .bottom, content: @escaping () -> PopSheet) -> some View {
        Group {
            if UIDevice.current.userInterfaceIdiom == .pad {
                popover(isPresented: isPresented, attachmentAnchor: .rect(.bounds), arrowEdge: arrowEdge, content: {
                    content().popover()
                })
            } else {
                actionSheet(isPresented: isPresented, content: {
                    content().actionSheet()
                })
            }
        }
    }
}

protocol PopSheet {
    func actionSheet() -> ActionSheet
    associatedtype View
    func popover() -> View
}
Run Code Online (Sandbox Code Playgroud)

但整个函数声明失败并且出现 content().popover()错误。

Method must be declared internal because its parameter uses an internal type

Protocol 'PopSheet' can only be used as a generic constraint because it has Self or associated type requirements

Member 'popover' cannot be used on value of protocol type 'PopSheet'; use a generic constraint instead

Rob*_*ier 7

这里没有什么根本性的错误。只是几个小错误。

首先,您的View关联类型与 无关SwiftUI.View。它只是碰巧有相同的名字。你的意思可能是这样的:

public protocol PopSheet {
    associatedtype V: View   // Create a new type that conforms to View
    func actionSheet() -> ActionSheet
    func popover() -> V
}
Run Code Online (Sandbox Code Playgroud)

你的第二个问题是你不能直接依赖 PopSheet,因为它有一个关联类型。您的意思是您期望某种符合 PopSheet 的具体类型:

func popSheet<Sheet: PopSheet>(isPresented: Binding<Bool>, 
                               arrowEdge: Edge = .bottom, 
                               content: @escaping () -> Sheet) -> some View {
Run Code Online (Sandbox Code Playgroud)

这样,您的实施应该没问题。