How to fetch dates(as weekly-monthly) from CoreData in swift?

70 Views Asked by At

i am trying to make a spending control application. However, I cannot pull storages from the dates registered by users on a weekly or monthly basis.Monthly and weekly extraction of user-selected and saved dates to coredata how can I do that ?

if let newSaglik = Int(saglikText.text!){
            if let newMarket = Int(marketText.text!){
                if let newOther = Int(otherText.text!){
                    toplam = newSaglik + newMarket + newOther
                    
                }
            }
        }
        let appDelegate = UIApplication.shared.delegate as! AppDelegate
        let context = appDelegate.persistentContainer.viewContext
        let newPendings = NSEntityDescription.insertNewObject(forEntityName: "Pendings", into: context)
        
        let formatter = DateFormatter()
        formatter.dateStyle = .medium
        formatter.timeStyle = .none
        
        let pickTime = formatter.date(from: dateText.text!)
        
        newPendings.setValue(String(toplam), forKey: "totalPend")
        newPendings.setValue(pickTime, forKey: "selectDate")
        
        do {
            try context.save()
        } catch{
            
        }
      
    }
dateArray.removeAll(keepingCapacity: false)
        toplamArray.removeAll(keepingCapacity: false)
        let appDelegate = UIApplication.shared.delegate as! AppDelegate
        let context = appDelegate.persistentContainer.viewContext
        let fetch = NSFetchRequest<NSFetchRequestResult>(entityName: "Pendings")
        fetch.returnsObjectsAsFaults = false
        
        do {
           let results =  try context.fetch(fetch)
            if results.count > 0 {
                for result in results as! [NSManagedObject]{
                    if let getPend = result.value(forKey: "totalPend") as? String{
                        toplamArray.append(getPend)
                    }
                    
                    if let getDate = result.value(forKey: "selectDate") as? Date {
                        dateArray.append(getDate)
                    }
                }
                
                tablevİEW.reloadData()
            }
              
        } catch {
            
        }
        
    }```
1

There are 1 best solutions below

0
vadian On

First of all don't use multiple arrays (like toplamArray and dateArray) as data source, use one array of Pendings instances.

Second of all take advantage of the generic capabilities of NSManagedObject. The major benefit is to have strong typed property values using dot notation rather than error prone KVC syntax value(forKey:). Also insert a new record with Pendings(context: context) rather than with the old non-generic syntax.


Assuming the significant part of the Pendings class is

class Pendings : NSManagedObject {
    @NSManaged var selectDate : Date
    @NSManaged var totalPend : String

    @nonobjc public class func fetchRequest() -> NSFetchRequest<Pendings> {
        return NSFetchRequest<Pendings>(entityName: "Pendings")
    }
}

add a function to return a predicate for a given month, year and keyPath

func monthlyPredicateFor(month: Int, in year: Int, keyPath: KeyPath<Pendings,Date>) throws -> NSPredicate {
    let calendar = Calendar.current
    let startComponents = DateComponents(year: year, month: month)
    guard let startDate = calendar.date(from: startComponents) else { throw PredicateError.invalidDate }
    let endDate = calendar.date(byAdding: .month, value: 1, to: startDate)!
    let keyPathString = NSExpression(forKeyPath: keyPath).keyPath
    return NSPredicate(format: "%K > %@ AND %K < %@", argumentArray: [keyPathString, startDate, keyPathString, endDate])
}

This requires a custom Error enum

enum PredicateError: Error {
    case invalidDate
}

As mentioned replace the two arrays representing the data source with one array for example

var filteredPendings = [Pendings]()

In the code to fetch the data apply the predicate and assign the result to filteredPendings

let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
do {
    let fetchRequest : NSFetchRequest<Pendings> = Pendings.fetchRequest()
    fetchRequest.predicate = try monthlyPredicateFor(month: 7, in: 2023, keyPath: \.selectDate)
    fetchRequest.returnsObjectsAsFaults = false
    filteredPendings = try context.fetch(fetchRequest)
    tableview.reloadData()
} catch {
    print(error)
}

The predicate for the week depends on what weekly actually means. A week number or a start date or something else?