I'm trying to fetch data from core data with table view cells, but when the data is reloaded each item in the cell take separate cells, I hope you understand what I mean.
this is the code that I think it has an error
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: "ShopList")
//3
do {
let results =
try managedContext.executeFetchRequest(fetchRequest)
people = results as! [NSManagedObject]
let results2 =
try managedContext.executeFetchRequest(fetchRequest)
ids = results2 as! [NSManagedObject]
} catch let error as NSError {
print("Could not fetch \(error), \(error.userInfo)")
}
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! itemsList
let shopList = people[indexPath.row]
cell.items!.text = shopList.valueForKey("name") as? String
let shopList2 = ids[indexPath.row]
cell.itemsId!.text = shopList2.valueForKey("logo") as? String
return cell
}
Try this if problem still exists please add code for numberOfRowsInSection in question
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: "ShopList")
//3
do {
let results =
try managedContext.executeFetchRequest(fetchRequest)
people = results as! [NSManagedObject]
} catch let error as NSError {
print("Could not fetch \(error), \(error.userInfo)")
}
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! itemsList
let shopList = people[indexPath.row]
cell.items!.text = shopList.valueForKey("name") as? String
cell.itemsId!.text = shopList.valueForKey("logo") as? String
return cell
}
Related
in my app I am trying to create a budgeting app. I have tried creating a custom tableView Cell, but when it is run in the simulator, the tableView is condensed and does not show up correctly. As well as this, I am trying to save and load data from Coredata. However when the viewController loads, the error "Fatal Error: Index Out of Range" appears. I have viewed many coreData tutorials and threads however none of them help with my issue.
I want my tableViews to show up like this: storyboard view
However they appear like this.
Here is my code for the tableView and core data.
Any help is appreciated, thank you!
ViewController
var goals: [NSManagedObject] = []
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return CGFloat(goals.count)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! AllGoalsTableViewCell
let goal = goals[1]
cell.titleLabel?.text = goal.value(forKey: "title") as? String
return cell
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
//1
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
return
}
let managedContext = appDelegate.persistentContainer.viewContext
//2
let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "Goal")
//3
do {
goals = try managedContext.fetch(fetchRequest)
} catch let error as NSError {
print("Could not fetch. \(error), \(error.userInfo)")
}
if !self.goals.isEmpty
{
tableView.reloadData()
}
}
addNewViewController
var goals: [NSManagedObject] = []
func save(title: String, goalAmount: Double, percent: Double, amountPerWeek: Double) {
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
return
}
//1
let managedContext = appDelegate.persistentContainer.viewContext
//2
let entity = NSEntityDescription.entity(forEntityName: "Goal", in: managedContext)!
let goal = NSManagedObject(entity: entity, insertInto: managedContext)
//3
goal.setValue(title, forKey: "title")
goal.setValue(goalAmount, forKey: "goalAmount")
goal.setValue(percent, forKey: "percent")
goal.setValue(amountPerWeek, forKey: "amountPerWeek")
//4
do {
try managedContext.save()
goals.append(goal)
} catch let error as NSError {
print("Could not save. \(error), \(error.userInfo)")
}
}
#IBAction func addNewAction(_ sender: Any)
//CoreData
self.save(title: title, goalAmount: goalAmount ?? 0.0, percent: percent, amountPerWeek: amountPerWeekFloat ?? 0.0)
print("saved")
}
I save data from MovieDetailViewController in coreData. I try to access coreData data from another controller. When I save the data to coreData and switch to another controller where I output the result in tableView, it doesn't show me the newly saved names there. When I delete the background and reopen it then it shows me the last saved data.
I need something similar to the tableView method tableView.reloadData().
class MovieDetailViewController: UIViewController {
var coreDataMovieName: [NSManagedObject] = []
var movie: Movie!
var detailsImageView: UIImage!
var movieName = ""
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.title = movie.title
//Detalebshi Photos gamochena
if let posterPath = movie.posterPath {
TMDBClient.downloadPosterImage(path: posterPath) { (data, error) in
guard let data = data else {
return
}
let image = UIImage(data: data)
self.imageView.image = image
self.detailsImageView = image
}
}
}
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: "Favorite")
do {
coreDataMovieName = try managedContext.fetch(fetchRequest)
} catch let error as NSError {
print("Could not fetch. \(error), \(error.userInfo)")
}
}
func save(name: String) {
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
return
}
let managedContext = appDelegate.persistentContainer.viewContext
let entity = NSEntityDescription.entity(forEntityName: "Favorite", in: managedContext)!
let person = NSManagedObject(entity: entity, insertInto: managedContext)
person.setValue(name, forKeyPath: "movieName")
do {
try managedContext.save()
coreDataMovieName.append(person)
print("saved \(person)")
} catch let error as NSError {
print("Could not save. \(error), \(error.userInfo)")
}
}
#IBAction func coreDataFavoritesBtnTapped(_ sender: Any) {
save(name: movieName)
}
}
A controller where I try to access Core Data:
class CoreDataFavoritesViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
var movie: [NSManagedObject] = []
override func viewDidLoad() {
super.viewDidLoad()
title = "The List"
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
tableView.dataSource = self
}
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: "Favorite")
do {
movie = try managedContext.fetch(fetchRequest)
} catch let error as NSError {
print("Could not fetch. \(error), \(error.userInfo)")
}
}
}
// MARK: - UITableViewDataSource
extension CoreDataFavoritesViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return movie.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let person = movie[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.textLabel?.text = person.value(forKeyPath: "movieName") as? String
return cell
}
}
You are appending Data after context save
coreDataMovieName.append(person)
do it before
try managedContext.save()
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'm trying to use core data with my table view elements, but I get a runtime error: "unexpectedly found nil while unwrapping an Optional value"
here is the cellForRowAtIndexPath function and the function for maintaining the core data, I'm not sure which part of these has the error
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! itemsList
let shopList = people[indexPath.row]
cell.items!.text = shopList.valueForKey("name") as? String
return cell
}
func saveName(name: String) {
//1
let appDelegate =
UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
//2
let entity = NSEntityDescription.entityForName("ShopList",
inManagedObjectContext:managedContext)
let shopList = NSManagedObject(entity: entity!,
insertIntoManagedObjectContext: managedContext)
//3
shopList.setValue(name, forKey: "name")
//4
do {
try managedContext.save()
//5
people.append(shopList)
} catch let error as NSError {
print("Could not save \(error), \(error.userInfo)")
}
}
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: "ShopList")
//3
do {
let results =
try managedContext.executeFetchRequest(fetchRequest)
people = results as! [NSManagedObject]
} catch let error as NSError {
print("Could not fetch \(error), \(error.userInfo)")
}
}
}
the breakpoint at this line
let managedContext = appDelegate.managedObjectContext
i am new to CORE DATA in my app i am using coredata.
i just stored data in my core data. my entity name is "FEED" and i have a rows with name "title", "id " , "link" ,"desc" so now i want to delete perticular row on based on "id". so how can i do this?
Here is my code,
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell : MessageMusicCell = tableView.dequeueReusableCellWithIdentifier("MessageMusicCell") as! MessageMusicCell
cell.pinButton.tag = indexPath.row
cell.pinButton.addTarget(self, action: #selector(MessageViewController.buttonDeletePressed(_:)), forControlEvents: UIControlEvents.TouchUpInside)
cell.selectionStyle = .None
person = people[indexPath.row]
cell.lbl_title_msg_music.text = person!.valueForKey("title") as? String
cell.img_message_music.image = UIImage(named: "PlaceHolder")
cell.desc_msg_music.text = person!.valueForKey("desc") as? String
return cell
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print(people.count)
return people.count
}
func buttonDeletePressed(sender:UIButton) {
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let cell : MessageMusicCell = tableView.dequeueReusableCellWithIdentifier("MessageMusicCell") as! MessageMusicCell
}
so how can i do this?
Try Like this,
func buttonDeletePressed(sender:UIButton) {
let appDel:AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let context:NSManagedObjectContext = appDel.managedObjectContext
let index = sender.tag
context.deleteObject(people[index] as NSManagedObject)
people.removeAtIndex(index)
let _ : NSError! = nil
do {
try context.save()
self.tableView.reloadData()
} catch {
print("error : \(error)")
}
}
Hope this will help you.
func deleteFeed(id:String)
{
let appDelegate =
UIApplication.sharedApplication().delegate as? AppDelegate
let managedContext = appDelegate?.managedObjectContext
let fetchRequest = NSFetchRequest(entityName:"FEED")
fetchRequest.predicate = NSPredicate(format: "id = %#", "\(id)")
do
{
let fetchedResults = try managedContext!.executeFetchRequest(fetchRequest) as? [NSManagedObject]
for entity in fetchedResults! {
managedContext?.deleteObject(entity)
}
}
catch _ {
print("Could not delete")
}
}
Now you can call this function and pass the id whatever you want to delete
func buttonDeletePressed(sender:UIButton){
deleteFeed("1")
}
You can delete data like,
let appDel:AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate
let context:NSManagedObjectContext = appDel.managedObjectContext!
context.deleteObject(myData[indexPath.row] as NSManagedObject)
myData.removeAtIndex(indexPath.row)
context.save(nil)
this is done from commitEditingStyle so here used indexPath.row. You can pass your id if you want to delete data from other place. If you want to delete data from tableview then you should implement commitEditingStyle and delete data like mentioned above.
Hope this will help :)
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
switch editingStyle {
case .Delete:
// remove the deleted item from the model
let appDel: AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let context: NSManagedObjectContext = appDel.managedObjectContext
context.deleteObject(people[indexPath.row] )
people.removeAtIndex(indexPath.row)
do {
try context.save()
} catch _ {
}
// remove the deleted item from the `UITableView`
self.tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
default:
return
}
}
Hope this could be of some help!