skip to Main Content

I would love to get help on this one since I’ve been on it for a while.

So I fetch my Sections like this and they all get in the right order, but the relationship "Todoitem" they have do not come in the same order. They get all in the correct Section but in wrong order.
I wanna get the Todoitems like this:

Section[
Todoitem "first created",
Todoitem "second created",
Todoitem "third created"…]

Instead they come like this when I create them, always random:

Section[
Todoitem "second created",
Todoitem "third created",
Todoitem "first created"…]

You guys in here are awesome and if someone would like to take the time to help me I would be more than tankful!

I’m working in Swift Xcode, Storyboard.

func fetchSections() {
    let startOfDay = Calendar.current.startOfDay(for: currentDate)
    var components = DateComponents()
           components.day = 1
           components.second = -1
    
    let endOfDay = Calendar.current.date(byAdding: components, to: startOfDay)
    let fetchRequest : NSFetchRequest<Section> = Section.fetchRequest()
    fetchRequest.predicate = NSPredicate(format: "date >= %@ AND date <= %@", startOfDay as NSDate, endOfDay! as NSDate)

    
    do {
        self.tableViewData = try context.fetch(fetchRequest)
        DispatchQueue.main.async {
            self.tableView.reloadData()
        }
    }
    catch {
        //error
    }
}

Fixed it with this:

extension Section {
    var sortedItems: [TodoItem] {
        guard let items = todoitem as? Set<TodoItem> else {
            return []
        }
        
        return items.sorted { (item1, item2) in
            
            return item1.date ?? Date() < item2.date ?? Date()
        }
    }
}

and in cell for row:

let text = self.tableViewCoreData[indexPath.section].sortedItems[indexPath.row – 1].todo
cell.myLabel.text = text

2

Answers


  1. Chosen as BEST ANSWER

    Fixed it with this:

    extension Section {
        var sortedItems: [TodoItem] {
            guard let items = todoitem as? Set<TodoItem> else {
                return []
            }
            
            return items.sorted { (item1, item2) in
                
                return item1.date ?? Date() < item2.date ?? Date()
            }
        }
    }
    

    and in cell for row:

        let text = self.tableViewCoreData[indexPath.section].sortedItems[indexPath.row - 1].todo
        cell.myLabel.text = text
    

    Got help from a friend of mine, thanks anyways!


  2. Predicate is for filtering data only. You probably need to use an NSSortDescriptor to get the output you desire.

    After this line:

    fetchRequest.predicate = NSPredicate(format: "date >= %@ AND date <= %@", 
                                         startOfDay as NSDate, endOfDay! as NSDate)
    

    Add these lines:

    let dateSortDescriptor = NSSortDescriptor(key: "date", ascending: true)
    fetchRequest.sortDescriptors = [dateSortDescriptor]
    

    Update

    As Joakim Danielson rightly mentioned in the comments, the sorting cannot be directly applied on sections as the date resides in the ToDoItems entity.

    Since you are creating a fetch request using the sections entity, I am not sure you can apply the sort descriptor directly to your to do items entity (atleast to my knowledge).

    I would do the following updates to get your desired goal:

    First change your var tableViewData to be compatible with this solution

    // I am assuming Section and ToDoItems are names of your entities
    // and NOT the name of the relationship between them so create this
    var tableViewData: [Section: ToDoItem] = [:]
    

    Then make some updates in the fetching

    // Since you said this works fine, I do not make any changes to these two lines
    let fetchRequest : NSFetchRequest<Section> = Section.fetchRequest()
        
    fetchRequest.predicate = NSPredicate(format: "date >= %@ AND date <= %@", 
                                         startOfDay as NSDate, endOfDay! as NSDate)
    
    // Temp container to build the desired sorted results
    var sectionItems: [Section: [ToDoItems]] = [:]
        
    do {
        // Retrieve the sections
        let sections = try context.fetch(fetchRequest)
        
        // Loop over all the sections you retrieve
        for section in sections
        {
            // Initialize a sort descriptor for the date attribute in the ToDoItems
            // entity. Change it to the right name if it is not date
            let sortDescriptor = [NSSortDescriptor(key: "date", ascending: true)]
        
            // Change hasToDoItems to your correct relationship name
            if let sortedItems = section.hasToDoItems?
                                .sortedArray(using: sortDescriptor) as? [ToDoItem]
            {
                sectionItems[section] = sortedItems
            }
        }
        
        // Assign the tableViewData with the sorted data
        self.tableViewData = sectionItems
        
        // Reload your data
        DispatchQueue.main.async {
            self.tableView.reloadData()
        }
    }
    

    Give this a go and let me know if this gives you the desired results or comment with your results and I’ll amend the code accordingly.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search