
swift ui 如何自定义组件并且获取组件内部回调函数所传递出来的数据
作者: boyyang
分类: Swift
发布: 2025-07-06 06:52:11
更新: 2025-07-06 06:52:11
浏览: 3
背景描述
最近使用swift ui开发项目的时候,遇到了一个问题。当我在封装一个自定义图片组件的时候,当组件接收到传递给图片组件的url地址的时候,我会通过通过url地址获取图片数据,同时向组件外部返回图片下载进度,以及图片是否下载成功。正常情况下可以这样做,代码如下
import SwiftUI
struct DownloadImage: View {
@State var url: URL
@State private var nsimage:NSImage?
var onSuccess :((_ isDownload: Bool) -> Void)?
func downloadImage(){
// 成功下载图片后 伪代码
if (onSuccess != nil){
onSuccess!(true)
}
}
var body: some View {
VStack{
if self.nsimage != nil {
Image(nsImage: self.nsimage!)
}
}
.onAppear{
downloadImage()
}
}
}
#Preview {
DownloadImage(url: URL(string: "https://www.test/image.png")!) { isDownload in
print(isDownload)
}
}
但是如果我同时需要向这个组件传递一个View视图,那么代码将会变成以下:
import SwiftUI
struct DownloadImage<Content:View>: View {
@State var url: URL
@State private var nsimage:NSImage?
var content: Content
var onSuccess :((_ isDownload: Bool) -> Void)?
init(url: URL, @ViewBuilder content: @escaping () -> Content, onSuccess: ((_: Bool) -> Void)? = nil) {
self.url = url
self.content = content()
self.onSuccess = onSuccess
}
func downloadImage(){
// 成功下载图片后 伪代码
if (onSuccess != nil){
onSuccess!(true)
}
}
var body: some View {
VStack{
content
if self.nsimage != nil {
Image(nsImage: self.nsimage!)
}
}
.onAppear{
downloadImage()
}
}
}
#Preview {
DownloadImage(
url: URL(string: "https://www.test/image.png")!,
content: {
VStack{
Text("xxx")
}.frame(width: 100, height: 100)
},
onSuccess: { isDownload in
print(isDownload)
}
)
}
虽然也能实现同样的效果,但是我想实现类似于以下效果:通过.onDelete来接受组件传递出来的数据信息
List {
ForEach(users, id: \.self) { user in
Text(user)
}
.onDelete(perform: delete)
}
最终代码如下:
import SwiftUI
struct DownloadImage<Content:View>: View {
@State var url: URL
@State private var nsimage:NSImage?
var content: Content
var onSuccess :((_ isDownload: Bool) -> Void)?
init(url: URL, @ViewBuilder content: @escaping () -> Content) {
self.url = url
self.content = content()
}
func downloadImage(){
// 成功下载图片后 伪代码
if (onSuccess != nil){
onSuccess!(true)
}
}
var body: some View {
VStack{
content
if self.nsimage != nil {
Image(nsImage: self.nsimage!)
}
}
.onAppear{
downloadImage()
}
}
}
extension DownloadImage {
func onSuccess(perform action: ((_ isDownlaod: Bool) -> Void)?) -> Self{
var this = self
this.onSuccess = action
return this
}
}
#Preview {
DownloadImage(
url: URL(string: "https://www.test/image.png")!
){
VStack{}.frame(width: 100, height: 100)
}
.onSuccess { isDownlaod in
print(isDownlaod)
}
}