Reputation: 885
Aim :
To be able to display the days selected and the time picked by the user in the same row of the table view. The time should appear at the top and the days selected should appear at the bottom, both in the same row, just like an alarm clock.
Work :
This is the relationship I've got setup :
and this is how I save the days that are selected from a UITable and the time from a UIDatepicker when the save button is tapped :
@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)
}
Now that the data is once saved, I get the data :
func getData()
{
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
do
{
bobs = try context.fetch(Bob.fetchRequest())
}
catch
{
print("Fetching failed")
}
}
Attempt to get the days selected :
I tried to follow this, the below comments and a formerly deleted answer to this question to do 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
}
EDIT :
print(daysArray)
gives this :
[<Days: 0x6080000a5880> (entity: Days; id: 0xd000000000040000 <x-coredata://30B28771-0569-41D3-8BFB-D2E07A261BF4/Days/p1> ; data: <fault>)]
print(daysArray[0])
gives this :
<Days: 0x6080000a5880> (entity: Days; id: 0xd000000000040000 <x-coredata://30B28771-0569-41D3-8BFB-D2E07A261BF4/Days/p1> ; data: <fault>)
How to save days
let weekdays = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
var filteredWeekdays: [String] = []
@NSManaged public var daysSelectedbyUser: NSSet
And then
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)
}
}
Many thanks!
Upvotes: 0
Views: 1415
Reputation: 13860
OK based on your latest comment that the crash occur on this line:
cell.textLabel?.text = days.value(forKey: "daySelected") as! String
It's clearly pointing to the typo you've made in key name. You have: daySelected
and should be (based on your core data model) daysSelected
, but nevertheless it's not very good approach to use values for your core data entity and also force type like that. To make it better I suggest replacing this line with:
cell.textLabel?.text = days.daysSelected!
This should be already a String
since this is a String in CoreData
. In case it's optional (should be an optional), you shouldn't force it. I will assume that whenever data will be not there you will just display empty cell, so even better it will be:
cell.textLabel?.text = days.daysSelected ?? ""
This will produce empty string to text, whenever (for some reason) data will be not there.
EDIT
So for additional piece of code you put in your question:
In your CoreData field daysSelected
is type of String?
, right?
Then you assign timeAndDateLink
to NSSet<String>
, right? But expected value here should be NSSet<Days>
.
So let's edit your input code a bit ( i will put comment on every line):
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 */
}
I hope everything is clear in above example. You may have a problem with a compiler in that case, because if you choose generate class for entities you will endup with two func
with the same name but different parameter (in Swift this should be two different functions, but Xcode sometimes pointing to the wrong one). If you hit that problem try:
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 */
You should also rename your Days
entity to Day
to avoid future confusion that we have right now, days
as array will only be in relation from other entities to this not entity itself.
Upvotes: 1
Reputation: 2169
I don't know why no one uses FetchedResultsController, which is made for fetching NSManagedObjects into tableView, but it doesn't matter I guess...
Problem in this question is that you didn't post here your NSManagedObject class for the variable, so I cannot see which type you set there (Should be Transformable in CoreData model and [String] in NSManagedObject class...)
Ignoring all force unwraps and force casting and that mess (which you should pretty damn well fix as first, then it won't crash at least but just don't display any data...)
Days selected by user is NSSet, which it sure shouldn't be.
Please provide you NSManagedObjectClass in here so I can edit this answer and solve your problem...
Upvotes: 0