I am making a list app and have a Coredata model with two attributes in it (One for item and one for details)
I can save and input data and it will be displayed correctly but when i close and reopen the app, everything has its own cell.
Any help guys?
Code For CellAtIndex
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell")! as UITableViewCell
let item = listItems[indexPath.row]
let detailed = detailedItems[indexPath.row]
cell.textLabel?.text = item.valueForKey("item") as? String
cell.detailTextLabel?.text = detailed.valueForKey("detail") as? String
return cell
}
Code For ViewWillAppear
verride func viewWillAppear(animated: Bool) {
//Load First Item
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let fetchrequest = NSFetchRequest(entityName: "ListEnt")
do{
let results = try managedContext.executeFetchRequest(fetchrequest)
listItems = results as! [NSManagedObject]
detailedItems = results as! [NSManagedObject]
}catch{
print("Error")
}
}
Here is the code for saving, I have a dialog box appear, with to text field, and each text field has its own save function
//Saving Items//
func saveItem(itmToSave: String){
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let entity = NSEntityDescription.entityForName("ListEnt", inManagedObjectContext: managedContext)
let item = NSManagedObject(entity: entity!, insertIntoManagedObjectContext: managedContext)
item.setValue(itmToSave, forKey: "item")
do{
try managedContext.save()
listItems.append(item)
}catch{
print("Saving Main Item")
}
}
//Saving Details
func saveItem2(itmToSave2: String){
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let entity = NSEntityDescription.entityForName("ListEnt", inManagedObjectContext: managedContext)
let item2 = NSManagedObject(entity: entity!, insertIntoManagedObjectContext: managedContext)
item2.setValue(itmToSave2, forKey: "detail")
do{
try managedContext.save()
detailedItems.append(item2)
}catch{
print("Saving deatil Item")
}
}
Pictures of the problem
How it looks when you input data (Correct way)
How it looks when you close and reopen the app
Cheers Guys
Related
I am trying to save 2 different string entities to core data. Then display with a tableview my function below saves the data. Right now the code is being displayed on different tableview cells. Meaning entity a is being displayed on cell 1 and entity b is being displayed on cell 2. They are not being printed into the same cell.
var itemName2 : [NSManagedObject] = []
var itemName : [NSManagedObject] = []
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return itemName.count
}
func enterData() {
let appDeldeaget = UIApplication.shared.delegate as! AppDelegate
let context = appDeldeaget.persistentContainer.viewContext
let entity = NSEntityDescription.entity(forEntityName: "Data", in: context)
let theTitle = NSManagedObject(entity: entity!, insertInto: context)
theTitle.setValue(hits.text, forKey: "hits")
let theTitle2 = NSManagedObject(entity: entity!, insertInto: context)
theTitle2.setValue(atBats.text, forKey: "atBATS")
do {
try context.save()
itemName.append(theTitle)
itemName.append(theTitle2)
} catch {
print("d")
}
self.theScores.reloadData()
hits.text = ""
hits.resignFirstResponder()
}
try this,
func enterData() {
let appDeldeaget = UIApplication.shared.delegate as! AppDelegate
let context = appDeldeaget.persistentContainer.viewContext
let entity = NSEntityDescription.entity(forEntityName: "Data", in: context)
let theTitle = NSManagedObject(entity: entity!, insertInto: context)
theTitle.setValue(hits.text, forKey: "hits")
//removed theTitle2 and set the second value in theTitle itself
theTitle.setValue(atBats.text, forKey: "atBATS")
do {
try context.save()
itemName.append(theTitle)
//add theTitle only
} catch {
print("d")
}
self.theScores.reloadData()
hits.text = ""
hits.resignFirstResponder()
}
I have a list of tableviewcells loaded. And beside each of those cells is an 'Add To favorite' button. When that 'Add To favorite' is clicked the image on it will change and that changed image should be stored into coredata so that when the app is run again I can know which cell was favorited. For that this is what has been tried...
func favoriteBtnTapped(cell: HistoryTableViewCell) {
if segmentControl.selectedSegmentIndex == 2 {
favBtnTapFlag = true
if let indexPath = tableview?.indexPath(for: cell) {
let myFavMsg = messages1[indexPath.row]
let likedMsg = myFavMsg.historyData
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
return
}
let managedContext = appDelegate.persistentContainer.viewContext
let entity = NSEntityDescription.entity(forEntityName: "FavoritedMessages", in: managedContext)
let category = NSManagedObject(entity: entity!, insertInto: managedContext)
category.setValue(likedMsg, forKeyPath: "favData")
//New image is set on the cell and it is saved to coredata here...
cell.favoriteButton.setImage(UIImage(named: "pin"), for: .normal)
let imageData = UIImageJPEGRepresentation((cell.favoriteButton.imageView?.image)!, 1)
category.setValue(imageData, forKey: "favImage")
do {
try managedContext.save()
self.favMessages.append(category as! FavoritedMessages)
} catch let error as NSError {
print("Could not save. \(error), \(error.userInfo)")
}
}
}
And it is fetched in viewWillAppear like so...
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
guard let appDelegate =
UIApplication.shared.delegate as? AppDelegate else {
return
}
let managedContext =
appDelegate.persistentContainer.viewContext
let fetchRequest =
NSFetchRequest<NSManagedObject>(entityName: "Messages")
let fetchRequest1 = NSFetchRequest<NSManagedObject>(entityName: "FavoritedMessages")
do {
messages1 = try managedContext.fetch(fetchRequest as! NSFetchRequest<NSFetchRequestResult>) as! [Messages]
favMessages = try managedContext.fetch(fetchRequest1 as! NSFetchRequest<NSFetchRequestResult>) as! [FavoritedMessages]
for result in favMessages as [FavoritedMessages] {
if let imageData = result.value(forKey: "favImage") as? NSData {
if let image = UIImage(data:imageData as Data) as? UIImage {
favoritedImage.image = image
}
}
}
tableview.reloadData()
} catch let error as NSError {
print("Could not fetch. \(error), \(error.userInfo)")
}}
Here favoritedImage.image = image I'm trying to assign the fetched image to an imageview variable and then assign it at cellForRow. But how that can be done I'm not sure...
You should not save image in coredata.
Save the model with favourite_status as 1. (0 => unfavourited and 1 => favourited ) in coredata. (Basically boolean value)
Load the image from app bundle based on favourite_status.
When loading cells also use favourite_status to load image.
/// Edited
func favoriteBtnTapped(cell: HistoryTableViewCell) {
//1. Get Entity from datasource(Array) using indexpath.row
//2. Favorite the entity by setting favaorite_status = 1
//3. Save to coredata also
//4. Reload Table view
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//1. Get Entity from datasource(Array) using indexpath= Array
//2. Set cell image based on favaorite_status. Use UIImage.init(name:””) (if favaorite_status == 0, imagename will be different)
}
I have a function that checking core data. if doesn't exist it should write to in it(but its not working in that way) SoundItems is an array that contains favorited objects and mainArray is the array that contains real objects;
#IBAction func Favori(_ sender: Any) {
// save core data
let app = UIApplication.shared.delegate as! AppDelegate
let context = app.persistentContainer.viewContext
let newSound = NSEntityDescription.entity(forEntityName: "Sounds", in: context)
let sound = NSManagedObject(entity: newSound!, insertInto: context)
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Sounds")
let predicate = NSPredicate(format: "soundName = %#", soundArray[soundIndex].deletingPathExtension().lastPathComponent)
fetchRequest.predicate = predicate
do {
let fetchResults = try context.fetch(fetchRequest) as? [Sounds]
if fetchResults!.count > 0 {
print("already favd")
}
else {
sound.setValue(soundArray[soundIndex].deletingPathExtension().lastPathComponent, forKey: "soundName")
try context.save()
soundItems.append(sound)
print(sound)
}
}
catch {
print(error)
}
}
and here is the code that listing the core data;
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "cell")! as UITableViewCell
let sound = soundItems[indexPath.row]
cell.textLabel?.text = sound.value(forKey: "soundName") as? String
return cell
}
I tried to run the code in debug mode and it works fine when there is no duplicated core data and adds into the tableView list. But here is the situation; when core data exist(fetchResults!.count > 0) still adding in the tableview as nil label.text but always adds the item of mainArray[0]
If you want to check if the sound is in the favorites and if not add a new sound you have to change the order of the steps
#IBAction func Favori(_ sender: Any) {
// save core data
let app = UIApplication.shared.delegate as! AppDelegate
let context = app.persistentContainer.viewContext
let fetchRequest : NSFetchRequest<Sounds> = Sounds.fetchRequest()
let favName = soundArray[soundIndex].deletingPathExtension().lastPathComponent
let predicate = NSPredicate(format: "soundName = %#", favName)
fetchRequest.predicate = predicate
do {
let fetchResults = try context.fetch(fetchRequest)
if fetchResults.isEmpty {
let newSound = NSEntityDescription.insertNewObject(forEntityName: "Sounds", into:context) as! Sounds
newSound.soundName = favName
try context.save()
soundItems.append(newSound)
print(newSound)
}
else {
print("already favd")
}
}
catch {
print(error)
}
}
It's recommended to name entities in singular form (Sound).
#vadian had the point. Why did you insert a new sound before fetching the data?
let newSound = NSEntityDescription.entity(forEntityName: "Sounds", in: context)
let sound = NSManagedObject(entity: newSound!, insertInto: context)
I'm learning how to use CoreData. I have a tableView with an add button, which segues to a view with just a textfield and a save button. When the button is pressed, the string in the textfield is saved in a CoreData database:
#IBOutlet weak var name: UITextField!
#IBAction func onSave(sender: UIBarButtonItem) {
saveItem(name.text!)
self.dismissViewControllerAnimated(true, completion: nil)
}
private func saveItem(itemName: String)
{
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let entity = NSEntityDescription.entityForName("Item", inManagedObjectContext: managedContext)
let item = NSManagedObject(entity: entity!, insertIntoManagedObjectContext: managedContext)
item.setPrimitiveValue(itemName, forKey: "name")
do {
try managedContext.save()
listItems.append(item)
}catch let error {
print(error)
}
The tableView file has the Controller class and a global array of NSManagedObject:
Here is the relevant code:
var listItems = [NSManagedObject]()//outside the class
override func viewWillAppear(animated: Bool) { //in the tableviewcontroller class
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let fetch = NSFetchRequest(entityName: "Item")
do {
let results = try managedContext.executeFetchRequest(fetch)
listItems = results as! [NSManagedObject]
//EDIT
for item in listItems {
print(item)
}
} catch let error {
print(error)
}
self.tableView.reloadData()
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)
let item = listItems[indexPath.row]
cell.textLabel?.text = item.valueForKey("name") as? String
return cell
}
The database is very simple: an Entity named Item with a name attribute
This, however, doesn't work. When I press the save button, no new rows are added. If I remove all the code in viewWillAppear but self.tableView.reloadData(), the rows are created but when I relaunch the app they aren't there.
Any help would be much appreciated.
I want to save my data to core data when a button is clicked here is my action button code now let app = UIApplication.sharedApplication().delegate as! AppDelegate
let context = app.managedObjectContext
let entity = NSEntityDescription.entityForName("Cart", inManagedObjectContext: context)
let cart = Cart(entity: entity!, insertIntoManagedObjectContext: context) but the only problem now is that i dont how to save here is my code to parse json
Alamofire.request(.GET, url!, headers: headers).responseJSON { (response) in
let result = response.result
if response.result.isSuccess{
let jsonObj = JSON(result.value!)
if let x = jsonObj["Items"].array {
x.forEach
{
if let uw = ($0["name"]).string{
print(uw)
let qw = ($0["image"]).string
if let rw = ($0["price"]).int{
if let hu = ($0["id"]).int{
print(hu)
let foo = Rest(name: uw, imageUrl: qw!, price: "₦\(rw)")
self.rest.append(foo)
}
}
}
}
dispatch_async(dispatch_get_main_queue()) {
self.tableView.reloadData()
actInd.stopAnimating()
}
}
}
So i have an array called rest which is where i want get data for the tableview. I want to save information of each cell tapped into coredata here is a screenshot of the app
So when the sure button is tapped it saves the item to coredata
here is my code incase you neecode
Try this, adapted to your code.
In the portion that you have (...let app=...) replace it by this:
let app2 = UIApplication.sharedApplication().delegate as! UIApplicationDelegate
if let context2 = app2.managedObjectContext {
let cart2 = NSEntityDescription.insertNewObjectForEntityForName("Cart", inManagedObjectContext: context2) as! Cart
cart2.name = self.res.name
cart2.price = self.res.price
cart2.url = self.res.imageUrl
cart2.id = ""
// Perform a save operation
do {
try context2?.save()
} catch {
let saveError = error as NSError
print(saveError)
}
}
Let me know if this works.
Cheers
Just an example here when you want to save your data in coredata. You have to create entity/model and all the setup for core data elements. For details please study https://www.raywenderlich.com/115695/getting-started-with-core-data-tutorial
func saveName(name: String) {
//1
let appDelegate =
UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
//2
let entity = NSEntityDescription.entityForName("Person",
inManagedObjectContext:managedContext)
let person = NSManagedObject(entity: entity!,
insertIntoManagedObjectContext: managedContext)
//3
person.setValue(name, forKey: "name")
//4
do {
try managedContext.save()
//5
people.append(person)
} catch let error as NSError {
print("Could not save \(error), \(error.userInfo)")
}
}