GetStream / stream-swift

Swift client for Stream API
https://getstream.io
BSD 3-Clause "New" or "Revised" License
35 stars 26 forks source link

Basic get doesn't work #41

Open solkpolk opened 2 years ago

solkpolk commented 2 years ago

Adding custom activities in a feed causes a parsing error unless the entire feed contains the same activities

final class GossipActivity: EnrichedActivity<GetStream.User, String, DefaultReaction> {
    private enum CodingKeys: String, CodingKey {
        case user
    }

    var user: AvatarLead

    init(verb: Verb, object: String, user: AvatarLead, startDate: Date = Date()) {
        self.user = user
        super.init(actor: .init(id: user.id), verb: verb, object: object)
    }

    required init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        user = try container.decode(AvatarLead.self, forKey: .user)
        try super.init(from: decoder)
    }

    override public func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(user, forKey: .user)
        try super.encode(to: encoder)
    }
}
self.userFeed?.get(typeOf: GossipActivity.self, completion: { result in
            switch result {
                case .success(let activiti):
                    self.gossip = activiti.results
                case .failure(let e):
                    print(e)
            }
        })

This is dangerous because if one activity does not confirm to GossipActivity then the entire feed disappears.

b-onc commented 2 years ago

Hello @solkpolk ,

Thank you for the report. I'm looking into this and will keep you posted.

b-onc commented 2 years ago

Hello @solkpolk

I've looked into the SDK and seems like it's how it was designed to work. If you want to decode a feed with multiple activity types, you can do so with a custom workaround, such as:

final class MixedActivity: EnrichedActivity<GetStream.User, String, DefaultReaction> {

    var anyActivity: Activity?
    var gossipActivity: GossipActivity?

    required init(from decoder: Decoder) throws {
        if let gossipActivity = try? GossipActivity(from: decoder) {
            self.gossipActivity = gossipActivity
        } else {
            anyActivity = try Activity(from: decoder)
        }
        try super.init(from: decoder)
    }

    required public init(actor: ActorType, verb: Verb, object: ObjectType, foreignId: String? = nil, time: Date? = nil, feedIds: FeedIds? = nil, originFeedId: FeedId? = nil) {
        fatalError("init(actor:verb:object:foreignId:time:feedIds:originFeedId:) has not been implemented")
    }
}

you can then check which activity you were able to decode.

Does this make sense?