从核心数据中获取和显示数据

时间:2017-07-04 13:19:49

标签: ios swift3

目标:

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

工作:

这是我设置的关系: enter image description here

这就是我如何保存从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,以下评论和之前删除的问题答案:

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)
        }
    }

非常感谢!

2 个答案:

答案 0 :(得分: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<String>,对吧?但是这里的期望值应该是NSSet<Days>

所以让我们稍微编辑你的输入代码(我会对每一行进行评论):

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 :(得分:0)

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

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

忽略所有的力量展开并强制施放和那些混乱(你应该非常好地修复它,然后它至少不会崩溃但只是不显示任何数据......)

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

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