Search code examples
jsonswiftlocalgetjson

How do I download json file from remote saver and save to bundle for offline access


I am able to download a json file from a server and put it into a TableView each time the App is opened. (see code below)

However, I also want to allow offline access using the last file downloaded. So essentially I am having trouble working out how to save the downloaded file for local access offline. Any help (especially examples) much appreciated.

 class KalkanTableController: UITableViewController {

var TableData:Array< String > = Array < String >()


override func viewDidLoad() {
super.viewDidLoad()


get_data_from_url("http://ftp.MY FILE LOCATION/kalkanInfoTest.json")
    if let path = Bundle.main.path(forResource: "kalkanInfoTest", ofType: "json") {
        do {
            let jsonData = try NSData(contentsOfFile: path, options: NSData.ReadingOptions.mappedIfSafe)
            do {
                let jsonResult: NSDictionary = try JSONSerialization.jsonObject(with: jsonData as Data, options: JSONSerialization.ReadingOptions.mutableContainers) as! NSDictionary
            } catch {}
        } catch {}
    }
}


override func numberOfSections(in tableView: UITableView) -> Int {
    return 1
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return TableData.count
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)

    cell.textLabel?.text = TableData[indexPath.row]
    return cell
}

func get_data_from_url(_ link:String)
{
    let url:URL = URL(string: link)!
    let session = URLSession.shared

    let request = NSMutableURLRequest(url: url)
    request.httpMethod = "GET"
    request.cachePolicy = URLRequest.CachePolicy.reloadIgnoringCacheData


    let task = session.dataTask(with: request as URLRequest, completionHandler: {
        (
        data, response, error) in

        guard let _:Data = data, let _:URLResponse = response  , error == nil else {

           return
        }
        self.extract_json(data!)
    }) 
    task.resume()
}


func extract_json(_ data: Data)
{
    let json: Any?
    do
    {
        json = try JSONSerialization.jsonObject(with: data, options: [])
    }
    catch
    {
        return
    }

    guard let data_list = json as? NSArray else
    {
        return
    }

    if let item_list = json as? NSArray
    {
        for i in 0 ..< data_list.count
        {
            if let item_obj = item_list[i] as? NSDictionary
            {
                if let item_name = item_obj["kalkanInfo"] as? Stri                          
                    {
                         TableData.append(item_name)

                         print(item_name)
                }
            }
        }
    }
    DispatchQueue.main.async(execute: {self.do_table_refresh()})
}

func do_table_refresh()
{
    DispatchQueue.main.async(execute: {
        self.tableView.reloadData()
        return
    })
}

}


Solution

  • You can try to save your json locally using these methods to save on disk

    override func viewDidLoad() {
        super.viewDidLoad()
    
        if readKalkanDataFromDisk() {
            extract_json(readKalkanDataFromDisk())
        } else {
            get_data_from_url("http://ftp.MY FILE LOCATION/kalkanInfoTest.json")
        }
    }
    
    func get_data_from_url(_ link:String)
    {
        let url:URL = URL(string: link)!
        let session = URLSession.shared
    
        let request = NSMutableURLRequest(url: url)
        request.httpMethod = "GET"
        request.cachePolicy = URLRequest.CachePolicy.reloadIgnoringCacheData
    
    
        let task = session.dataTask(with: request as URLRequest, completionHandler: {
            (
            data, response, error) in
    
            guard let _:Data = data, let _:URLResponse = response  , error == nil else {
    
                return
            }
            saveKalkanDataOnDisk(kalkanData: data!)
            self.extract_json(data!)
        }) 
        task.resume()
    }
    
    func saveKalkanDataOnDisk(kalkanData: Data) {
        do {
            let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
            let fileURL = documentsURL.appendingPathComponent("Kalkan.json")
            try kalkanData.write(to: fileURL, options: .atomic)
        } catch { }
    }
    
    func readKalkanDataFromDisk() -> Data? {
        let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
        let filePath = documentsURL.appendingPathComponent("Kalkan.json").path
        if FileManager.default.fileExists(atPath: filePath), let data = FileManager.default.contents(atPath: filePath) {
            return data
        }
        return nil
    }