无法将“NSManagedObject”类型的返回表达式转换为“字符串”类型?

Posted

技术标签:

【中文标题】无法将“NSManagedObject”类型的返回表达式转换为“字符串”类型?【英文标题】:Cannot convert return expression of type 'NSManagedObject' to return type 'String?' 【发布时间】:2020-05-03 08:05:22 【问题描述】:

我已经构建了一个应用程序(我的第一个),它的工作方式与我想要的一样,但是我需要向它添加 CoreData 以保存/获取我的事件。我可以看到我的事件(将信息添加到 tableview/从那里删除信息)在我打印时被保存,并且应用程序在“viewDidAppear”中“加载”。 我认为的问题是我正在保存数组,而不是 NSobject。或者我正在获取数组,而不是 NSobject?我相信我需要做的是将我的数组添加到 NSManagedObject? 像这样:

var 列表:[MealsMenu] = []。 当我这样做时,我让它工作!那太棒了!但是,我有一个在 UIPickerView 中调用此变量的 VC,一旦我将列表添加到 NSManagedObject(MealsMenu,这是我在 coredatamodel 中的实体),我就会收到以下错误消息:

无法将“NSManagedObject”类型的返回表达式转换为“String”类型的返回表达式?

我已经尝试用谷歌搜索了几天,但在我的情况下找不到任何解决方案。你们有人知道我能做什么吗?

我的实体 (MealsMenu) 有一个名为“meals”的属性,它指的是字符串。

正如我所说,如果我跳过 PickerView 所在的 VC,我就能让它工作!正在保存已添加和已删除的事件。

这是我的代码: (所有显示“List[row]”或“List[indexPath.row]”的地方都会收到此错误消息)。

添加视图控制器:

import UIKit
import CoreData

class addViewController: UIViewController, UITextFieldDelegate 

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

@IBOutlet weak var input: UITextField!
@IBAction func addToMenu(_ sender: Any) 
   if input != nil
            let newMeal = NSEntityDescription.insertNewObject(forEntityName: "MealsMenu",     into: context)
    newMeal.setValue(self.input.text, forKey: "meals")
            do 
                try context.save()
                print("SAVED")
            
            catch
                print(error)
            
            input.text = ""
        else
            print("That's not a meal!")
        
    



override func viewDidLoad() 
    super.viewDidLoad()



override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) 
    self.view.endEditing(true)


func textFieldShouldReturn(_ textField: UITextField) -> Bool 
    input.resignFirstResponder()
    return true



tableViewController:

import UIKit
import CoreData


class tableViewController: UIViewController, UITableViewDelegate, UITableViewDataSource
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
    return (List.count)



func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) ->     UITableViewCell 
    let cell = UITableViewCell(style: .default, reuseIdentifier: "cell")
    cell.textLabel?.text = List[indexPath.row]
    cell.textLabel?.textColor = UIColor.white
    cell.backgroundColor = UIColor.clear




    return(cell)



func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle,     forRowAt indexPath: IndexPath) 
    if editingStyle == UITableViewCell.EditingStyle.delete
    
        List.remove(at: indexPath.row)
        myTableView.reloadData()
    







@IBOutlet weak var myTableView: UITableView!

override func viewDidAppear(_ animated: Bool) 
    myTableView.reloadData()


override func viewDidLoad() 
    super.viewDidLoad()
    coredataClass.saveItems()
    coredataClass.loadData()



视图控制器:

import UIKit
import CoreData

var List:[MealsMenu] = []


class ViewController: UIViewController 

@IBOutlet weak var monday: UITextField!
@IBOutlet weak var tuesday: UITextField!
@IBOutlet weak var wednesday: UITextField!
@IBOutlet weak var thursday: UITextField!
@IBOutlet weak var friday: UITextField!
@IBOutlet weak var saturday: UITextField!
@IBOutlet weak var sunday: UITextField!

var daysArray = [UITextField]()

let pickerView = ToolbarPickerView()

var selectedMenu : String?

override func viewDidLoad() 
    super.viewDidLoad()

    setupDelegateForPickerView()
    setupDelegatesForTextFields()
    coredataClass.loadData()





func setupDelegatesForTextFields() 
    //appending textfields in an array
    daysArray += [monday, tuesday, wednesday, thursday, friday, saturday, sunday]
    //using the array to set up the delegates, inputview for pickerview and also the     inputAccessoryView for the toolbar
    for day in daysArray 
        day.delegate = self
        day.inputView = pickerView
        day.inputAccessoryView = pickerView.toolbar
    


