首页 > 解决方案 > 如何在 SwiftUI 中使用来自用户的输入更改 url 字符串

问题描述

我正在制作这个应用程序,它使用 jikan API 来显示动漫列表,所以在 url 中有一个选项可以更改类型 - 动漫、漫画等和子类型 - 即将上映、电视、电影等,API工作正常并且正在获取详细信息,但现在我想在表单视图中显示两个选择器,最好允许用户选择类型和子类型,因此我使用了选择器的 @State 属性,但是当我运行时它没有更新列表应用程序并从选择器中选择不同的值

这是代码 -

import SwiftUI


struct Response: Codable{
    var top: [Result]
    
}

struct Result: Codable {
    
    var mal_id: Int
    var rank: Int
    var title: String
    var type: String
    var start_date: String?
    var image_url: String
    
}

struct ContentView: View {
    
    @State private var str2 = ""
   @State private var str3 = ""
    
    func loadData() {

         str3 = String("/\(subtype[subTypeSelection])")
        
         str2 = String("\(type[typeSelection])/")
        
        let str1 = "https://api.jikan.moe/v3/top/"
        
        guard let url = URL(string: str1 + str2 + "\(1)" + str3) else {
            print("Invalid URL")
            return
        }
        
        
        let request = URLRequest(url: url)
        
        URLSession.shared.dataTask(with: request) { data, response, error in
            if let data = data {
                if let decodedResponse = try? JSONDecoder().decode(Response.self, from: data) {
                    // we have good data – go back to the main thread
                    DispatchQueue.main.async {
                        // update our UI
                        self.top = decodedResponse.top
                    }
                    // everything is good, so we can exit
                    return
                }
            }
            // if we're still here it means there was a problem
            print("Fetch failed: \(error?.localizedDescription ?? "Unknown error")")
        }.resume()
    }

     var type = ["anime", "manga", "people", "characters"]
     var subtype = ["airing", "upcoming", "tv", "movie", "ova", "special"]
    
    
    @State private var page = 1
    @State private var typeSelection = 0
    @State private var subTypeSelection = 2
   
    @State private var top = [Result]()
    var body: some View {
//        ScrollView {
        VStack {
       
            Picker("Your  Selection", selection: $subTypeSelection) {
                
                ForEach(0 ..< 6) {
                    somehting in
                    Text("\(subtype[somehting])")
                }
            }
                Picker("Your  Selection", selection: $typeSelection) {
                    
                    ForEach(0 ..< 4) {
                        somehting in
                        Text("\(type[somehting])")
                    }
                }
        }
        
//        .onAppear(perform: {
//            loadData()
//        })
            List(top, id: \.mal_id) { item in
                
                HStack {
                    AsyncImage(url: URL(string: item.image_url)!,
                                   placeholder: { Text("Loading ...") },
                                   image: { Image(uiImage: $0).resizable() })
                        .aspectRatio(contentMode: .fit)
                        .frame(width: 100, height: 100)
//                        .frame(idealHeight: UIScreen.main.bounds.width / 10 * 10 )
                        
                        .clipShape(Capsule())
                    VStack(alignment: .leading) {
                                Text(item.title)
                                    .font(.headline)
                                Text(String("\(item.rank)"))
                                    .font(.headline)
                                Text(item.type)
                                    .font(.headline)
                                Text(item.start_date ?? "")
                                                .font(.headline)
                                
                    }
                }
                    }
                      // }
            .onAppear(perform: loadData)
       
    }
}

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

标签: jsonapiswiftuistatepicker

解决方案


您可以尝试在每个选择器上使用“onChange”:

VStack {
    Picker("Your subtype Selection", selection: $subTypeSelection) {
        ForEach(0 ..< 6) { somehting in
            Text("\(subtype[somehting])").tag(somehting)
        }
    }.onChange(of: subTypeSelection) { value in
        loadData()
    }
    Picker("Your type Selection", selection: $typeSelection) {
        ForEach(0 ..< 4) { somehting in
            Text("\(type[somehting])").tag(somehting)
        }
    }.onChange(of: typeSelection) { value in
        loadData()
    }
}

这不是很有效,但我相信您会找到一种更好的方法来重新加载数据。


推荐阅读