尝试通过onAppear()显示json数据时TabView空白

时间:2020-07-31 22:03:33

标签: swift swiftui

我跟随this tutorial从我的API调用数据。我转弯了一下,转而使用TabView来显示“主页”,其中数据加载到第一个选项卡中。从某种意义上说,它“起作用”是,如果我导航到另一个选项卡并返回到主页选项卡,则会显示数据。当我打开应用程序时,该选项卡为空白。我最初将posts声明为空数组,为什么onAppear()不填充它?

这是应该显示我的数据的视图

struct DiscoverView: View {
    @ObservedObject var discoverPosts: DiscoverPosts
    
    var body: some View {
        NavigationView{
            ScrollView(.vertical, showsIndicators: false) {
                VStack(alignment: .center){
                    ForEach(self.discoverPosts.posts) { post in
                        HStack{
                            DiscoverList(isModal : false,displayName : post.displayName,id : post.id,likes : post.likes,owner : post.owner,avatar : post.avatar,author_id : post.author_id,icebreaker : post.icebreaker,answer : post.answer,mediaLink : post.mediaLink,songURL : post.songURL,type : post.type,liked: post.liked)
                        }
                        .padding(10)
                    }
                }
            }
            .onAppear(){
                // self.discoverPosts.getPosts()
            }
            .navigationViewStyle(StackNavigationViewStyle())
            .navigationBarTitle("Discover")
        }
    }
}

这是我的discoverPosts()

class discoverPosts : ObservableObject {
    @State var posts : [Post] = []
    func getPosts(completion: @escaping ([Post]) -> ()){
        let feedURL = "URL"
        guard let url = URL(string: feedURL) else { return }
        URLSession.shared.dataTask(with: url) { (data, _, _) in
            let posts = try! JSONDecoder().decode([Post].self, from: data!)
            DispatchQueue.main.async {
                self.posts = posts
                completion(posts)
            }
        }
        .resume()
    }
}

我的ConventView.swift显示TabView。我相信问题可能是等级制

struct ContentView: View {
    var body: some View {
        
        Home()
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

struct Home : View {
    
    @State var show = false
    @State var status = UserDefaults.standard.value(forKey: "status") as? Bool ?? false
    
    var body: some View{
            VStack{
                
                if self.status{
                    
                    TabView {
                        DiscoverView(discoverPosts: DiscoverPosts())
                            .tabItem(){
                                Image(systemName: "person")
                                .font(.system(size:20))
                            }
                            .tag(1)
                        InboxView(offsetLine: IndexSet.Element())
                            .tabItem(){
                                Image(systemName: "message")
                                .font(.system(size: 20))
                            }
                            .tag(2)
                        ProfileView()
                            .tabItem(){
                                Image(systemName: "person")
                                .font(.system(size: 20))
                            }
                            .tag(3)
                    }
                    .accentColor(Color.purple)
                    .navigationViewStyle(StackNavigationViewStyle())
                }
                else{
                    
                    ZStack{
                        
                        NavigationLink(destination: SignUp(show: self.$show), isActive: self.$show) {
                            
                            Text("")
                        }
                        .hidden()
                        
                        Login(show: self.$show)
                    }
                }
            }
            .navigationBarTitle("")
            .navigationBarHidden(true)
            .navigationBarBackButtonHidden(true)
            .onAppear {
                
                NotificationCenter.default.addObserver(forName: NSNotification.Name("status"), object: nil, queue: .main) { (_) in
                    
                    self.status = UserDefaults.standard.value(forKey: "status") as? Bool ?? false
                }
            }
    }
}

对于那些经历过这种情况的人,可以将Text("").frame(width: UIScreen.main.bounds.width)放在ScrollView的底部

1 个答案:

答案 0 :(得分:1)

将您的ObservableObject更改为:

class DiscoverPosts: ObservableObject { // make Types capitalised
    @Published var posts: [Post] = [] // <- replace @State with @Published

    init() {
        getPosts()
    }

    func getPosts() { // <- no need for completion handler, update `self.posts`
        let feedURL = "URL"
        guard let url = URL(string: feedURL) else { return }
        URLSession.shared.dataTask(with: url) { data, _, _ in
            let posts = try! JSONDecoder().decode([Post].self, from: data!)
            DispatchQueue.main.async {
                self.posts = posts
            }
        }
        .resume()
    }
}

并在您的视图中像这样使用它:

struct DiscoverView: View {
    @ObservedObject var discoverPosts: DiscoverPosts // declare only

    var body: some View {
        ZStack {
            ...
        }
        //.onAppear { // <- remove onAppear
        //    self.discoverPosts.getPosts()
        //}
    }
}

您还需要从DiscoverPosts视图将DiscoverView传递到Home

DiscoverView(discoverPosts: DiscoverPosts())

请注意,如果您先前曾在视图中访问过self.posts,则现在需要访问self.discoverPosts.posts