如何使用核心数据离线显示 Json 数据

Posted

技术标签:

【中文标题】如何使用核心数据离线显示 Json 数据【英文标题】:How to show Json data in Offline using core data 【发布时间】:2018-05-23 15:11:43 【问题描述】:

在这里,我创建了带有 labelName 和 labelUsername 的表格视图, 我已经下载了 Json 数据并将其保存在名为 Details 的核心数据实体中,其中包含属性名称和用户名。 这里的表格视图在网上显示其数据... 但是离线时如何在表格视图中显示获取的数据..

请帮我写代码...

import UIKit
import CoreData

struct JsonData 
  var nameS: String
  var usernameS: String

  init(name: String, username: String)         
    self.nameS = name
    self.usernameS = username
  

class ViewController: UIViewController 

  @IBOutlet weak var tableView: UITableView!

  let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext

  var iteamsArray = [JsonData]()

  override func viewDidLoad() 
    downloadJson()
  

  func downloadJson()        
    let urlStr = "https://jsonplaceholder.typicode.com/users"
    let url = URL(string: urlStr)

    URLSession.shared.dataTask(with: url!, completionHandler: (data, response, error) in            
        guard let respData = data else 
          return
        
        guard error == nil else 
          print("error")
          return
        

        do
          let jsonObj = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as! [[String: Any]]

          for items in jsonObj 
            let nameJson = items["name"] as? String
            let usernameJson = items["username"] as? String                    
            let coreData = NSEntityDescription.insertNewObject(forEntityName: "Details", into: self.context) as! Details
            coreData.name = nameJson
            coreData.username = usernameJson

            self.iteamsArray.append(JsonData(name: nameJson!, username: usernameJson!))
          
          try self.context.save()

            //fetching from core data
          let fetchRequest : NSFetchRequest<Details> = Details.fetchRequest()
          let details = try self.context.fetch(fetchRequest)

          if details.count > 0                    
            for detail in details as [NSManagedObject]                         
              let nameCore = detail.value(forKey: "name")
              let usernameCore = detail.value(forKey: "username")      
            
          

          DispatchQueue.main.async 
            self.tableView.reloadData()
                          
        
        catch 
          print("catch error")
                    
      ).resume()
    


// MARK: - TableView

extension ViewController: UITableViewDataSource, UITableViewDelegate     
  func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
    return iteamsArray.count
  

  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 

    let cell = tableView.dequeueReusableCell(withIdentifier: "JsonCell", for: indexPath) as! JsonTableViewCell        
    let aData = iteamsArray[indexPath.row]

    cell.labelName.text = aData.nameS
    cell.labelUsername.text = aData.usernameS

    cell.selectionStyle = .none
    return cell
  

【问题讨论】:

您能否更详细地描述您的问题是什么。 我想在离线时在表格视图中显示用户名和名称,我已从 jsonObj 保存在核心数据中,但在这里我无法将获取的数据附加到 itemsArray 以显示在 tableviw @JoakimDanielson 是的,我明白了,但是您的代码的哪一部分不起作用?您正在执行获取并实现表视图数据源方法。 我无法将获取的 nameCore 和 usernameCore 附加到 itemsArray 以显示在 tableview @JoakimDanielson 当我像 self.iteamsArray.append(JsonData(name: nameCore as!String, username: usernameCore as!String)) 一样追加时。它显示错误在展开可选值时意外发现 nil 【参考方案1】:

首先忘记自定义结构。使用NSManagedObject 类作为数据源数组。

var iteamsArray = [Details]()

viewDidLoad 首先获取数据,如果数组为空,则从网络服务加载它

override func viewDidLoad() 
   let fetchRequest : NSFetchRequest<Details> = Details.fetchRequest()
   do 
       iteamsArray = try self.context.fetch(fetchRequest)
       if iteamsArray.isEmpty  
           downloadJson()
        else 
           self.tableView.reloadData()
       
     catch  print(error) 

downloadJson()替换

self.iteamsArray.append(JsonData(name: nameJson!, username: usernameJson!))

self.iteamsArray.append(coreData)

并删除这些行

//fetching from core data
   let fetchRequest : NSFetchRequest<Details> = Details.fetchRequest()
   let details = try self.context.fetch(fetchRequest)

   if details.count > 0                    
     for detail in details as [NSManagedObject]                         
       let nameCore = detail.value(forKey: "name")
       let usernameCore = detail.value(forKey: "username")      
   

cellForRow 中直接从NSManagedObject 对象中获取值

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    let cell = tableView.dequeueReusableCell(withIdentifier: "JsonCell", for: indexPath) as! JsonTableViewCell        
    let aData = iteamsArray[indexPath.row]
    cell.labelName.text = aData.name
    cell.labelUsername.text = aData.userName
    cell.selectionStyle = .none
    return cell
  

【讨论】:

以上是关于如何使用核心数据离线显示 Json 数据的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Flutter 中直接持久化存储 JSON 数据以供查询和离线使用?

如何使用 QML/QtLocation 模块在地图上显示大量离线数据?

如何缓存 Firebase 数据以供离线使用?

如何使用离线数据 + 同步创建原生 ios 应用

如何使用 JSON 预加载一对多核心数据关系

如何在我的 swift 框架中使用核心数据