用户输入的值保存到 Core Data (?) 但未出现在表视图中

Posted

技术标签:

【中文标题】用户输入的值保存到 Core Data (?) 但未出现在表视图中【英文标题】:User-entered values saved to Core Data (?) but not appearing in table view 【发布时间】:2017-02-11 18:49:19 【问题描述】:

我一直在努力让用户输入的值在我正在处理的项目的表格视图中正确显示。

我获取用户输入值的方法是让用户在文本字段中输入信息(公司名称、股票代码和徽标的 URL),然后在按下完成按钮时调用 handleSave()

func handleSave() 

let newCompanyName = nameTextField.text
guard let newCompanyStockSymbol = stockTextField.text else 
    // handle the error how you see fit
    print("error getting text from field")
    return

let newCompanyLogo = logoTextField.text

var newCompanyStockPrice = ""

// Fetch stock price from symbol provided by user for new company
let url = URL(string: "https://query.yahooapis.com/v1/public/yql?q=select%20symbol%2C%20Ask%2C%20YearHigh%2C%20YearLow%20from%20yahoo.finance.quotes%20where%20symbol%20in%20(%22\(newCompanyStockSymbol)%22)&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys")!
let task = URLSession.shared.dataTask(with: url)  (data, response, error) in
    if error != nil 
        print(error!)
     else if let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 
        let json = JSON(data: data!)
        if let quotes = json["query"]["results"]["quote"].array 
            for quote in quotes 
                let ask = quote["Ask"].stringValue
                newCompanyStockPrice = ask
            
        
    
    self.viewController?.save(name: newCompanyName!, logo: newCompanyLogo!, stockPrice: newCompanyStockPrice)
    //self.viewController?.tableView.reloadData()

task.resume()



let cc = UINavigationController()
let companyController = CompanyController()
cc.viewControllers = [companyController]
present(cc, animated: true, completion: nil)

然后调用此save 函数,将值保存到托管上下文中。

func save(name: String, logo: String, stockPrice: String) 

guard let appDelegate =
    UIApplication.shared.delegate as? AppDelegate else 
        return


let managedContext =
    appDelegate.persistentContainer.viewContext

let entity =
    NSEntityDescription.entity(forEntityName: "Company",
                               in: managedContext)!
let company = NSManagedObject(entity: entity,
                              insertInto: managedContext)


company.setValue(stockPrice, forKey: "stockPrice")
company.setValue(name, forKey: "name")
company.setValue(logo, forKey: "logo")


do 
    try managedContext.save()
    companies.append(company)
 catch let error as NSError 
    print("Could not save. \(error), \(error.userInfo)")


tableView.reloadData()

如果我在我的handleSave() 函数中调用self.viewController?.save(name: newCompanyName!, logo: newCompanyLogo!, stockPrice: newCompanyStockPrice) 时放置一个断点,我可以看到所有三件事(newCompanyNamenewCompanyLogonewCompanyStockPrice)都有值。但是当我尝试在cellForRow 中设置新公司时,它并没有出现在我的表格视图中:

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


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

    let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath) as! Cell
    let company = companies[indexPath.row]
    let stock = company.value(forKey: "stockPrice") as? String

    // Company name labels
    cell.textLabel?.text = company.value(forKey: "name") as? String


    // Stock price underneath
    if let stock = stock 
        cell.detailTextLabel?.text = "Current stock price: \(stock)"
    

    // Logos
    DispatchQueue.main.async 
    if let url = NSURL(string: (company.value(forKey: "logo") as? String)!) 
        if let data = NSData(contentsOf: url as URL) 
            cell.logoView.image = UIImage(data: data as Data)
         else 
            cell.logoView.image = UIImage(named: "noImage")
        
    
    
    return cell

编辑:viewWillAppear

override func viewWillAppear(_ animated: Bool) 
    super.viewWillAppear(animated)

    //1
    guard let appDelegate =
        UIApplication.shared.delegate as? AppDelegate else 
            return
    

    let managedContext =
        appDelegate.persistentContainer.viewContext

    //2
    let fetchRequest =
        NSFetchRequest<NSManagedObject>(entityName: "Company")

    //3
    do 
        companies = try managedContext.fetch(fetchRequest)
     catch let error as NSError 
        print("Could not fetch. \(error), \(error.userInfo)")
    


【问题讨论】:

从核心数据加载数据的代码在哪里? @SahebRoy 抱歉,我刚刚在帖子底部添加了viewWillAppear 如果您使用故事板,请不要使用默认初始化程序 () 创建视图控制器。它们是全新的实例,当然不是故事板中的预期对象。 @vadian 我实际上并没有使用故事板,它都是程序化的 @doxi45 您应该将 CoreData 中的所有对象加载到 NSManaged 对象的数组/字典中。然后在其中循环以获取您的特定键值。 【参考方案1】:

我建议将重新加载数据的调用明确地放在主队列中。在我看来,您正在从 dataTask 完成处理程序中调用 func save(name: String, logo: String, stockPrice: String),然后在该线程上调用 reloadData

因此,在save 函数中,将其包装成这样:

DispatchQueue.main.async  [weak self] in 
    self?.tableView.reloadData()

【讨论】:

我试了一下,但表格视图仍然没有显示新公司

以上是关于用户输入的值保存到 Core Data (?) 但未出现在表视图中的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Core Data 中保存用户偏好?

在 SwiftUI 中将加载的 json 文件中的更改保存到 Core Data

Core Data 对象有时不会保存到永久存储中

如何将用户登录的 JSON 响应保存到 Core Data 中以跟踪 Swift 中的用户状态?

如何使用 Core Data 有效地保存 UI/主线程中所做的更改?

用户更新软件后如何保存Core Data?