0

我正在使用与 AsyncImage 中相同的初始化签名创建一个名为 AsyncImageCached 的自定义对象。我的问题是,如何在 init 之外定义变量以保存内容占位符参数以在我的异步等待调用完成时使用?

public struct AsyncImageCached<Content> : View where Content : View {

    private let content: ((Image) -> I)?   <--- Doesn't Work, Cannot find type 'I' in scope
    private let placeholder: (() -> P)?    <--- Doesn't work, Cannot find type 'P' in scope

    init<I, P>(url: URL?, scale: CGFloat = 1, 
        @ViewBuilder content: @escaping (Image) -> I,
        @ViewBuilder placeholder: @escaping () -> P)
        where Content == _ConditionalContent<I, P>, I : View, P : View {

        let content: (Image) -> I = content    <--- Works, but can't access outside of init
        let placeholder: () -> P = placeholder <--- Works, but can't access outside of init

        ...
    }
}

将 I、P 移动到结构级别会破坏其他初始化,并且不会匹配 Apple 的 AsyncImage 签名。

必须有办法让它工作,因为相同的签名在 AsyncImage 中。我不想更改初始化签名函数,因为我已经有其他初始化工作:

public init(url: URL?, scale: CGFloat = 1) where Content == Image
public init(url: URL?, scale: CGFloat = 1, @ViewBuilder content: @escaping (AsyncImagePhase) -> Content)

任何帮助将不胜感激,我花了两天时间在网上找不到任何教如何在简单示例之外使用 ViewBuilder 的东西,没有像这样的自定义初始化。

4

1 回答 1

2

好吧,检查 Swift 接口文件,我们可以看到以下内容:

public struct AsyncImage<Content> : SwiftUI.View where Content : SwiftUI.View {
    /* ... */

    @_alwaysEmitIntoClient public init<I, P>(url: Foundation.URL?, scale: CoreGraphics.CGFloat = 1, @SwiftUI.ViewBuilder content: @escaping (SwiftUI.Image) -> I, @SwiftUI.ViewBuilder placeholder: @escaping () -> P) where Content == SwiftUI._ConditionalContent<I, P>, I : SwiftUI.View, P : SwiftUI.View {
        self.init(url: url, scale: scale) { phase in
            if let i = phase.image {
                content(i)
            } else {
                placeholder()
            }
        }
    }

    /* ... */
}

所以,事实证明它只是调用另一个init本身,它不需要这些泛型!

您可以在 处看到接口文件/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/System/Library/Frameworks/SwiftUI.framework/Modules/SwiftUI.swiftmodule/arm64.swiftinterface,替换Xcode.app为任何名称(因为 beta 具有不同的名称)

于 2021-11-29T02:54:59.497 回答