SwiftUI - 代码中的扩展定义放置
SwiftUI - Extension definition placement in code
Xcode 最近使用将 SwiftUI 视图转换为 UIImage 的扩展让我很头疼。该项目主要是 SwiftUI 通用应用程序。我需要 UIImage 来定义 ClockKit Complications,我发现以下代码理论上应该可以做到这一点:
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 并且不能共享或设置为两者的目标成员).在代码的任何其他地方我得到 the following errors.
- 即使扩展没有在主 ContentView 中给出错误,常量声明也不起作用,它给出 a following error。如果将其更改为
let exportimage: UIImage = MoonView.snapshot(MoonView)
,则只会显示 无法将类型 'MoonView.Type' 的值转换为预期的参数类型 'MoonView'.
如何解决这个问题?扩展可以放置的地方有问题吗? Xcode 版本 12.5,我清理了构建文件夹,但找不到与名称有任何相似之处。在所有代码文件中,SwiftUI 和 UIKit 库都被导入(尽管后者对于编译器来说似乎不是最重要的)。
非常感谢所有贡献。
给定以下扩展名:
extension View {
func sayHello() {
print("Hello, world!")
}
}
为了实现#1,您可以将扩展名放在它自己的文件中,然后将其分配给将要使用它的每个目标。
然后,正如@aheze 在评论中指出的那样,您必须在 View 的实例(而不是 View 类型本身)上调用该函数。所以:
MoonView().sayHello()
但是,在您的情况下,您看到错误的原因(如范围内的 Cannot find UIHostingController
)是因为 UIHostingController
和 UIGraphicsImageRenderer
在 WatchOS 上不可用(请参阅https://developer.apple.com/documentation/swiftui/uihostingcontroller and https://developer.apple.com/documentation/uikit/uigraphicsimagerenderer),这意味着所写的扩展不会在该平台上编译。
Xcode 最近使用将 SwiftUI 视图转换为 UIImage 的扩展让我很头疼。该项目主要是 SwiftUI 通用应用程序。我需要 UIImage 来定义 ClockKit Complications,我发现以下代码理论上应该可以做到这一点:
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 并且不能共享或设置为两者的目标成员).在代码的任何其他地方我得到 the following errors.
- 即使扩展没有在主 ContentView 中给出错误,常量声明也不起作用,它给出 a following error。如果将其更改为
let exportimage: UIImage = MoonView.snapshot(MoonView)
,则只会显示 无法将类型 'MoonView.Type' 的值转换为预期的参数类型 'MoonView'.
如何解决这个问题?扩展可以放置的地方有问题吗? Xcode 版本 12.5,我清理了构建文件夹,但找不到与名称有任何相似之处。在所有代码文件中,SwiftUI 和 UIKit 库都被导入(尽管后者对于编译器来说似乎不是最重要的)。
非常感谢所有贡献。
给定以下扩展名:
extension View {
func sayHello() {
print("Hello, world!")
}
}
为了实现#1,您可以将扩展名放在它自己的文件中,然后将其分配给将要使用它的每个目标。
然后,正如@aheze 在评论中指出的那样,您必须在 View 的实例(而不是 View 类型本身)上调用该函数。所以:
MoonView().sayHello()
但是,在您的情况下,您看到错误的原因(如范围内的 Cannot find UIHostingController
)是因为 UIHostingController
和 UIGraphicsImageRenderer
在 WatchOS 上不可用(请参阅https://developer.apple.com/documentation/swiftui/uihostingcontroller and https://developer.apple.com/documentation/uikit/uigraphicsimagerenderer),这意味着所写的扩展不会在该平台上编译。