Swift core data saving to multiple entity's - swift

In my view I have UITextfields for all except note which is a UITextView. When I hit save it dose save all the data but dose not link the note to the Teas entity.
#IBAction func addTea(sender: AnyObject) {
let appDel: AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate
let context: NSManagedObjectContext = appDel.managedObjectContext!
let en = NSEntityDescription.entityForName("Teas", inManagedObjectContext: context)
var newItem = dataModel(entity: en!, insertIntoManagedObjectContext: context)
newItem.teaname = teaName.text
newItem.teatype = teaType.text
newItem.amount = qty.text
newItem.temp = temp.text
newItem.time = time.text
let en1 = NSEntityDescription.entityForName("Notes", inManagedObjectContext: context)
let newNote = dataNote(entity: en1!, insertIntoManagedObjectContext: context)
newNote.note = note.text
println(note.text)
context.save(nil)
self.navigationController?.popViewControllerAnimated(true)
}
dataModel.swift
#objc(dataModel)
class dataModel: NSManagedObject {
#NSManaged var amount: String
#NSManaged var teaname: String
#NSManaged var teatype: String
#NSManaged var temp: String
#NSManaged var time: String
#NSManaged var notes: dataNote
}
notes.swift
#objc(dataNote)
class dataNote: NSManagedObject {
#NSManaged var note: String
#NSManaged var teas: dataModel
}
I think after looking at a lot of other examples I need some thing like this.
#IBAction func addTea(sender: AnyObject) {
let appDel: AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate
let context: NSManagedObjectContext = appDel.managedObjectContext!
let en = NSEntityDescription.entityForName("Teas", inManagedObjectContext: context)
var newItem = dataModel(entity: en!, insertIntoManagedObjectContext: context)
newItem.teaname = teaName.text
newItem.teatype = teaType.text
newItem.amount = qty.text
newItem.temp = temp.text
newItem.time = time.text
newItem.notesRel = noteAdd.text
But I get 'NSString' is not a subtype of 'dataNote'

Related

Core Data Fetch Relationship not working

