0

So I have a section in my app which displays events that your followers are going to. I successfully pull the followers and there corresponding events. I then add those events to a bigger array of event objects. I am currently having trouble removing the duplicates I have tried many extensions but it doesn't seem to be working. I figure it is because the array contains different objects with different memory addresses so when I compare them they aren't the same regardless of the fact that the content is. I have been messing with this for a while now and can't really figure anything out. if anyone could help me I would appreciate it.

This is the method grabs the events and returns them to an array in my main VC.

static func showFollowingEvent(for followerKey: String,completion: @escaping (Event) -> Void) {
    //getting firebase root directory
    let ref = Database.database().reference()

    ref.child("users").child(followerKey).child("Attending").observeSingleEvent(of: .value, with: { (attendingSnapshot) in
        print(attendingSnapshot)
        guard var eventKeys = attendingSnapshot.children.allObjects as? [DataSnapshot] else{return}
        for event in eventKeys{
            let dispatchGroup = DispatchGroup()
            dispatchGroup.enter()
            EventService.show(forEventKey: event.key, completion: { (event) in
                dispatchGroup.leave()
                completion(event!)
            })
        }
    }) { (err) in
        print("couldn't grab event info",err)

    }
}  print("couldn't grab event info",err)

    }
}

This is the function that receives the events and reloads the collectionView upon getting them.

@objc func grabFriendsEvents(){
    print("Attempting to see where your friends are going")
    UserService.following { (user) in
        for following in user {
            print(following.username as Any)
            PostService.showFollowingEvent(for: following.uid, completion: { (event) in
                self.friendsEvents.append(event)
               // self.friendsEvents.append(contentsOf: event)
                // leave here
                self.allEvents2["Friends Events"] = self.friendsEvents.removeDuplicates()
                self.collectionView?.reloadData()
            })

        }  

    }
}

I tried these extensions which I saw in previous questions and nothing worked.

extension Array where Element: Equatable {
    func removeDuplicates() -> [Element] {
        var result = [Element]()

        for value in self {
            if result.contains(value) == false {
                result.append(value)
            }
        }
        return result
    }

    mutating func removeDuplicatesTwo() {
        var result = [Element]()
        for value in self {
            if !result.contains(value) {
                result.append(value)
            }
        }
        self = result
    }
}


import Foundation
import FirebaseDatabase.FIRDataSnapshot

@objc(Event)
class Event:NSObject{
    var key: String?
    let currentEventName: String
    let currentEventImage: String
    let currentEventPromo: String?
    let currentEventDescription: String
    //nested properties
    let currentEventStreetAddress: String
    let currentEventCity: String
    let currentEventState: String
    let currentEventDate: String?
    let currentEventEndDate: String?
    let currentEventTime: String?
    let currentEventEndTime: String?
    let currentEventZip: Int
    var category: String
    //nested properties stop
    var currentAttendCount: Int
    var isAttending = false
    var eventDictionary: [String: Any]{


        let dateDict = ["start:date":currentEventDate, "start:time": currentEventTime,"end:time":currentEventEndTime, "end:date": currentEventEndDate]

        return ["event:name":currentEventName,"event:imageURL" : currentEventImage,
                "event:description": currentEventDescription, "attend:count": currentAttendCount,
                "event:street:address": currentEventStreetAddress,"event:zip": currentEventZip,
                "event:state": currentEventState, "event:city": currentEventCity, "event:promo": currentEventPromo ?? "", "event:date": dateDict, "event:category":category]
    }

    init(currentEventKey: String, dictionary: [String:Any]) {
        self.key = currentEventKey
        self.currentEventName = dictionary["event:name"] as? String ?? ""
        self.currentEventImage = dictionary["event:imageURL"] as? String ?? ""
        self.currentEventDescription = dictionary["event:description"] as? String ?? ""
        self.currentEventPromo = dictionary["event:promo"] as? String ?? ""
        self.currentAttendCount = dictionary["attend:count"] as? Int ?? 0
        self.category = dictionary["event:category"] as? String ?? ""
        //nested properties
        self.currentEventStreetAddress = dictionary["event:street:address"] as? String ?? ""
        self.currentEventCity = dictionary["event:city"] as? String ?? ""
        self.currentEventState = dictionary["event:state"] as? String ?? ""
        self.currentEventZip = dictionary["event:zip"] as? Int ?? 0
        let eventDate = dictionary["event:date"] as? [String: Any]
        self.currentEventDate = eventDate?["start:date"] as? String ?? ""
        self.currentEventTime = eventDate?["start:time"] as? String ?? ""
        self.currentEventEndTime = eventDate?["end:time"] as? String ?? ""
        self.currentEventEndDate = eventDate?["end:date"] as? String ?? ""


    }

