saving Core Data arrays and dictionaries - ios

referring to my previous question: Unique value of object to use in section Swift
my problem now is core data. this is code to save data following the previous code to populate section and table:
let app = UIApplication.sharedApplication().delegate as! AppDelegate
let context = app.managedObjectContext
let entity = NSEntityDescription.entityForName("Movie", inManagedObjectContext: context)!
let movie = Movie(entity: entity, insertIntoManagedObjectContext: context)
movie.title = title.text
movie.plot = plot.text
movie.genre = genre.text
context.insertObject(movie)
do {
try context.save()
} catch {
print("Could not save movie")
}
and fetch data is:
let app = UIApplication.sharedApplication().delegate as! AppDelegate
let context = app.managedObjectContext
let fetchRequest = NSFetchRequest(entityName: "Movie")
do {
let results = try context.executeFetchRequest(fetchRequest)
self.loadMovie = results as! [Movie]
} catch let err as NSError {
print(err.debugDescription)
}
}
but nothing I receive the error on loadMovie Line..
where am I wrong?

First of all, delete the line
context.insertObject(movie)
because the object has already been inserted in the let movie = line.
To load the movies you need to recreate the data structure using the insertMovie(movie : Movie) function.
let movies = try context.executeFetchRequest(fetchRequest) as! [Movie]
loadMovie.removeAll()
for movie in movies {
insertMovie(movie)
}

As the answer of your previous question suggested, the self.loadMovie now has type [String:[Movie]], so you should probably try casting results as [String:[Movie]].
Try self.loadMovie = results as! [String:[Movie]] instead.

Related

Delete all data from an attribute in CoreData

How to delete all data for example from an attribute <name>, not Entity, from attribute. I have an entity name - Users, attribute - name and I don't know how to delete all data from an attribute.
for delete the all data you can use this function
func deleteAllData(entity: String) {
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let fetchRequest = NSFetchRequest(entityName: entity)
fetchRequest.returnsObjectsAsFaults = false
do
{
let results = try managedContext.executeFetchRequest(fetchRequest)
for managedObject in results
{
let managedObjectData:NSManagedObject = managedObject as! NSManagedObject
managedContext.deleteObject(managedObjectData)
print("Deleted")
}
} catch let error as NSError {
print(error)
}
}
and after that call the function like this
deleteAllData(entity: "your Entity name")
You have to set that attibute to nil and save the context. This is how you have to remove the attribute from entity. You can't delete it like how an entity is deleted from coreData.
I just renewed Rahuld and Piet.t code for Swift and it works.
func deleteAllData(entity: String) {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let managedObjectContext = appDelegate.persistentContainer.viewContext
let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: entity)
fetchRequest.returnsObjectsAsFaults = false
do
{
let results = try managedObjectContext.fetch(fetchRequest)
for managedObject in results
{
let managedObjectData:NSManagedObject = managedObject
managedObjectContext.delete(managedObjectData)
print("Deleted")
}
} catch let error as NSError {
print(error)
}
try? managedObjectContext.save()
self.fetch(entity: "ListItem")
}
and after that call the function like this
deleteAllData(entity: "your Entity name")
in addition after you need to show the result so you will fetch your data again.
the below function can be used for it
func fetch(entity: String) {
//Veritabanındaki bilginin ekrana gelmesi için veriyi çekme işlemi
let appDelegate = UIApplication.shared.delegate as? AppDelegate
let managedObjectContext = appDelegate?.persistentContainer.viewContext
let fetchRequest = NSFetchRequest<NSManagedObject>.init(entityName: entity)
data = try! managedObjectContext!.fetch(fetchRequest)
tableView.reloadData()
}
use it like:
self.fetch(entity: "your entity name")
or like this:
fetch(entity: "your entity name")

Core Data Value returns Nil

