ios - SwiftUI - 代码中的扩展定义放置
问题描述
Xcode 最近让我很头疼,因为它使用了一个将 SwiftUI 视图转换为 UIImage 的扩展。该项目主要是 SwiftUI 通用应用程序。我需要用于 ClockKit Complications 定义的 UIImage,并且我发现以下代码理论上应该可以做到这一点:
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)
}
}
}
问题是:
- Xcode 只允许将扩展放在主 ContentView 的顶部,watchOS Extension 不会检测到它(因为它有自己的 ContentView,不能共享或设置为两者的目标成员)。在代码中的任何其他地方,我都会收到以下错误。
- 即使扩展在主 ContentView 中没有给出错误,那么常量声明也不起作用,它会给出以下错误。如果将其更改为
let exportimage: UIImage = MoonView.snapshot(MoonView)
它,则只需说Cannot convert value of type 'MoonView.Type' to expected argument type 'MoonView'。
如何解决问题?可以放置扩展名的问题吗?Xcode 版本 12.5,我清理了构建文件夹,但找不到任何与名称相似的地方。在所有代码文件中,SwiftUI 和 UIKit 库都被导入(即使后者对于编译器来说似乎并不是最重要的)。
非常感谢所有的贡献。
解决方案
给定以下扩展名:
extension View {
func sayHello() {
print("Hello, world!")
}
}
为了实现#1,您可以将扩展名放在其自己的文件中,然后将其分配给将使用它的每个目标。
然后,正如@aheze 在评论中指出的那样,您必须在 View 的实例(而不是 View 类型本身)上调用该函数。所以:
MoonView().sayHello()
但是,在您的情况下,您看到错误的原因(如Cannot find UIHostingController
范围内)是因为WatchOSUIHostingController
上UIGraphicsImageRenderer
不可用(请参阅https://developer.apple.com/documentation/swiftui/uihostingcontroller和https:// developer.apple.com/documentation/uikit/uigraphicsimagerenderer),这意味着所写的扩展程序不会在该平台上编译。
推荐阅读
- flutter - Flutter 1.5 - 有没有办法更新资产文件夹中的文件?
- aws-lambda - 如何引用 SAM 模板中定义的角色?
- javascript - 如何在 Vue.js 中将搜索查询框合并到 api 调用中
- c++ - 如果使用 WS_POPUP 样式创建 Window,则永远不会传递 WM_PAINT 消息
- python - SMTPHandler 一次发送一封电子邮件。我怎样才能改变这个?
- android - 如何将信息传递给 Android Studio 中的导航标头
- azure - azure 数据库与 aurora mysql (aws manged database) 相比最显着的差异
- python - Selenium 检查元素是否在 x 秒内可见
- javascript - 如何使用 split 与逗号分隔,除了逗号有一个前面的字符和 6 个后面的字符
- javascript - 试图第二次从 div 中删除一个孩子(javascript)