Alright I will close this thread because I got more updates.
Post
Replies
Boosts
Views
Activity
Another update I modified my save function and I think it is consistent with my print results. Like it prints 3 favourites when there are 3 favourites and shows me my saved favourites. I just need need to figure out how to retrieve the data when the app restarts because nothing is saved. Any input would really help.
@IBAction func save(_ sender: UIBarButtonItem) {
let entity = NSEntityDescription.entity(forEntityName: "CurrentPlayers", in: context)!
let saveFav = CurrentPlayers(entity: entity, insertInto: context)
for o in prefArr {
saveFav.yahooName = o.yahooName
saveFav.team = o.team
saveFav.position = o.position
saveFav.photoUrl = o.photoUrl
do {
try context.save()
print("These are my saved objects: \(saveFav)")
print("how many saved objects: \(prefArr.count)")
} catch {
print("error is: \(error)")
}
}
}
}
What problem exactly ? No save at all ? partial save ?
No save it all.
Could you show more of convenience init ? It seems you get only one value.
I added a prefArr.count to it. If I add a player to my favourites I get this. It is a Core Data entity as you can see and I also get how many favourites I have from the count.
These are my saved objects: <CurrentPlayers: 0x6000033fd630> (entity: CurrentPlayers; id: 0x600001031f80 <x-coredata:///CurrentPlayers/tB4FE931D-0582-445E-BFAB-099B58D904391054>; data: {
firstName = nil;
jerseyNumber = 0;
lastName = nil;
photoUrl = "https://s3-us-west-2.amazonaws.com/static.fantasydata.com/headshots/nhl/low-res/30000007.png";
position = G;
status = nil;
team = MON;
yahooName = "Carey Price";
})
1
Okay so I got rid of fetchSave I don't think I need it since when it saves it should not need to be fetched because I add it to the array. I still have trouble getting the save to work.
@IBAction func save(_ sender: UIBarButtonItem) {
// Assign values to the entity's properties
for o in prefArr {
let saveFav = CurrentPlayers(context: context)
saveFav.yahooName = o.yahooName
saveFav.team = o.team
saveFav.position = o.position
saveFav.photoUrl = o.photoUrl
// To save the new entity to the persistent store, call
// save on the context
print("These are my saved objects: \(saveFav)")
do {
try context.save()
prefArr.append(saveFav) //favourite is added
} catch {
print("error is: \(error)")
}
}
}
}
Please tell exactly where you stand now: are the favorites saved corectly
When I click save it prints out all the favourites I saved as a CoreData entity so i think it's saved.
What are all print output you get when you restart the app ?
When I restart the app it prints no saved favourites and there are 0 favourites.
provide more precise output with print("There are favourites", prefArr.count)
This prints how many favourites I have, depending on the number I added.
Okay I see your point this will save each of my instances that I have. The issue is my fetchSave() func then. I should be able to see my favourites when I restart the app.
override func viewDidLoad() {
super.viewDidLoad()
fetchSave()
//don't seem to have any saveFavs in my array when it restarts
if prefArr.count == 0 {
print("There are 0 favourites")
self.tableView.separatorStyle = UITableViewCell.SeparatorStyle.none
} else {
print("There are favourites")
DispatchQueue.main.asyncAfter(deadline: .now() + 300) {
self.reviewRating.requestReview(isWrittenReview: false)
}
}
}
func fetchSave() {
//If I have any number of favourites and restart the app this code block executes
if prefArr.count == 0 {
print("No saved favourites")
} else {
let fetchRequest: NSFetchRequest<CurrentPlayers>
fetchRequest = CurrentPlayers.fetchRequest()
do {
let objects = try context.fetch(fetchRequest)
print("These are how many saved favourites I have: \(objects.count)")
tableView.reloadData()
} catch {
print("Fetch failed")
}
}
}
When you save you create a new instance saveFav then, I don't understand what you are doing in the loop. Is it just for displaying saveFav ?
I do not see in save where you reference a newly created fav
The reason I have a loop is because I want to define all the objects in my array called prefArr as saveFav when the save button is pressed and I try to save them to the context.
where and how do you create a new favorite
I create a new favourite by adding it with a button in another VC
class HockeyDetailVC: UITableViewController {
let imageController = FetchImage()
static var item: CurrentPlayers?
@IBAction func addToFav(_ sender: Any) {
let alert = UIAlertController(title: "Favourite Added 💙", message: "\(name.text ?? "") is added to favourites", preferredStyle: .alert)
alert.addAction(UIAlertAction(
title: "OK",
style: UIAlertAction.Style.default)
{ _ in
FavouriteManager.shared.add(HockeyDetailVC.item!)
})
self.present(alert, animated: true, completion: nil)
}
class FavouriteManager {
static let shared = FavouriteManager()
var favArr : [CurrentPlayers] = []
//this function is called when button is clicked
func add(_ player: CurrentPlayers) {
NotificationCenter.default.post(
name: .passFavNotification,
object: player
)
favArr.append(player)
for player in favArr {
if !favArr.contains(player) {
favArr.append(player)
}
}
}
}
how do you use it in save
The save button is supposed to take the objects in my array and make them saveFav. Hope this makes sense.
Isn't it what you expect to have one more object ? I don't really understand your comment here.
What I mean is whether I add a favourite or not and click save it just adds 1
What is the real number of objects you should have ?
func fetchSave() {
let fetchRequest: NSFetchRequest<CurrentPlayers>
fetchRequest = CurrentPlayers.fetchRequest()
do {
let objects = try context.fetch(fetchRequest)
//I get over 40000 objects
print("These are how many saved favourites I have: \(objects.count)")
tableView.reloadData()
} catch {
print("Fetch failed")
}
}
@IBAction func save(_ sender: UIBarButtonItem) {
var saveFav = CurrentPlayers(context: context)
// Assign values to the entity's properties
for o in prefArr {
saveFav.yahooName = o.yahooName
saveFav.team = o.team
saveFav.position = o.position
saveFav.photoUrl = o.photoUrl
// To save the new entity to the persistent store, call
// save on the context
print("These are my saved objects: \(saveFav)")
}
do {
try context.save()
fetchSave()
} catch {
print(error)
}
}
Lets say I have 1 favourite and save it, my saveFav shows the favourite I saved in it's CoreData form, the entity, id, data and my objects.count should be 1 but it's over 56848. If I save it again it should still be 1 but it's 56849.
This is my currentPlayers class
import Foundation
import CoreData
enum DecoderConfigurationError: Error {
case missingManagedObjectContext
}
extension CodingUserInfoKey {
static let managedObjectContext = CodingUserInfoKey(rawValue: "managedObjectContext")!
}
@objc(CurrentPlayers)
public class CurrentPlayers: NSManagedObject, Decodable {
enum CodingKeys: String, CodingKey {
case photoUrl = "PhotoUrl"
case firstName = "FirstName"
case lastName = "LastName"
case position = "Position"
case team = "Team"
case yahooName = "YahooName"
case status = "Status"
case jerseyNumber = "Jersey"
}
public static var managedObjectContext: NSManagedObjectContext?
required public convenience init(from decoder: Decoder) throws {
guard let context = decoder.userInfo[.managedObjectContext] as? NSManagedObjectContext else {
throw DecoderConfigurationError.missingManagedObjectContext
}
self.init(context: context)
//...
let values = try decoder.container(keyedBy: CodingKeys.self)
photoUrl = try values.decode(String.self, forKey: CodingKeys.photoUrl)
firstName = try values.decode(String.self, forKey: CodingKeys.firstName)
lastName = try values.decode(String.self, forKey: CodingKeys.lastName)
position = try values.decode(String.self, forKey: CodingKeys.position)
team = try values.decode(String.self, forKey: CodingKeys.team)
yahooName = try values.decodeIfPresent(String.self, forKey: CodingKeys.yahooName)
status = try values.decode(String.self, forKey: CodingKeys.status)
jerseyNumber = try values.decodeIfPresent(Int64.self, forKey: CodingKeys.jerseyNumber) ?? 0
}
}
I changed the viewDidLoad code because my currentFav was nil in both conditions and I did not need the post notification there.
override func viewDidLoad() {
super.viewDidLoad()
fetchSave()
if prefArr.count == 0 {
print("There are 0 favourites") //when I add a favourite(s) and the app terminates it goes to this block
self.tableView.separatorStyle = UITableViewCell.SeparatorStyle.none
} else {
print("There are favourites") //when I add a favourite(s) and do not terminate it goes to this block
DispatchQueue.main.asyncAfter(deadline: .now() + 300) {
self.reviewRating.requestReview(isWrittenReview: false)
}
}
}
Whenever I click save it prints 1 more object then I already have regardless of how many favourites there are.
@IBAction func save(_ sender: UIBarButtonItem) {
var saveFav = CurrentPlayers(context: context)
// Assign values to the entity's properties
for o in prefArr {
saveFav.yahooName = o.yahooName
saveFav.team = o.team
saveFav.position = o.position
saveFav.photoUrl = o.photoUrl
print("These are my saved objects: \(saveFav)")
// To save the new entity to the persistent store, call
// save on the context
}
do {
try context.save()
fetchSave() //if I have 53704 saved objects then after I click save I have 53705 it seems to always be over 40000
} catch {
print(error)
}
}
I can easily access my favourite now with HockeyDetailVC.item I made the variable item static. I think it can prove useful. Really appreciate the help.
Is it ?
Yes that is my save button.
If so, where do you save ? Where is context defined ?
The button is where I save it. Context is defined at the beginning of my favourites section.
let context = PersistenceService.persistentContainer.viewContext
Where do you try to reload ?
I want to reload it when I go back to my favourites section after I restart the app but it reloads every time I go to my favourites section whether or not I add a favourite.
What do you mean ?
Lets say I add a favourite. I go to my favourites section there is one favourite, the one I added but when I restart the app , I can't see the favourite I added before in my favourites section.
Where are those favourites in the code above ?
my favourites are currentFav but when I click the save button I define them as saveFav.
I will make things more clear then.
Core Data should be able to save things like this locally am I not right?
I'm confused with this code: you have at least 2 different TableViewControllers (FavouritesVC, HockeyDetailVC). Both of them have handleFavNotification. It is not clear where you delete, where you add, where it is added back.
The favourites I want to add is originally in hockeydetailvc where it is added by a button in that vc. I have an observer and notification function there. It is added to an array in FavouriteManager.swift. In my favouritesvc I use that array to hold my favourites and when a new favourites is added to favouritesvc it reloads the tableview with a notification. I can delete a favourite but when I add a new one it's as if the favourite I deleted comes back onto the array.
You should show how you handle the passFavNotification (I mean, where do you call handleFavNotification)
I will show you where I called it's a detailed tableview controller where the button is to add favourites.
extension Notification.Name {
static let passFavNotification = Notification.Name("pass")
}
class HockeyDetailVC: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
gonnaLoadView()
tableV.bounces = false
tableV.alwaysBounceVertical = false
favButton.layer.cornerRadius = 10
// Add self as Observer and a function to handle it
NotificationCenter.default.addObserver(self,
selector: #selector(handleFavNotification(notification:)),
name: .passFavNotification,
object: nil)
}
@objc func handleFavNotification(notification:Notification){
if let theFav = notification.object as? CurrentPlayers {
self.item = theFav
}
}
}
Having two separate properties favArr and noRepFav may be causing the issue.
The thing is I need noRepFav because I don't want duplicates in my array.
Okay I will show you that I still have same issue.
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return favSet.count
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 152
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "favcell", for: indexPath) as! FavCell
let itemFav = favSet[favSet.index(favSet.startIndex, offsetBy: indexPath.row)]
cell.layer.borderColor = UIColor.black.cgColor
cell.layer.borderWidth = 0.5
cell.contentView.backgroundColor = .random
cell.update(with: itemFav)
return cell
}