Hi i have been working with core data to store and retrieve some values(String only) from the core data. Here is how i am storing the values.
The Function :
public func saveStringValue(forKey: String, value: String) -> Bool{
var saved = false
if self.entityName != nil && self.appDelegate != nil{
let context = appDelegate?.persistentContainer.viewContext
if context != nil{
let entity = NSEntityDescription.entity(forEntityName: self.entityName!, in: context!)
let entityHandle = NSManagedObject(entity: entity!, insertInto: context!)
entityHandle.setValue(value, forKey: forKey)
do{
try context?.save()
saved = true
}catch let error as NSError{
saved = false
print("Error : \(error)")
}
}
}
return saved
}
Here is how i call it
let historyManager = HistoryManager(entity: "SearchHistory")
let titleInserted = historyManager.saveStringValue(forKey: "title", value: book.title!)
if(titleInserted == true)
{
print("Title Inserted to Entity")
}
if let image = book.imageUrl{
let imageInserted = historyManager.saveStringValue(forKey: "image", value: image)
if imageInserted == true{
print("Image Url Inserted to Entity")
}
}
I can see in the console printed that
Title inserted into entity
ImageInserted Into entity
Here is the code to retrieve the value from core data store
public func fetchAll() -> [Book]{
var books = [Book]()
let context = self.appDelegate?.persistentContainer.viewContext
let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: self.entityName!)
//let fetchRequest: NSFetchRequest<SearchHistory> = SearchHistory.fetchRequest()
do{
let fetchedBooks = try context?.fetch(fetchRequest)
for aBook in fetchedBooks!{
if let title = aBook.value(forKey: "title"){
let book = Book(title: title as! String)
if let im = aBook.value(forKey: "image"){
book.imageUrl = im as! String
print("ImageUrl : \(im) : ")
}
else{
print("No Value for key : image")
}
books.append(book)
}
}
}
catch let error as NSError{
print("Fetch Error: \(error.localizedDescription)")
}
print("Books : \(books.count)")
return books
}
But when i run the code to retrieve the book imageUrl it returns nil and prints
No value for key : image
It retrieves the title but not the imageUrl.
Can you help me through this problem or point me to the right direction. And please do post the reason why i was getting this problem and how to solve it. Thanks.
Your problem is that your saveStringValue creates a new NSManagedObject instance each time you call it.
The first time you call saveStringValue you will create a SearchHistory object that has a title but no image. The second time you call it you will create another SearchHistory object with an image value but no title.
In my opinion, your saveStringValue function is unnecessary. Assuming your code is based on a template that resulted from clicking "use Core Data" in Xcode, you will have a SearchHistory class available and you can use something like this:
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
let newHistory = SearchHistory(context: context)
newHistory.title = book.title
newHistory.image = book.imageUrl
appDelegate.saveContext()

fetching a custom object from core data into an array

I'm having trouble fetching my object from core data. Object looks like this:
class cilj: NSObject {
var imeCilja: String
var slikaCilja: String }
My entity is called Entity and has two Attributes "tekst" and "slika", both of type String. My save func is this:
func saveImage(goalName:String, imageName:String) {
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let entityDescription = NSEntityDescription.entityForName("Entity", inManagedObjectContext:managedContext)
let thingToSaveToCD = NSManagedObject(entity: entityDescription!, insertIntoManagedObjectContext: managedContext)
thingToSaveToCD.setValue(globalGoalTitle, forKey: "tekst")
thingToSaveToCD.setValue(globalGoalImagePath, forKey: "slika")
do {
try managedContext.save()
print("managed to save to core data")
//5
// listaObjekata.append(cilj5) as! [cilj]
} catch let error as NSError {
print("Could not save \(error), \(error.userInfo)")
}
}
I use an alertController to pick up the text, and imagePicker to pick up image that I then store in documents and get the path. I store both of these in a global variables visible in the code above.
My fetch function is :
func coreDataFetch(){
//core data fetch
//1
let appDelegate =
UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
//2
let fetchRequest = NSFetchRequest(entityName: "Entity")
do {
let fetchedResults = try managedContext.executeFetchRequest(fetchRequest) as! [cilj]
listaObjekata = fetchedResults
} catch let error as NSError {
print("Could not fetch \(error), \(error.userInfo)")
}
}
I have been through ray wenderlich's article on Core Data, Apple's documentation, a couple of YT videos but I still seem to be missing something. I would greatly appreciate any help. Thanks !
EDIT - here is my cellForRowAtIndexPath
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("myCell") as! cellController
let ciljZaPrikaz = listaObjekata[indexPath.item]
cell.labelText.text = ciljZaPrikaz.imeCilja ?? "no text found"
let path = getDocumentsDirectory().stringByAppendingPathComponent(ciljZaPrikaz.slikaCilja)
cell.imageToShow.image = UIImage(contentsOfFile: path)
return cell
}
You are doing correct but just missing type casting to your model. Try below:
let fetchedResults = try managedContext.executeFetchRequest(fetchRequest)
if let results = fetchResults where results.count > 0 {
let entityModel = results[0] as? Entity
let tekst = entityModel.tekst
}
I would also like to add how I iterate through my return objects from core data:
do {
let fetchedResults = try managedContext.executeFetchRequest(fetchRequest)
listaObjekata.removeAll()
for i in 0...(fetchedResults.count-1) {
let enityModel = fetchedResults[i] as? Entity
let thisToArray = cilj(imeCilja: (enityModel?.tekst!)!, slikaCilja: (enityModel?.slika!)!)
listaObjekata.append(thisToArray)
}
} catch let error as NSError {
print("Could not fetch \(error), \(error.userInfo)")
}