I have a problem with fetching data from relationships.
I have a survey and i want to save the answers, the userIds and the results to core data and fetch the data at the next start of the app.
They are in arrays.
Each of it will be turned to a NSManagedObject "Wert", into the attribute "valueInt" if it is a result and "valueString" if it is an answer or an userId.
extension Wert {
#NSManaged var valueInt: NSNumber?
#NSManaged var valueString: String?
}
Afterwards it will be saved on the NSManagedObject "Message", as a NSSet on answers, results or userIds.
extension Message {
#NSManaged var absenderId: String?
#NSManaged var absenderName: String?
#NSManaged var datum: NSDate?
#NSManaged var gruppenId: String?
#NSManaged var image: NSData?
#NSManaged var latitude: NSNumber?
#NSManaged var longitude: NSNumber?
#NSManaged var messageId: String?
#NSManaged var question: String?
#NSManaged var sound: NSData?
#NSManaged var text: String?
#NSManaged var answers: NSSet?
#NSManaged var results: NSSet?
#NSManaged var userIDs: NSSet?
}
I think that this is working, because after the "addObjectsFromArray" AnswersSet contains some values.
func saveCoreData(AbsenderName: String, AbsenderID: String, Text: String?, Image: NSData?, Datum: NSDate, Latitude: Double?, Longitude: Double?, MessageId: String, Sound: NSData?, question: String?, answers : [String]?, results : [Int]?, userIDs: [String]?) {
let newMessage = NSEntityDescription.insertNewObjectForEntityForName("Message", inManagedObjectContext: context) as NSManagedObject
newMessage.setValue(AbsenderID, forKey: "absenderId")
newMessage.setValue(AbsenderName, forKey: "absenderName")
newMessage.setValue(Text, forKey: "text")
newMessage.setValue(Image, forKey: "image")
newMessage.setValue(Latitude, forKey: "latitude")
newMessage.setValue(Longitude, forKey: "longitude")
newMessage.setValue(Datum, forKey: "datum")
newMessage.setValue(GroupId, forKey: "gruppenId")
newMessage.setValue(MessageId, forKey: "messageId")
newMessage.setValue(Sound, forKey: "sound")
if question != nil && answers != nil && results != nil && userIDs != nil {
newMessage.setValue(question, forKey: "question")
var AnswersArray = [NSManagedObject]()
var ResultsArray = [NSManagedObject]()
var userIDsArray = [NSManagedObject]()
for var index = 0; index < answers?.count ; ++index {
let newWert = NSEntityDescription.insertNewObjectForEntityForName("Wert", inManagedObjectContext: context) as NSManagedObject
newWert.setValue(answers![index], forKey: "valueString")
AnswersArray.append(newWert)
}
for var index = 0; index < results?.count ; ++index {
let newWert = NSEntityDescription.insertNewObjectForEntityForName("Wert", inManagedObjectContext: context) as NSManagedObject
newWert.setValue(results![index], forKey: "valueInt")
ResultsArray.append(newWert)
}
for var index = 0; index < userIDs?.count ; ++index {
let newWert = NSEntityDescription.insertNewObjectForEntityForName("Wert", inManagedObjectContext: context) as NSManagedObject
newWert.setValue(userIDs![index], forKey: "valueString")
userIDsArray.append(newWert)
}
let answersSet = newMessage.mutableSetValueForKey("answers")
let resultsSet = newMessage.mutableSetValueForKey("results")
let userIdsSet = newMessage.mutableSetValueForKey("userIDs")
answersSet.addObjectsFromArray(AnswersArray)
resultsSet.addObjectsFromArray(ResultsArray)
userIdsSet.addObjectsFromArray(userIDsArray)
}
do {
try context.save()
}
catch _ {
print("Error")
}
}
But when i try to fetch the saved values with mutableSetValueForKey(), they contain 0 objects. Everything else is working.
func loadCoreData() -> Int {
var x : [AnyObject] = [AnyObject]()
let request = NSFetchRequest(entityName: "Message")
request.resultType = NSFetchRequestResultType.DictionaryResultType
request.predicate = NSPredicate(format: "gruppenId = %#", GroupId)
let sort1 = NSSortDescriptor(key: "datum", ascending: true)
request.sortDescriptors = [sort1]
do {
x = try context.executeFetchRequest(request)
for (var i = 0 ; i < x.count; ++i ) {
let Absender = x[i].valueForKey("absenderName") as! String
let AbsenderID = x[i].valueForKey("absenderId") as! String
let Text : String? = x[i].valueForKey("text") as? String
let Image : NSData? = x[i].valueForKey("image") as? NSData
let Sound : NSData? = x[i].valueForKey("sound") as? NSData
let Date : NSDate = x[i].valueForKey("datum") as! NSDate
let GruppenID : String = x[i].valueForKey("gruppenId") as! String
let MessageID : String = x[i].valueForKey("messageId") as! String
let longitude : Double? = x[i].valueForKey("longitude") as? Double
let latitude : Double? = x[i].valueForKey("latitude") as? Double
let question : String? = x[i].valueForKey("question") as? String
let answers = x[i].mutableSetValueForKey("answers") as? NSMutableSet
let results = x[i].mutableSetValueForKey("results") as? NSMutableSet
let userIds = x[i].mutableSetValueForKey("userIDs") as? NSMutableSet
}
}
}
It seems that the answers, results etc. are one-to-many relationships. In this case, it is always safer (and more concise) to simply set the to-one relationship.
Thus, rather than maintaining a clumsy array and dealing with mutableSetValueForKey, you could simply use the inverse relationship:
newWert.message = newMessage
NB: Please adopt the convention of using lowerCase variable names to avoid confusion with class names.
NB2: I strongly advise using NSManagedObject subclasses and using dot.notation to set and get values. With one stroke, all the variables you define in your many lines of code above would become utterly superfluous.

CoreData and Swift: contents gets swapped

