Saya telah mengikuti Json di lokal saya

{
"country":[
      {
         "alpha2Code":"AF",
         "alpha3Code":"AFG",
         "flag":"https://raw.githubusercontent.com/DevTides/countries/master/afg.png",
         "name":"Afghanistan",
         "code":"+93"
      },
      {
         "alpha2Code":"AX",
         "alpha3Code":"ALA",
         "flag":"https://raw.githubusercontent.com/DevTides/countries/master/ala.png",
         "name":"Aland Islands",
         "code":"+358"
      },
      {
         "alpha2Code":"AL",
         "alpha3Code":"ALB",
         "flag":"https://raw.githubusercontent.com/DevTides/countries/master/alb.png",
         "name":"Albania",
         "code":"+355"
      }
]
}

Dalam hal ini saya mencoba memuat nama file ini dan mengurai Json menggunakan kode di bawah ini

func readLocalJSONFile(forName name: String) -> Data? {
        do {
            if let filePath = Bundle.main.path(forResource: name, ofType: "json") {
                let fileUrl = URL(fileURLWithPath: filePath)
                let data = try Data(contentsOf: fileUrl)
                return data
            }
        } catch {
            print("error: \(error)")
        }
        return nil
    }
    
    func parseJson(jsonData: Data) -> countryCode? {
        do {
            let decodedData = try JSONDecoder().decode(sampleModel.self, from: jsonData)
            return decodedData
        } catch {
            print("error: \(error)")
        }
        return nil
    }

Tapi di sini juga memperbarui kelas sampleModel saya.

Pernyataan masalah :

Setelah parsing (sebelum memperbarui model) saya perlu mengunduh gambar url kunci "bendera" ke lokal saya dan kemudian menggunakan jalur gambar lokal alih-alih url di "bendera" kunci ini.

Setelah itu saya ingin menambahkan data ini ke dalam model saya.

Adakah ide perubahan apa yang perlu saya lakukan?

0
JOhn Mic 11 Mei 2021, 12:31

2 jawaban

Jawaban Terbaik

Saya baru saja membuat beberapa perubahan pada fungsi parseJson Anda, harap periksa dan beri tahu saya.

class SOViewController: UIViewController {

//MARK:- Outlets

//MARK:- Variables
var arrImagesUrls = [URL]()
var arrCountries = [Country]()
var dictMainJson = [String:Any]()

//MARK:- UIViewController Methods
override func viewDidLoad() {
    super.viewDidLoad()
    let data = readLocalJSONFile(forName: "Country")
    let response = parseCodableJson(jsonData: data!)
    arrCountries = (response?.country)!
    print(arrCountries)
    arrImagesUrls.removeAll()
    for i in 0...arrCountries.count - 1{
        downloadFromServer(url: URL(string: arrCountries[i].flag!)!)
    }
    print(arrImagesUrls)
    changeFlagProperty(arrLocalUrls: arrImagesUrls)
}

//MARK:- Helpers
func readLocalJSONFile(forName name: String) -> Data? {
    do {
        if let filePath = Bundle.main.path(forResource: name, ofType: "json") {
            let fileUrl = URL(fileURLWithPath: filePath)
            let data = try Data(contentsOf: fileUrl)
            return data
        }
    } catch {
        print("error: \(error)")
    }
    return nil
}

func parseCodableJson(jsonData: Data) -> Response? {
    do {
        let decodedData = try JSONDecoder().decode(Response.self, from: jsonData)
        let jsonResult = try JSONSerialization.jsonObject(with: jsonData, options: .mutableLeaves)
        let result = jsonResult as! [String : Any]
        dictMainJson = result
        return decodedData
    } catch {
        print("error: \(error)")
    }
    return nil
}

//MARK:- Get Directory Path
func getDocumentsDirectory() -> URL {
    let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
    let documentsDirectory = paths[0]
    let appURL = documentsDirectory.appendingPathComponent("APP_NAME")
    if !FileManager.default.fileExists(atPath: appURL.path) {
        try! FileManager.default.createDirectory(at: appURL, withIntermediateDirectories: true, attributes: nil)
    }
    return appURL
}

//MARK:- Download Zip From Server
func downloadFromServer(url:URL) {
    let zipFileName = url.lastPathComponent
    let downloadPath = self.getDocumentsDirectory()
    
    let newFolder = downloadPath.appendingPathComponent("Flag")
    if !FileManager.default.fileExists(atPath: newFolder.path) {
        do {
            try FileManager.default.createDirectory(atPath: newFolder.path, withIntermediateDirectories: true, attributes: nil)
        } catch let error {
            print(error.localizedDescription)
        }
    }
    let fileUrl = newFolder.appendingPathComponent(zipFileName)

    if FileManager.default.fileExists(atPath: fileUrl.path) {
        print("FILE AVAILABLE")
        //get images from local folder
        arrImagesUrls.append(fileUrl)
    } else {
        print("FILE NOT AVAILABLE")
        let urlSession = URLSession(configuration: .default, delegate: self, delegateQueue: OperationQueue())
        let downloadTask = urlSession.downloadTask(with: url)
        downloadTask.resume()
    }
}

func changeFlagProperty(arrLocalUrls:[URL]) {
    let arrDict : [[String:Any]] = (dictMainJson["country"] as? [[String:Any]])!
    var arrDicts = [[String:Any]]()
    for (i,dict) in arrDict.enumerated() {
        var dictData = dict
        dictData.updateValue("\(arrLocalUrls[i])", forKey: "flag")
        arrDicts.append(dictData)
    }
    dictMainJson["country"] = arrDicts
    if let jsonData = try? JSONSerialization.data(withJSONObject: dictMainJson,options: []) {
        print(jsonData)
        let response = parseCodableJson(jsonData: jsonData)
        arrCountries = (response?.country)!
        print(arrCountries)
    }
}
}

