1

I am making a collection view that shows somebody their 'feed' which includes their compliments, likes, replies, and sent. I have an object named Feed which is made of an array of compliments, an array of likes, and array of replies, and an array of sent. Every object within those smaller arrays has a date_created property.

I know how to fill a collection view based off of one array sorted by dates, but how can I load a collection view with every like, reply, compliment, and sent from four arrays based on their date sent?

Do I perhaps append every one of these objects to one array? If so, how can I then go through that array and sort everything in it?

struct Feed: Decodable {
    let likes: [Like]
    let replies: [Reply]
    let compliments: [Compliment]
    let sent: [Compliment]
}

struct Like: Decodable {
    let id: Int
    let user: QuickUser
    let created_at: String
}

struct Reply: Decodable {
    let parent: Compliment
    let content: String
    let created_at: String
}

struct Compliment: Decodable {
    let id: Int
    let content: String
    let sender: QuickUser

    let created_at: String

    let is_liked: Bool
    let recipient: QuickUser
    let is_public: Bool
}

func getFeed() {
    UserServices.getInboxFeed { feed in
        guard let feed = feed else {
            self.showOkayAlert(title: "Oops!", message: "We are having trouble loading your inbox.", completion: nil)
            return
        }
        self.feed = feed

        DispatchQueue.main.async {
            //load collection view here
        }
    }
}

A mockup of what the collection view will look like mockup

rmaddy
  • 314,917
  • 42
  • 532
  • 579
Levi K
  • 573
  • 1
  • 4
  • 23

1 Answers1

0

Well, to solve this i have made a dummy protocol that contains the shared properties they all share.

in this case it was created_at and i assume this should be in date format.

however the next step was to make an extension of Feed that contains a function

that returns the latest object that confirm to the dummy protocol that i called, it LatestAction,

it basically sort each array by date and return the first item.

in our case the latest date,

after that creates a [LatestAction] sort it again the same way and return the first item which is the LatestAction.

Observe the code below.

struct QuickUser: Codable {

}

struct Feed: Decodable {
    let likes: [Like]
    let replies: [Reply]
    let compliments: [Compliment]
    let sent: [Compliment]
}
extension Feed {
    func latestAction() -> LatestAction {
        let latestLike = self.likes.sorted(by: { $0.created_at.compare($1.created_at) == .orderedDescending }).first!
        let latestReply = self.replies.sorted(by: { $0.created_at.compare($1.created_at) == .orderedDescending }).first!
        let latestComp = self.compliments.sorted(by: { $0.created_at.compare($1.created_at) == .orderedDescending }).first!
        let latestActions: [LatestAction] = [latestReply, latestLike, latestComp].sorted(by: { $0.created_at.compare($1.created_at) == .orderedDescending })
        return latestActions.first!
    }

}
protocol LatestAction  {
    var created_at: Date { get }
}

struct Like: Decodable, LatestAction {

    let id: Int
    let user: QuickUser
    let created_at: Date
}

struct Reply: Decodable, LatestAction {

    let parent: Compliment
    let content: String
    let created_at: Date
}

struct Compliment: Decodable, LatestAction {

    let id: Int
    let content: String
    let sender: QuickUser

    let created_at: Date

    let is_liked: Bool
    let recipient: QuickUser
    let is_public: Bool
}



// Simply used like this
var latest = feed.latestAction() 

We are not done yet if you checked the latest type it would say LatestAction and only can access the one property in there which is created_at,

now the for the last part we are going to TypeCast the Object.

if let latest = feed.latestAction() as? Like {
    // used as Like
} else if let latest = feed.latestAction() as? Compliment {
    // used as Compliment
} else if let latest = feed.latestAction() as? Reply {
    // used as reply
}
Mohmmad S
  • 5,001
  • 4
  • 18
  • 50
  • in your question created_at is a String type considering this should be a date, however if its not you . can cast the String to date check other questions on how to achieve that, and then you can use this simple extension and method. – Mohmmad S Nov 05 '18 at 08:44
  • that is great! However, it appears that you are only finding the most recent out of all of the categories. I need to be able to load a collection view with all of them combined all sorted in date. I actually just came up with a workaround because I made an array that contained only the display information from each of them, which is made up of the same data, and then used that array to sort the collection view, and stored their corresponding indexes if I needed the extra info. However, I think you have a better solution, assuming it can do what I mentioned – Levi K Nov 05 '18 at 23:49
  • Remove .first and get all the results sorted – Mohmmad S Nov 06 '18 at 05:47
  • it solves what i thought you needed, and if u edit a bit you can use it more – Mohmmad S Nov 06 '18 at 06:45
  • I'll test it out, I'm going to mark it as the correct answer for now and if there are any problems I'll let you know. I really appreciate the time and effort! Have a great day – Levi K Nov 06 '18 at 22:32