I am new to swift and have a problem with CoreData: I can save and load to and from my CoreData store. But when I load the saved data from CoreData the data has been rearranged. I don't want this to happen. How do I solve this?
My code is this:
Meetings.swift
import Foundation
import CoreData
class Meetings: NSManagedObject {
#NSManaged var meetingTimeLeft: NSNumber
#NSManaged var title: String
#NSManaged var date: NSDate
#NSManaged var timeFrom: NSDate
#NSManaged var timeTo: NSDate
#NSManaged var timeFromActual: NSDate
#NSManaged var timeToActual: NSDate
#NSManaged var location: String
#NSManaged var locationRoom: String
#NSManaged var meetingGoals: String
#NSManaged var purpose: String
#NSManaged var averageHourlyCost: NSNumber
#NSManaged var completed: NSNumber
#NSManaged var durationActual: NSNumber
#NSManaged var durationPlanned: NSNumber
#NSManaged var persons: NSSet
#NSManaged var agendas: NSSet
#NSManaged var minutes: NSSet
#NSManaged var relationship: NSManagedObject
#NSManaged var startSetting: StartSetting?
}
extension Meetings {
func addPer(value: Person) {
self.mutableSetValueForKey("persons").addObject(value)
}
func removePer(value: Person) {
self.mutableSetValueForKey("persons").removeObject(Person)
//self.mutableSetValueForKey("persons").addObject(value)
}
func getPer() -> [Person] {
var persons: [Person]
persons = self.persons.allObjects as! [Person]
return persons
}
func addAgenda(value: AgendaItem) {
self.mutableSetValueForKey("agendas").addObject(value)
}
func removeAgenda(value: AgendaItem) {
self.mutableSetValueForKey("agendas").removeObject(AgendaItem)
//self.mutableSetValueForKey("persons").addObject(value)
}
func getAgenda() -> [AgendaItem] {
var agendas: [AgendaItem]
agendas = self.agendas.allObjects as! [AgendaItem]
return agendas
}
func getAgendaItem(i: Int) -> AgendaItem {
var agendas: [AgendaItem]
agendas = self.agendas.allObjects as! [AgendaItem]
let agendaItem = agendas[i]
return agendaItem
}
}
person.swift
import Foundation
import CoreData
class Person: NSManagedObject {
#NSManaged var name: String
#NSManaged var email: String
#NSManaged var phone: NSNumber
#NSManaged var title: String
#NSManaged var company: String
#NSManaged var photo: NSData
#NSManaged var meeting: Meetings
}
AgendaItem.swift
import Foundation
import CoreData
class AgendaItem: NSManagedObject {
#NSManaged var agendaItemTitle: String
#NSManaged var presenter: String
#NSManaged var durationPlanned: NSNumber
#NSManaged var durationActual: NSNumber
#NSManaged var filePresentation: NSData
#NSManaged var fileSupporting: NSData
#NSManaged var agendaTimeStart: NSDate
#NSManaged var meeting: Meetings
}
when saving i do like this:
internal var meetingsModels = [Meetings]()
public let managedObjectContext = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
managedObjectContext?.deleteObject(meetingsModels[meetingsIndexPassed.row]) meetingsModels.removeAtIndex(meetingsIndexPassed.row)
let entityDescription = NSEntityDescription.entityForName("Meetings", inManagedObjectContext: managedObjectContext!)
let entityDescription2 = NSEntityDescription.entityForName("Person", inManagedObjectContext: managedObjectContext!)
let entityDescription3 = NSEntityDescription.entityForName("AgendaItem", inManagedObjectContext: managedObjectContext!)
let meetings = Meetings(entity: entityDescription!, insertIntoManagedObjectContext: managedObjectContext)
meetings.title = meetingTitle_txt.text!
meetings.date = lDate
meetings.timeFrom = lStartTime
meetings.timeTo = lEndTime
meetings.location = address_txt.text!
meetings.purpose = details[0]
meetings.meetingGoals = details[1]
meetings.locationRoom = details[2]
meetings.durationPlanned = meetingsEditPassed.durationPlanned
meetings.completed = false
for var i = 0; i < personsEdit.count; i++ {
let person = Person(entity: entityDescription2!, insertIntoManagedObjectContext: managedObjectContext)
person.name = personsEdit[i].name
person.email = personsEdit[i].email
person.title = personsEdit[i].title
person.company = personsEdit[i].company
person.phone = personsEdit[i].phone
meetings.addPer(person)
}
for var i = 0; i < agendaEdit.count; i++ {
let agenda = AgendaItem(entity: entityDescription3!, insertIntoManagedObjectContext: managedObjectContext)
agenda.agendaItemTitle = agendaEdit[i].agendaItemTitle
//print(agendaEdit[i].agendaItemTitle)
agenda.presenter = agendaEdit[i].presenter
agenda.durationPlanned = agendaEdit[i].durationPlanned
meetings.addAgenda(agenda)
}
do {
try managedObjectContext?.save()
} catch let error1 as NSError {
print("\(error1)")
}
meetingsModels.append(meetings)
when loading i do this:
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
//1
let appDelegate =
UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext!
//2
let fetchRequest = NSFetchRequest(entityName:"Meetings")
//fetchRequest.sortDescriptors = nil
//3
let fetchedResults: [Meetings]
do {
try
fetchedResults = (managedContext.executeFetchRequest(fetchRequest) as? [Meetings])!
if let results: [Meetings] = fetchedResults {
var temp = [Meetings]()
var temp2 = [Meetings]()
for tmp: Meetings in results {
temp.append(tmp)
if tmp.completed.boolValue {
temp2.append(tmp)
}else {
}
}
meetingsModels = temp
meetingsModels2 = temp2
} else {
}
} catch let error1 as NSError {
print("could not fetch meetings: \(error1), \(error1.userInfo)")
}
}
i hope that some of you can help me.
Your meetings data is being "rearranged" just because your Meetings don't belong to any ordered relationship. I'm not able to run your code on my side. However, I can recommend you one of the following:
Use ordered relations any time you want to make sure the order of
data is preserved any time you fetch it.
Use the
sortDescriptors property on your fetch requests. When you
create one, you can add a sort descriptor to it in order to
arrange data.

