SwiftUI - 代码中的扩展定义位置 [英] SwiftUI - Extension definition placement in code

查看:41
本文介绍了SwiftUI - 代码中的扩展定义位置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Xcode 最近在使用将 SwiftUI 视图转换为 UIImage 的扩展程序时让我很头疼.该项目主要是 SwiftUI 通用应用程序.我需要 UIImage 来定义 ClockKit Complications,我发现以下代码理论上应该可以做到这一点:

Xcode is recently giving me a lot of headaches with using an extension that converts a SwiftUI View to an UIImage. The project is predominantly SwiftUI universal app. I need UIImage for ClockKit Complications definitions and I have found the following code that should in theory do that just fine:

extension View {
    func snapshot() -> UIImage {
        let controller = UIHostingController(rootView: self)
        let view = controller.view

        let targetSize = controller.view.intrinsicContentSize
        view?.bounds = CGRect(origin: .zero, size: targetSize)
        view?.backgroundColor = .clear

        let renderer = UIGraphicsImageRenderer(size: targetSize)

        return renderer.image { _ in
            view?.drawHierarchy(in: controller.view.bounds, afterScreenUpdates: true)
        }
    }
}

问题是:

  1. Xcode 只允许将扩展放在主 ContentView 的顶部,watchOS 扩展不会检测到它(因为它有自己的 ContentView,不能共享或设置为两者的目标成员).在代码的任何其他地方,我得到以下错误.
  2. 即使扩展没有在主 ContentView 中给出错误,常量声明也不起作用,它给出 以下错误.如果将其更改为 let exportimage: UIImage = MoonView.snapshot(MoonView),则它只会说无法将类型 'MoonView.Type' 的值转换为预期的参数类型 'MoonView'.
  1. Xcode allows only the extension to be put at the top of main ContentView, which is not detected by watchOS Extension (as it has its own ContentView and it cannot be shared or set as Target Member for both). In any other place in code I get the following errors.
  2. Even if the extension doesn't give en error in the main ContentView then the constant declaration doesn't work either way and it gives a following error. If that is changed to let exportimage: UIImage = MoonView.snapshot(MoonView) it then just says Cannot convert value of type 'MoonView.Type' to expected argument type 'MoonView'.

如何解决这个问题?是不是可以放置扩展的问题?Xcode 12.5 版,我清理了构建文件夹,但找不到与名称的任何相似之处.在所有代码文件中,SwiftUI 和 UIKit 库都被导入(即使后者对于编译器来说似乎不是最重要的).

How can one approach the problem? Is it a problem where the extension can be placed? Xcode version 12.5, I cleaned build folder and I can't find any similarities to names. In all code files both SwiftUI and UIKit libraries are imported (even though the latter doesn't seem paramount for the compiler).

非常感谢所有的贡献.

推荐答案

鉴于以下扩展名:

extension View {
  func sayHello() {
    print("Hello, world!")
  }
}

为了实现 #1,您可以将扩展名放在自己的文件中,然后将其分配给将使用它的每个目标.

In order to achieve #1, you would put the extension in its own file and then assign it to each target where it will be used.

然后,正如@aheze 在评论中指出的那样,您必须在 View 的实例(而不是 View 类型本身)上调用该函数.所以:

Then, as @aheze points out in the comments, you would have to call that function on an instance of a View (not a View type itself). So:

MoonView().sayHello()

但是,在您的情况下,您看到错误的原因(例如 Cannot find UIHostingController in scope)是因为 UIHostingControllerUIGraphicsImageRenderer 在 WatchOS 上不可用(请参阅 https://developer.apple.com/documentation/swiftui/uihostingcontrollerhttps://developer.apple.com/documentation/uikit/uigraphicsimagerenderer),意味着扩展,如所写,不会在该平台上编译.

However, in your case, the reason that you're seeing the error (like Cannot find UIHostingController in scope) is because UIHostingController and UIGraphicsImageRenderer are not available on WatchOS (see https://developer.apple.com/documentation/swiftui/uihostingcontroller and https://developer.apple.com/documentation/uikit/uigraphicsimagerenderer), meaning the extension, as written, will not compile on that platform.

这篇关于SwiftUI - 代码中的扩展定义位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