Why can't I set a variable on my custom class?

I'm creating my first iOS app in Swift, and I'm stuck on a basic thing. I want to create a custom class and set a variable. I keep seeing the error "Value of type [Item] has no member [name].
This is my custom class:
import UIKit
import Foundation
import CoreData
class Item:NSManagedObject {
var name:String?
convenience init(name: String?, insertIntoManagedObjectContext context: NSManagedObjectContext!) {
let entity = NSEntityDescription.entityForName("ItemEntity", inManagedObjectContext: context)!
self.init(entity: entity, insertIntoManagedObjectContext: context)
}
}
And this is my code that tries to use it:
func editItem(id:Int, category:String, brand:String, name:String, colour:String, purchasePrice:String, purchaseDate:String, expiryDate:String) -> Int {
// vars
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let entity = NSEntityDescription.entityForName("ItemEntity", inManagedObjectContext: managedContext)
let item = NSManagedObject(entity: entity!, insertIntoManagedObjectContext: managedContext)
var listItem = [Item]()
let fetchRequest = NSFetchRequest(entityName: "ItemEntity")
// fetch the item from the core data with the same ID
do{
let predicate = NSPredicate(format: "id == %#", String(id))
fetchRequest.predicate = predicate
fetchRequest.fetchLimit = 1
let results = try managedContext.executeFetchRequest(fetchRequest)
listItem = results as! [Item]
}
catch {
let fetchError = error as NSError
print (fetchError)
}
// edit the item
listItem.name = "text" // !! THIS IS THE LINE WHICH DISPLAYS THE ERROR
// save the item
do {
try managedContext.save()
}
catch {
let saveError = error as NSError
print (saveError)
}
}
Really appreciate your help, this one seems so basic but a lot of googling hasn't helped me figure it out.
listItem is an array of Item, so if you want to change the name of one thing in this list you should specify the index you wanna change, like
listItem[0].name = "text"
Put spaces around the colon. Syntax if I'm not mistaken.
I think the problem code is here:
let item = NSManagedObject(entity: entity!, insertIntoManagedObjectContext: managedContext) as! Item
By default, the item type is NSManagedObject, so listItem have no member [name]. You need to cast down it to Item Object.

how to fetch all values in attributes using magical Records Library Swift

I am using CoreData with swift,I am facing an issue in core data while fetching.
I have an Entity with 3 attributes. I am able to save the data Successfully in attributes. only i want to fetch Data from one attribute
Image for Entity
1) Create object of ManagedObject like,
var objModel = [NSManagedObject]()
then fetch data like,
func loadData()
{
let app = UIApplication.sharedApplication().delegate as! AppDelegate
let context = app.managedObjectContext
let fetchReq = NSFetchRequest(entityName: "Student") // Your entity
var fetchResult = [NSManagedObject]()
let err : NSError! = nil
do{
fetchResult = try context.executeFetchRequest(fetchReq) as! [NSManagedObject]
self.objModel = fetchResult
self.tblList.reloadData()
}
catch{
print(err)
}
} // Call this loadData() in ViewDidLoad
Then you can get record in CellForRow method of tableview like,
self.objModel[indexPath.row].valueForKey("parent_id")
self.objModel[indexPath.row].valueForKey("task_id")
Hope this helps you.

Resources