【问题标题】:Fetching and displaying data from core data从核心数据中获取和显示数据
【发布时间】:2017-07-04 13:19:48
【问题描述】:

目标:

能够在表格视图的同一行中显示用户选择的日期和时间。时间应显示在顶部,所选日期应显示在底部,两者都在同一行中,就像闹钟一样。

工作:

这是我设置的关系:

这就是我如何保存从 UITable 中选择的日期以及在点击保存按钮时从 UIDatepicker 中选择的时间:

@IBAction func saveButnTapped(_ sender: AnyObject)
    {
        let context =  (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext //creates an object of a property in AppDelegate.swift so we can access it

        let bob = Bob(context: context)

        //save the time from UIDatePicker to core data
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "HH:mm"
        bob.timeToPing = dateFormatter.string(from: timePicked.date)

        // save the days selected to core data
        for weekday in filteredWeekdays
        {
            var day = Days(context: context) //create new Days object
            day.daysSelected = weekday as NSObject? //append selected weekday
            bob.addToTimeAndDaysLink(day) //for every loop add day object to bob object
        }

        //Save the data to core data
        (UIApplication.shared.delegate as! AppDelegate).saveContext()

        //after saving data, show the first view controller
        navigationController!.popViewController(animated: true)
    }

现在数据已经保存,我得到了数据:

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

    do
    {
        bobs = try context.fetch(Bob.fetchRequest())
    }
    catch
    {
        print("Fetching failed")
    }

}

尝试选择日期:

我尝试关注this、以下 cmets 和以前删除的对此问题的回答:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
    let cell = UITableViewCell()

    let bob = bobs[indexPath.row]
    cell.textLabel?.text = bob.timeToPing?.description

    // retrieve the days that are selected
    var daysArray: [Days] = []
    daysArray = bob.timeAndDaysLink?.allObjects as! [Days]

    for days in daysArray
    {
        print (days.daysSelected?.description)
        cell.textLabel?.text = days.daysSelected! as! String

    }

    return cell
}

编辑: print(daysArray) 给出了这个:

[<Days: 0x6080000a5880> (entity: Days; id: 0xd000000000040000 <x-coredata://30B28771-0569-41D3-8BFB-D2E07A261BF4/Days/p1> ; data: <fault>)]

print(daysArray[0]) 给出了这个:

<Days: 0x6080000a5880> (entity: Days; id: 0xd000000000040000 <x-coredata://30B28771-0569-41D3-8BFB-D2E07A261BF4/Days/p1> ; data: <fault>)

如何节省时间

let weekdays = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
var filteredWeekdays: [String] = []
 @NSManaged public var daysSelectedbyUser: NSSet

然后

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
    {
        selectedWeekdays()

    }

    override func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath)
    {
        selectedWeekdays()
    }

    func selectedWeekdays()
    {
        if let selectedRows = tableView.indexPathsForSelectedRows
        {
            let rows = selectedRows.filter {$0.section == 0}.map{ $0.row}
            filteredWeekdays = rows.map{ weekdays[$0] }
            print(filteredWeekdays)
        }
    }

非常感谢!

【问题讨论】:

  • 什么错误?而且您发布的代码不会出现在您的代码中。我猜想用bob 替换salawaatbobs 中的对象在哪里? bobs = try context.fetch(Bob.fetchRequest()) 是什么?
  • 嗨@Larme,我刚刚更新了代码。抱歉,打错字了。
  • 您能否显示bob 的值以及您收到的确切错误或警告消息?
  • 嗨,我如何向你展示 bob 的价值?我已经更新了原始问题以添加确切的错误。我无法将它粘贴在这里,因为它对于 cmets 来说太长了哈哈。
  • bob.timeAndDaysLink 那是 Days 对象的 NSSet,而不是 String 对象的 NSSet,这就是为什么你有演员表问题。 daysArray = bob.timeAndDaysLink?.allObjects.valueFor(key:"daysSelected") 而不是?

标签: ios swift3


【解决方案1】:

好的,根据你最近的评论,崩溃发生在这一行:

cell.textLabel?.text = days.value(forKey: "daySelected") as! String

这清楚地指向您在键名中输入的错字。你有:daySelected 并且应该是(基于你的核心数据模型)daysSelected,但是它不是为你的核心数据实体使用值并强制类型这样的好方法。为了使它更好,我建议将此行替换为:

cell.textLabel?.text = days.daysSelected!

这应该已经是String,因为这是CoreData 中的字符串。如果它是可选的(应该是可选的),你不应该强迫它。我会假设每当数据不存在时,您只会显示空单元格,所以更好的是:

cell.textLabel?.text = days.daysSelected ?? ""

每当(由于某种原因)数据不存在时,这将产生空字符串到文本。

编辑

因此,对于您在问题中添加的其他代码:

在您的 CoreData 字段中,daysSelected 的类型是 String?,对吗? 然后你将timeAndDateLink 分配给NSSet&lt;String&gt;,对吧?但是这里的期望值应该是NSSet&lt;Days&gt;

所以让我们稍微编辑一下您的输入代码(我会在每一行上添加注释):

let bob = Bob(context: context) /* create new Bob object */
for weekday in filteredWeekdays {
    var day = Days(context: context) /* create new Days object */
    day.daysSelected = weekday /* append selected weekday */
    bob.addToTimeAndDaysLink(day) /* for every loop add day object to bob object */
}   

我希望在上面的例子中一切都清楚。在这种情况下,您可能会遇到编译器问题,因为如果您选择为实体生成类,您最终会得到两个 func 名称相同但参数不同(在 Swift 中,这应该是两个不同的函数,但 Xcode 有时会指向错误的)。如果您遇到了这个问题,请尝试:

let bob = Bob(context: context) /* create new Bob object */
var output: NSMutableSet<Days> = NSMutableSet()
for weekday in filteredWeekdays {
    var day = Days(context: context) /* create new Days object */
    day.daysSelected = weekday /* append selected weekday */
    output.add(day)
}
bob.addToTimeAndDaysLink(output) /* this will assign output set to bob object */

您还应该将您的 Days 实体重命名为 Day 以避免我们现在遇到的未来混淆,days 因为数组只会与其他实体相关而不是实体本身。

【讨论】:

  • 感谢库巴的回复。 1. cell.textLabel?.text = days.daysSelected! 给出编译错误,所以 Xcode 建议我使用这个:cell.textLabel?.text = days.value(forKey: "daysSelected") as! String。它编译得很好,但在这一行崩溃并出现错误Could not cast value of type '__NSSetI' (0x1033748b0) to 'NSString' (0x10255eab8)
  • 2. cell.textLabel?.text = days.daysSelected! 给出编译错误。所以我把它改成了cell.textLabel?.text = days.daysSelected! as! String,它在这一行崩溃,错误Could not cast value of type '__NSSetI' (0x1023528b0) to 'NSString' (0x10153cab8) 3。daysSelected 的类型是Transformable,不是可选的(我需要它不是可选的)。我将daysSelected 更改为字符串并得到编译错误daysSelectedbyUser.daysSelected = NSSet(array: filteredWeekdays)cannot assign value of type 'NSSet' to type String
  • 你的'days'变量的类型是什么?你希望它是什么类型的?
  • 我相信它和daysArray是同一类型的。从此代码:daysArray = bob.timeAndDaysLink?.allObjects as! [Days] for days in daysArray { print (days.daysSelected?.description) cell.textLabel?.text = days.daysSelected?.description }
  • 说实话,我对将什么变量存储为什么类型没有任何偏好。我只想要用户可以将选择的星期几和时间添加到 UITableView 的功能。项目的下一部分是在选定的日期和时间向用户发送内部通知,以此为例:stackoverflow.com/a/40060373/1886931
【解决方案2】:

我不知道为什么没有人使用 FetchedResultsController,它是用来将 NSManagedObjects 提取到 tableView 中的,但我猜没关系...

这个问题的问题是你没有在这里发布你的变量的 NSManagedObject 类,所以我看不到你在那里设置的类型(在 CoreData 模型中应该是可转换的,在 NSManagedObject 类中应该是 [String]...)

忽略所有强制解包和强制转换以及那些混乱(你应该首先修复它,然后它至少不会崩溃,但只是不显示任何数据......)

用户选择的天数是 NSSet,它肯定不应该是。

请在此处为您提供 NSManagedObjectClass,以便我可以编辑此答案并解决您的问题...

【讨论】:

  • 嗨多米尼克,感谢您的回复。在Days 实体中,我有daysSelected 类型的Transformable 属性。我在我的代码中进行了查找,其中只有一行@NSManaged,即这个变量@NSManaged public var daysSelectedbyUser: NSSet。请参考如何节省时间下的原始问题中的代码,然后参考@IBAction func saveButnTapped(_ sender: AnyObject)的代码。谢谢。
猜你喜欢
  • 1970-01-01
  • 2016-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多