func setupDelegateForPickerView() 
    pickerView.dataSource = self
    pickerView.delegate = self
    pickerView.toolbarDelegate = self



    // Create an extension for textfield delegate

extension ViewController : UITextFieldDelegate 
func textFieldDidBeginEditing(_ textField: UITextField) 
    self.pickerView.reloadAllComponents()







// Extension for pickerview and toolbar

extension ViewController : UIPickerViewDelegate, UIPickerViewDataSource 
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int 
    return List.count


func numberOfComponents(in pickerView: UIPickerView) -> Int 

    return 1


func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component:     Int) -> String? 

    return List[row]



func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component:     Int) 

    // Check if the textfield isFirstResponder.
    if monday.isFirstResponder 
       monday.text = List[row]
     else if tuesday.isFirstResponder 
        tuesday.text = List[row]
     else if wednesday.isFirstResponder 
        wednesday.text = List[row]
     else if thursday.isFirstResponder 
        thursday.text = List[row]
     else if friday.isFirstResponder 
        friday.text = List[row]
     else if saturday.isFirstResponder 
        saturday.text = List[row]
     else if sunday.isFirstResponder 
        sunday.text = List[row]
    else 
        //log errors
    




extension ViewController: ToolbarPickerViewDelegate 

func didTapDone() 
    self.view.endEditing(true)


func didTapCancel() 
    self.view.endEditing(true)
 

“ViewController”中的特定这些函数/行正在引发这些错误: 无法将“MealsMenu”类型的返回表达式转换为“String”类型的返回表达式?

 func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? 

    return List[row]



func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) 

    // Check if the textfield isFirstResponder.
    if monday.isFirstResponder 
       monday.text = List[row]
     else if tuesday.isFirstResponder 
        tuesday.text = List[row]
     else if wednesday.isFirstResponder 
        wednesday.text = List[row]
     else if thursday.isFirstResponder 
        thursday.text = List[row]
     else if friday.isFirstResponder 
        friday.text = List[row]
     else if saturday.isFirstResponder 
        saturday.text = List[row]
     else if sunday.isFirstResponder 
        sunday.text = List[row]
    else 
        //log errors
    

在“tableViewController”中,这个函数抛出了一个类似的错误: 无法将“MealsMenu”类型的值分配给“字符串”类型?

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    let cell = UITableViewCell(style: .default, reuseIdentifier: "cell")
    cell.textLabel?.text = List[indexPath.row]
    cell.textLabel?.textColor = UIColor.white
    cell.backgroundColor = UIColor.clear

非常感谢任何指导和帮助!

/ 安德烈亚斯

【问题讨论】:

你有一个MealsMenu 对象。你需要访问它的.meals 属性来获取你保存的字符串 谢谢!我尝试按照您所说的方式访问它,但我收到此错误:“属性 'meals' 不是 'MealsMenu' 的成员类型”。但它是一个成员,对吧?我在实体“MealsMenu”中有一个名为“meals”的属性。谢谢... 就是这么简单!!非常感谢!我搞定了! ?????? 【参考方案1】:

请仔细阅读错误信息,然后看看你的设计

您的数据源是MealsMenu 实例的数组,它是NSManagedObject 的子类,而返回值的类型是String?

这就是错误消息的内容:您不能返回一个预期为字符串的MealsMenu 实例

return List[row].meals

数据源声明行有两个不好的做法。

    变量名应该小写。 数组的变量名应该以复数形式命名。

后者会清楚地表明该变量包含多个项目,例如

var menus : [MealsMenu] = []

随着这一变化以及将线一分为二,错误变得更加明显

let menu = menus[row]
return menu.meals

顺便说一下,meals 的命名也令人困惑,因为它暗示着是一个数组。


cellForRow 中相应地更改行

let menu = menus[indexPath.row]
cell.textLabel?.text = menu.meals

【讨论】:

您好,感谢您的反馈!我会尽快看看这个! :) 谢谢,你可能已经明白我是新手。 :)

以上是关于无法将“NSManagedObject”类型的返回表达式转换为“字符串”类型?的主要内容,如果未能解决你的问题,请参考以下文章

如何更正错误“无法将 [NSManagedObject] 类型的值分配给 [String] 类型

Swift:返回 self 类型的数组

无法将 String 类型的值转换为预期的参数类型 NSManagedObject

Swift:无法将“NSManagedObject”类型的值转换为“data Model.Entity”

核心数据迁移:无法将“NSManagedObject_MyType”类型的值转换为“MyModule.MyType”

NSManagedObject 上的 Swift 扩展