Home > Back-end >  No exact matches in call to instance method 'append' in swift
No exact matches in call to instance method 'append' in swift

Time:03-29

Tried to combine or merging two model to one model 1st model = items [ InboxModel]. (My own Inbox) 2nd model = items2 [MoInboxModel] (SDK Inbox)

1st 2nd -> combinedItems

private var items: [InboxModel] = []
private var items2: [MoInboxModel] = []
private var combinedItems: [combinedInboxModel] = []

struct InboxModel {
    let id: String
    let title: String
    let message: String
    let date: Date
}

struct MoInboxModel {
    let id: String
    let title: String
    let message: String
    let date: Date
}

struct combinedInboxModel {
    let id: String
    let title: String
    let message: String
    let date: Date
}

self?.combinedItems.append(self?.items). //No exact matches in call to instance method 'append
self?.combinedItems.append(contentsOf: self?.items2 ?? []) //No exact matches in call to instance method 'append

Why there is an error while merge it ? How to merge it correctly?

CodePudding user response:

You have three unrelated types - InboxModel, MoInboxModel and combinedInboxModel (Which should be CombinedInboxModel. Even though they all have properties with the same name, they are different types.

There is no append function on an array of combinedInboxModel that accepts an array of InboxModel or MoInboxModel.

You could use map on each of your two input arrays to convert them to an array of CombinedInboxModel which you can then put into combinedItems.

Presumably you are writing this code in a closure, which is why you have a weak self. Best to deal with that first and then process your arrays.

guard let self = self else {
    return
}

self.combinedItems = self.items.map { CombinedInboxModel(id:$0.id,title:$0.title,message:$0.message,date:$0.date) }

let items2 = self.items2.map { CombinedInboxModel(id:$0.id,title:$0.title,message:$0.message,date:$0.date) }

self.combinedItems.append(contentsOf:items2)

You haven't shown where items and items2 come from; Is it possible just to fetch them as instances of the same struct to start with?

CodePudding user response:

The fact that you have three structs with the same properties is a bit fishy. I would consider a different design if I were you.

However, if you must go with this approach, you might want to consider starting with a protocol and getting rid of the combinedInboxModel struct.

protocol InboxModelable {
    var id: String { get }
    var title: String { get }
    var message: String { get }
    var date: Date { get }
}

Now make your two structs conform to InboxModelable.

struct InboxModel: InboxModelable {
    let id: String
    let title: String
    let message: String
    let date: Date
}

struct MoInboxModel: InboxModelable {
    let id: String
    let title: String
    let message: String
    let date: Date
}

Since both of your types conform to InboxModelable you can directly store both types in an array of type Array<InboxModelable> without having to map the elements.

class SomeClass {
    private var items: [InboxModel] = []
    private var items2: [MoInboxModel] = []
    private var combinedItems: [InboxModelable] = []

    func combineItems() {
        doSomething { [weak self] in
            guard let self = self else { return }
            self.combinedItems.append(contentsOf: self.items)
            self.combinedItems.append(contentsOf: self.items2)
        }
    }
}
  • Related