将数据从模态视图传递到父视图

问题描述 投票:0回答:1

我正在制作一个视频应用程序,并尝试将数据从列表模式视图传递到父列表。 当我将静态 url 设置为 fetcher 时,列表视图可以工作。 我试图将 json url 从模态视图更改为父级并将数据解析为列表视图,当我在打印日志上看到但列表视图不更新内容时,获取器工作良好且正确。

VideoView.swift

public class VideoFetcher: ObservableObject {

    @Published var videos = [Video]()
/*
    init(){
        load(videoURL: URL(string: "http://192.168.1.168:8080/category/shorts/vegie-elite.json")!)
    }
*/
    func load(videoURL: URL) {
        URLSession.shared.dataTask(with: videoURL) {(data,response,error) in
            do {
                if let d = data {
                    let decodedLists = try JSONDecoder().decode([Video].self, from: d)
                    DispatchQueue.main.async {
                        self.videos = decodedLists
                        print(decodedLists)
                    }
                }else {
                    print("No Data")
                }
            } catch {
                print (error)
            }
        }.resume()
    }
}

这是显示内容的列表


struct VideoView: View {
 //   @State private var isPresented = false
    @State private var showingSheet = false
    @ObservedObject var fetcher = VideoFetcher()
    
    @State var vURL: String

    
    var body: some View {
        NavigationStack {
            List (fetcher.videos) { video in
                NavigationLink(destination: VideoPlayerLive(videoLink: video.v1080p)
                    .navigationBarBackButtonHidden(true)
                    .toolbar(.hidden, for: .tabBar)
                ) {
                    HStack {
                        WebImage(url: URL(string: video.image)) { image in
                            image.resizable() // Control layout like SwiftUI.AsyncImage, you must use this modifier or the view will use the image bitmap size
                            
                        } placeholder: {
                            Rectangle().foregroundColor(Color("color.background.cell"))
                        }
                        // Supports options and context, like `.delayPlaceholder` to show placeholder only when error
                        .onSuccess { image, data, cacheType in
                            // Success
                            // Note: Data exist only when queried from disk cache or network. Use `.queryMemoryData` if you really need data
                        }
                        .indicator(.activity) // Activity Indicator
                        .transition(.fade(duration: 0.5)) // Fade Transition with duration
                        .scaledToFit()
                        .frame(width: 100, height: 100, alignment: .center)
                        .cornerRadius(5)
                        
                        VStack (alignment: .leading)  {
                            Spacer()
                            Text(video.name)
                                .font(.system(size: 18))
                                .foregroundColor(Color("color.text.orange"))
                            Spacer()
                            Text(video.released)
                                .font(.system(size: 13))
                                .foregroundColor(Color("color.text.gray"))
                            Spacer()
                        }
                    }
                }
                
            }
 
            .refreshable {
                fetcher.load(videoURL: URL(string: vURL)!)
                fetcher.objectWillChange.send()
            }    
              
            .toolbar {
                ToolbarItem(placement: .navigationBarLeading) {
                    Button {
                        showingSheet.toggle()
                    }label: {
                        Image(systemName: "list.bullet")
                    }
                    .sheet(isPresented: $showingSheet) {
                        VideoCategory()
                    }
                }
                           
            }
        }
        
    }
}

这是VideoModel.swift


public struct Video: Identifiable, Codable {
    public var id: Int
    public var name: String
    public var image: String
    public var released: String
    public var v720p: String
    public var v1080p: String

    
    enum CodingKeys: String, CodingKey {
        case id = "id"
        case name = "title"
        case image = "image"
        case released = "year"
        case v720p = "v720p"
        case v1080p = "v1080p"
    }
}

这是 VideoCategory(带列表的子视图)

var body: some View {
        @State var fileItems = FileItem.preview()
        
        NavigationStack {
            List(fileItems, children: \.children) { fileItem in
                
                if fileItem.isFolder {
                    Label(fileItem.title, systemImage: "folder.fill")
                        .foregroundColor(Color("color.text.pink"))
                    
                } else {
              //      Label(fileItem.title, systemImage: "film")
                //        .foregroundColor(Color("color.text.orange"))
                    Button {
                   //     VideoFetcher().load(videoURL: URL(string: fileItem.url)!)
                        VideoView(vURL: fileItem.url).fetcher.load(videoURL: URL(string: fileItem.url)!)
                        self.presentationMode.wrappedValue.dismiss()
                    } label: {
                        HStack {
                            Image(systemName: "film")
                            Text(fileItem.title)
                                .foregroundColor(Color("color.text.orange"))
                        }
                    }
                }
            }
        }
    }

我尝试搜索解决方案,但找不到像我一样的案例。

谁能帮我解决这个问题。我是 swiftui 的新手。谢谢!

swiftui swiftui-list
1个回答
0
投票

尝试这种方法来解决您的一些问题。 在您的

@StateObject private var fetcher = VideoFetcher()
中使用
VideoView
并使用
VideoCategory
将模型传递给
.environmentObject(fetcher)

查看此链接在应用程序中管理模型数据,它为您提供了一些有关如何在应用程序中管理数据的好示例。

由于代码中缺少许多元素,我无法测试代码, 然而,使用这种方法应该会让您更接近您想要实现的目标。

struct VideoCategory: View {
    @EnvironmentObject var fetcher: VideoFetcher  // <--- here
    let fileItems = FileItem.preview() // <--- I assume this gives [FileItem]
    
    var body: some View {
        NavigationStack {
            List(fileItems, children: \.children) { fileItem in
                if fileItem.isFolder {
                    Label(fileItem.title, systemImage: "folder.fill")
                        .foregroundColor(Color("color.text.pink"))
                } else {
                    //      Label(fileItem.title, systemImage: "film")
                    //        .foregroundColor(Color("color.text.orange"))
                    Button {
                        if let url = URL(string: fileItem.url) { // <--- here
                            fetcher.load(videoURL: url) // <--- here
                        }
                    } label: {
                        HStack {
                            Image(systemName: "film")
                            Text(fileItem.title)
                                .foregroundColor(Color("color.text.orange"))
                        }
                    }
                }
            }
        }
    }
}

struct VideoView: View {
    @State private var showingSheet = false
    @StateObject private var fetcher = VideoFetcher()  // <--- here
    let vURL: String // <--- here

    var body: some View {
        NavigationStack {
            List (fetcher.videos) { video in
                NavigationLink(destination: VideoPlayerLive(videoLink: video.v1080p)
                    .navigationBarBackButtonHidden(true)
                    .toolbar(.hidden, for: .tabBar)
                ) {
                    HStack {
                        // ......
                    }
                }
            }
            .refreshable {
                fetcher.load(videoURL: URL(string: vURL)!)
              //  fetcher.objectWillChange.send() // <--- should not have to do this
            }
            .toolbar {
                ToolbarItem(placement: .navigationBarLeading) {
                    Button {
                        showingSheet.toggle()
                    }label: {
                        Image(systemName: "list.bullet")
                    }
                    .sheet(isPresented: $showingSheet) {
                        VideoCategory()
                            .environmentObject(fetcher)  // <--- here
                    }
                }
            }
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.