One-to-Many Relationship in Swift Core Data

I'm building a journal app where you create a FocusArea object, which then contains 30 journal Entry objects.
So I created a one-to-many relationship in my data model.
Then I implemented two NSManagedObject Classes:
#objc(FocusArea)
class FocusArea: NSManagedObject {
#NSManaged var focusName: String
#NSManaged var focusStart: NSDate
#NSManaged var focusEnd: NSDate
#NSManaged var completeFlag: Bool
//#NSManaged var entries: NSSet
var entries: NSMutableOrderedSet {
return self.mutableOrderedSetValueForKey("entries")
}
}
#objc(Entry)
class Entry: NSManagedObject {
#NSManaged var entryJournal: String
#NSManaged var entryDate: NSDate
#NSManaged var completeFlag: Bool
#NSManaged var entryStatus: Bool
#NSManaged var focus: FocusArea
}
I'm able to add a FocusArea with no problems, but when I try to create 30 Entry objects and store in FocusArea.entries, everything keeps crashing.
What's the correct way to add multiple Entry objects to the FocusArea object?
Am I way off here?
#IBAction func saveFocusArea(sender: AnyObject) {
if txtFocusName.text != nil {
let appDel: AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let context: NSManagedObjectContext = appDel.managedObjectContext!
//create new focus area
let entFocus = NSEntityDescription.entityForName("FocusArea", inManagedObjectContext: context)
let newFocus = FocusArea(entity:entFocus!, insertIntoManagedObjectContext: context)
newFocus.focusName = txtFocusName.text!
newFocus.focusStart = NSDate()
newFocus.focusEnd = NSDate().dateByAddingTimeInterval(60*60*24*30)
newFocus.completeFlag = false
//initialize 30 new entries into core data
let entEntry = NSEntityDescription.entityForName("Entry", inManagedObjectContext: context)
for var i = 0; i < 30; i++ {
let newEntry = Entry(entity:entEntry!, insertIntoManagedObjectContext: context)
let c = Double(i)
newEntry.entryDate = NSDate().dateByAddingTimeInterval(60*60*24*c)
newEntry.entryJournal = ""
newEntry.entryStatus = false
newEntry.completeFlag = false
//THIS IS THE PROBLEM AREA
newFocus.entries.append(newEntry)
}
do {
try context.save()
} catch {
print("There's a problem!")
}
}
}
I figured it out. All I had to do was:
newEntry.focus = newFocus.
So instead of setting the relationship between the parent to the child, set it from the child to the parent.

Relationship with Swift

I have a code:
extension Person {
#NSManaged var name: String?
#NSManaged var personDevice: NSSet?
}
extension Device {
#NSManaged var deviceName: String?
#NSManaged var device: Person?
}
class Person: NSManagedObject {
// Insert code here to add functionality to your managed object subclass
func addNewDevice(device:Device) {
let newDevice = self.mutableSetValueForKey("personDevice")
newDevice.addObject(device)
}
}
and call this:
let managedObjectContext = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
let entityDescription = NSEntityDescription.entityForName("Person", inManagedObjectContext: managedObjectContext)
let contact = Person(entity: entityDescription!, insertIntoManagedObjectContext: managedObjectContext)
let entityDevice = NSEntityDescription.entityForName("Device", inManagedObjectContext: managedObjectContext)
let device = Device(entity: entityDevice!, insertIntoManagedObjectContext: managedObjectContext)
contact.name = "Test"
device.deviceName = "3310"
contact.addNewDevice(Device())
But I get error.
"CoreData: error: Failed to call designated initializer on
NSManagedObject class 'Test.Device' "
How fix it, please?

Swift: Could not cast value of type 'NSManagedObject_' to 'dataModel.Entity'