extension SOViewController : URLSessionDownloadDelegate {
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
    print("File Downloaded Location- ",  location)
    
    guard let url = downloadTask.originalRequest?.url else {
        return
    }
    
    let downloadPath = self.getDocumentsDirectory()
    let newFolder = downloadPath.appendingPathComponent("Flag")
    if !FileManager.default.fileExists(atPath: newFolder.path) {
        do {
            try FileManager.default.createDirectory(atPath: newFolder.path, withIntermediateDirectories: true, attributes: nil)
        } catch let error {
            print(error.localizedDescription)
            return
        }
    }
    
    let fileUrl = newFolder.appendingPathComponent(url.lastPathComponent)
    
    if !FileManager.default.fileExists(atPath: fileUrl.path) {
        do{
            try FileManager.default.copyItem(at: location, to: fileUrl)
            print("File Downloaded Location- \(fileUrl)" )
            arrImagesUrls.append(fileUrl)
        }catch let error {
            print("Copy Error: \(error.localizedDescription)")
        }
    }else {
        print("File Downloaded Location- \(fileUrl)" )
        arrImagesUrls.append(fileUrl)
    }
}
}

Respons.swift

import Foundation

struct Response : Codable {

        let country : [Country]?

        enum CodingKeys: String, CodingKey {
                case country = "country"
        }
    
        init(from decoder: Decoder) throws {
                let values = try decoder.container(keyedBy: CodingKeys.self)
                country = try values.decodeIfPresent([Country].self, forKey: .country)
        }

}

Country.swift

import Foundation

struct Country : Codable {

        let alpha2Code : String?
        let alpha3Code : String?
        let code : String?
        let flag : String?
        let name : String?

        enum CodingKeys: String, CodingKey {
                case alpha2Code = "alpha2Code"
                case alpha3Code = "alpha3Code"
                case code = "code"
                case flag = "flag"
                case name = "name"
        }
    
        init(from decoder: Decoder) throws {
                let values = try decoder.container(keyedBy: CodingKeys.self)
                alpha2Code = try values.decodeIfPresent(String.self, forKey: .alpha2Code)
                alpha3Code = try values.decodeIfPresent(String.self, forKey: .alpha3Code)
                code = try values.decodeIfPresent(String.self, forKey: .code)
                flag = try values.decodeIfPresent(String.self, forKey: .flag)
                name = try values.decodeIfPresent(String.self, forKey: .name)
        }

}
1
RB's 12 Mei 2021, 08:26

Saya telah mencoba metode berikut dan berfungsi dengan baik sekarang

struct CountryCodeList : Decodable {
    var alpha2Code: String?
    var alpha3Code: String?
    var flag      : String?
    var name      : String?
    var code      : String?
}

public struct CountryCodeListModel : Decodable {
    var data      : [CountryCodeList]?
}

private var completionBlocks: ((String) -> Void)?
var cclm: CountryCodeListModel?


//Method to load json

func readLocalJSONFile(forName name: String) {
    do {
        if let filePath = Bundle.main.path(forResource: name, ofType: "json") {
            let fileUrl = URL(fileURLWithPath: filePath)
            let data = try Data(contentsOf: fileUrl)
            if let countryCodeObject = parse(jsonData: data) {
                cclm = countryCodeObject
                print(cclm?.data?[1].alpha2Code ?? "")  //Printing Correct Value
            }
        }
    } catch {
        print("error: \(error)")
    }
}



func parse(jsonData: Data) -> CountryCodeListModel?{
    var dataArray : [Dictionary<String,Any>] = [[:]]
    var country = Dictionary<String,Any>()
    var modelData = Dictionary<String,Any>()
    do {
        // make sure this JSON is in the format we expect
        if let json = try JSONSerialization.jsonObject(with: jsonData, options: []) as? Dictionary<String,Any> {
            dataArray.removeAll()
            for item  in json["data"] as! [Dictionary<String, Any>] {
                country = item
                
                let url = URL(string: country["flag"] as? String ?? "")
                let data = try? Data(contentsOf: url!) //make sure your image in this url does exist, otherwise unwrap in a if let check / try-catch
                let image = UIImage(data: data!)
                let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
                let fileName = url?.lastPathComponent // name of the image to be saved
                let fileURL = documentsDirectory.appendingPathComponent(fileName ?? "")
                if let data = image?.jpegData(compressionQuality: 1.0){
                    do {
                        try data.write(to: fileURL)
                        country["flag"] = fileURL.absoluteString
                        //print("file saved")
                        //urlAsString = fileURL.absoluteString
                    } catch {
                        print("error saving file:", error)
                    }
                }
                
                dataArray.append(country)
                country.removeAll()
                
                    
                
            }
            modelData["data"] = dataArray
            //print(modelData)
            let jsonData1 = try JSONSerialization.data(withJSONObject: modelData, options: [])
            
            do {
                    let decodedData = try JSONDecoder().decode(CountryCodeListModel.self, from: jsonData1)
                
                    return decodedData
                } catch {
                    print("error: \(error)")
                }
            
        }
    } catch let error as NSError {
        print("Failed to load: \(error.localizedDescription)")
    }
    return nil
}
0
JOhn Mic 11 Mei 2021, 19:30