首页 > 解决方案 > 如何创建要解码的 JSON URL 队列

问题描述

我的应用程序需要能够一次解码多个 JSON 文件(大约 50 个)。这是我目前用来执行此操作的代码:

class Api {
    static var Acceptable: Bool = true //Acceptable range to reload sites
    static var order = 1
    
    //From: https://stackoverflow.com/questions/38469648/unexpected-non-void-return-value-in-void-function-in-new-swift-class
    //Also from: https://stackoverflow.com/questions/65999965/how-to-pass-arguments-into-a-function-with-completion-swift (input part)
    func CoordsUpdate(completion: @escaping ((Double, Double, String) -> Void)) {
        var states = [ "AK", "AL", "AR", "AS", "AZ", "CA", "CO", "CT", "DC", "DE", "FL", "GA", "GU", "HI", "IA", "ID", "IL", "IN", "KS", "KY", "LA", "MA", "MD", "ME", "MI", "MN", "MO", "MS", "MT", "NC", "ND", "NE", "NH", "NJ", "NM", "NV", "NY", "OH", "OK", "OR", "PA", "PR", "RI", "SC", "SD", "TN", "TX", "UT", "VA", "VI", "VT", "WA", "WI", "WV", "WY"]

        for state in states {
            let URL = String("https://waterservices.usgs.gov/nwis/iv/?format=json&indent=off&stateCd=\(state)&parameterCd=00065&siteStatus=active")
            print("states URL:", URL)
            Api().getCoordinates(inputurl: URL) { lat, long, name in
                completion(lat, long, name)
                return
            }
            
            repeat {
                print("waiting for processing", state)
                //sleep(UInt32(0.1)) //waits for 0.1 sec
                sleep(1)
            } while (Api.order < 1)
            
            print("coordsupdate done for:", state)
            states.removeFirst()
            print("states left to process:", states)
        }
        print("done buh")
    }
    
    func getCoordinates(inputurl: String, completion: @escaping ((Double, Double, String) -> Void)) {
        Api.order = 0
        print("order is now 0")
        print("input:", inputurl)
        let url = URL(string: inputurl)!
        print("Fetching data")
        //Timer from: https://stackoverflow.com/questions/24755558/measure-elapsed-time-in-swift
        let start = DispatchTime.now()
        //Error handling from: https://www.hackingwithswift.com/forums/swift/urlsession-error/780
        URLSession.shared.dataTask(with: url) { [self] data, response, error in
            if let data = data {
                print("Data fetched", url)
                print("data size:",data)
                let end = DispatchTime.now()
                let nanoTime = end.uptimeNanoseconds - start.uptimeNanoseconds // <<<<< Difference in nano seconds (UInt64)
                var timeInterval = Double(nanoTime) / 1_000_000_000 // Technically could overflow for long running tests
                timeInterval = ((round(timeInterval * 100)) / 100) //Rounds to 2 decimals
                print("Time to fetch data: \(timeInterval) seconds")

                let posts = try! JSONDecoder().decode(Post.self, from: data)
                print("JSON processed:", url)
                
                let postarray = (posts.value?.timeSeries) //all sites in an array (not including header/query info)
                //from https://stackoverflow.com/questions/63609283/swift-for-in-loop-requires-deepspeechtokenmetadata-to-conform-to-sequence (or not idk)
                var numsadded = 0
                var numsremoved = 0
                for item in (postarray!) {
                    //From: https://stackoverflow.com/questions/42523769/how-to-parse-json-data-and-eliminate-duplicates-in-swift
                    for _ in nome.names {
                        let name = (item.sourceInfo?.siteName)
//                        print("nome:", name!)
                        if nome.names.contains(name!) {
//                            print("duplicate")
                            numsremoved += 1
                            break
                        } else {
                            nome.names.append(name!)
                            //print("all names:", nome.names)
//                            print("not duplicate")
                            numsadded += 1
                            let lat = (item.sourceInfo?.geoLocation?.geogLocation?.latitude)
                            let long = (item.sourceInfo?.geoLocation?.geogLocation?.longitude)
                            completion(lat!, long!, name!)
                        }
                    }
                }
                Api.order = 1
                print("order is now 1")
                return
            }
            print("Fetch failed: \(error?.localizedDescription ?? "Unknown error")")
        }.resume()
        print("done with urlsession")
    }
}

但是,当处理多个 JSON 文件/API 请求时,此代码会崩溃,这给了我Thread 10: Fatal error: 'try!' expression unexpectedly raised an error: Swift.DecodingError.dataCorrupted(Swift.DecodingError.Context(codingPath: [], debugDescription: "The given data was not valid JSON.", underlyingError: Optional(Error Domain=NSCocoaErrorDomain Code=3840 "Invalid value around character 0." UserInfo={NSDebugDescription=Invalid value around character 0.})))在线上的错误let posts = try! JSONDecoder().decode(Post.self, from: data)

就目前在 SwiftUI 中的情况而言,我将如何去做呢?

标签: jsonswiftxcode

解决方案


推荐阅读