I don't really know what I have to explain or not, don't hesitate to ask me more code or explanations if needed..
I'm trying to use a CoreData to stock datas gotten from an http POST request and then print them on an UITableView.
I successfully get datas from the JSON and send them to the database. The problem is when I try to send the datas from the database to the UITableView.
It's my first time with the Core Data, so to understand how it works, I have followed this tutorial I adapted to my situation: https://www.youtube.com/watch?v=UniafUWsvLg
This is the Entity in which I'm working:
import Foundation
import CoreData
class Task: NSManagedObject {
#NSManaged var summary: String
#NSManaged var status: String
#NSManaged var responsable: String
#NSManaged var id: String
#NSManaged var detail: String
#NSManaged var date: String
#NSManaged var context: String
}
This is a part of the code preparing the work on the CoreData, I have some comments on it:
//Preparing variables used to get and send datas from DB
let context = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
var nTask: Task? = nil
var frc : NSFetchedResultsController = NSFetchedResultsController()
func getFetchedResultsController() -> NSFetchedResultsController{
frc = NSFetchedResultsController(fetchRequest: taskFetchRequest(), managedObjectContext: context!, sectionNameKeyPath: nil, cacheName: nil)
return frc
}
func taskFetchRequest() -> NSFetchRequest {
//On which Entity are we working?
let fetchRequest = NSFetchRequest(entityName: "Task")
//Which attribute get the Order by. There summary as Ascending
let sortDescriptor = NSSortDescriptor(key: "summary", ascending: true)
fetchRequest.sortDescriptors = [sortDescriptor]
return fetchRequest
}
Now I have declared this, I set on the viewDidLoad the delegate of the getFetchedResultsController to self:
override func viewDidLoad() {
super.viewDidLoad()
frc = getFetchedResultsController()
frc.delegate = self
frc.performFetch(nil)
}
This is how I create the link to the database to get datas from:
//Link creation to SQLite DB
let context = self.context
let ent = NSEntityDescription.entityForName("Task", inManagedObjectContext: context!)
let nTask = Task(entity: ent!, insertIntoManagedObjectContext: context)
then I populate my nTask with String extracted from the JSON, I save the context and I reload the DataBase:
for dict in json2 {
var apps = [String]()
if let summary = dict["summary"] as? String{
nTask.summary = summary
}
if let description = dict["description"] as? String{
nTask.detail = description
}
if let context = dict["context"] as? String{
nTask.context = context
}
if let due = dict["due"] as? String {
nTask.date = due
}
if let status = dict["status"] as? String{
nTask.status = status
}
if let responsible = dict["responsible"] as? String{
nTask.responsable = responsible
}
if let id = dict["id"] as? String{
nTask.id = id
}
}
context?.save(nil)
println(nTask)
self.tableView.reloadData()
When we use a TableView, we have to declare cellForRowAtIndexPath and numberOfRowsInSection, these are them:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell: UITableViewCell = self.tableView.dequeueReusableCellWithIdentifier("customTableViewCell") as! UITableViewCell
let task = frc.objectAtIndexPath(indexPath) as! Task
cell.textLabel?.text = task.summary
var detail = task.detail
var context = task.context
var due = task.date
var status = task.status
var responsible = task.responsable
cell.detailTextLabel?.text = "Contexte: \(context), Detail: \(detail), Status: \(status), Ending date: \(due)"
return cell
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let numberOfRowsInSection = frc.sections?[section].numberOfObjects
return numberOfRowsInSection!
}
The error is line let task = frc.objectAtIndexPath(indexPath) as! Task on my cellForRowAtIndexPath.
The complete error is: Could not cast value of type 'NSManagedObject_Task_' (0x79ebd190) to 'TaskManager.Task' (0xa1f08).
I search for more than half day and no results. I really don't understand what's happening to me...
I'm sorry to give so much code but I haven't any idea of where or why I have this error, so I have to give as informations as possible..
Thanks you so much for having read to the end, thank you for your help.
Regards.
Edit:
I have finally solved my problem by doing several things. I don't really know which one solved... I added the annotation #objc(Task) on my Task class,on my DataModel I changed the class to Task, checked my NSManagedObjectModel was let modelURL = NSBundle.mainBundle().URLForResource("TaskManager", withExtension: "momd")! and the url let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent("TaskManager.sqlite") on the AppDelegate..
Thank you for your help.
I experienced a similar issue, and in my case what worked was to add this #objc(NameOfClass) above my core data class definition. Thank you!
Try:
let task = frc.objectAtIndexPath(indexPath) as NSManagedObject
Perhaps the real problem you have is not the extraction in its "cellForRowAtIndexPath" is in its "FOR":
for dict in json2 {
...
if let summary = json2["summary"] as? String{
nTask.summary = summary
}
...
You it is seeking "summary" of "dict" when you should get it from "json2"