    init?(snapshot: DataSnapshot) {
        guard let dict = snapshot.value as? [String : Any],
            let currentEventName = dict["event:name"] as? String,
            let currentEventImage = dict["event:imageURL"] as? String,
            let currentEventDescription = dict["event:description"] as? String,
            let currentEventPromo = dict["event:promo"] as? String,
            let category = dict["event:category"] as? String,
            let currentEventStreetAddress = dict["event:street:address"] as? String,
            let currentEventCity = dict["event:city"] as? String,
            let currentEventState = dict["event:state"] as? String,
            let currentEventZip = dict["event:zip"] as? Int,
            let currentAttendCount = dict["attend:count"] as? Int,
            let eventDate = dict["event:date"] as? [String: Any],
            let currentEventDate = eventDate["start:date"] as? String,
            let currentEventEndDate = eventDate["end:date"] as? String,
            let currentEventTime = eventDate["start:time"] as? String,
            let currentEventEndTime = eventDate["end:time"] as? String
            else { return nil }
        self.key = snapshot.key
        self.currentEventName = currentEventName
        self.currentEventImage = currentEventImage
        self.currentEventDescription = currentEventDescription
        self.currentEventStreetAddress = currentEventStreetAddress
        self.currentEventCity = currentEventCity
        self.currentEventState = currentEventState
        self.currentEventZip = currentEventZip
        self.currentAttendCount = currentAttendCount
        self.currentEventPromo = currentEventPromo
        self.currentEventDate = currentEventDate
        self.currentEventTime = currentEventTime
        self.currentEventEndTime = currentEventEndTime
        self.category = category
        self.currentEventEndDate = currentEventEndDate
    }

    static func ==(lhs: Event, rhs: Event) -> Bool {
        return lhs.key == rhs.key
    }

}
4
  • Could you append Event class code, please ? Commented Apr 4, 2018 at 21:37
  • 1
    Does your Event type implement Equatable? Commented Apr 4, 2018 at 21:41
  • @NazarLisovyi i added the event class Commented Apr 4, 2018 at 22:56
  • @theMikeSwan no it doesnt Commented Apr 4, 2018 at 22:56

2 Answers 2

1

Classes of type NSObject will automatically call isEqual() for the contains() method. You can override the superclass's implementation to fit your logic.

If your class HAS to inherit NSObject, then use:

class Event: NSObject {
    var key: String?

    init(key: String) {
        self.key = key
    }

    override func isEqual(_ object: Any?) -> Bool {
        guard let event = object as? Event else { return false }
        return self.key == event.key
    }
}

var event = Event(key: "abc")
var eventCopy = Event(key: "abc")

extension Array where Element:Equatable {
    func removeDuplicates() -> [Element] {
        return reduce(into: []) { result, element in
            if !result.contains(element) {
                result.append(element)
            }
        }
    }
}

var events = [event, eventCopy]
events = events.removeDuplicates()
print(events.count)

If your class does not inherit NSObject, make it conform to the Equatable protocol.

class Event: Equatable {
    var key: String?

    init(key: String) {
        self.key = key
    }

    static func ==(lhs: Event, rhs: Event) -> Bool {
        return lhs.key == rhs.key
    }
}

var event = Event(key: "abc")
var eventCopy = Event(key: "abc")

extension Array where Element:Equatable {
    func removeDuplicates() -> [Element] {
        var result = [Element]()

        for value in self {
            if result.contains(value) == false {
                result.append(value)
            }
        }

        return result
    }
}

var events = [event, eventCopy]
events = events.removeDuplicates()
print(events.count)
Sign up to request clarification or add additional context in comments.

9 Comments

i just added event class
I've updated the code. You can customize the == function to as per your equality logic.
just want to check if two events are equal
I didn't get you. I've implemented the logic to remove duplicates. You can run the above code in a playground to understand it better.
im agreeing with you
|
1

You have to make Event class conform to Equatable protocol

1 Comment

oh okay how would I do that

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.