Rather than using any of the alternatives you've listed, you could instead alter the way that you access your arrays. You can use a helper function, taking a closure as an argument, to process each element in the arrays:
struct Message {
let text: String
}
let pinnedMessages: [Message] = [Message(text: "I'm pinned"), Message(text: "I'm also pinned")]
let normalMessages: [Message] = [Message(text: "I'm normal"), Message(text: "I'm also normal")]
@inline(__always)
func foreachMessage(function: (Message) throws -> ()) rethrows {
try pinnedMessages.forEach(function)
try normalMessages.forEach(function)
}
If you also need to know the type of the message, you should either process the arrays individually, without a helper function, or let your closure take another argument:
enum MessageType {
case pinned
case normal
}
@inline(__always)
func foreachMessage(function: (Message, MessageType) throws -> ()) rethrows {
try pinnedMessages.forEach { try function($0, .pinned) }
try normalMessages.forEach { try function($0, .normal) }
}
foreachMessage { message in
print(message)
}
foreachMessage { message, type in
print(message, type)
}
Using this kind of method, frees you from the disadvantage of concatenating the two arrays: memory and performance overhead.
If you're displaying these messages as if they're in one array, the index of the first normal message, will simply be after the index of the last message in the pinnedMessages array. pinnedMessages.count will be equal to that array's last index + 1, equalling the first index of the normal messages.
GlobalArraythat concatenate them and return them:var allMessages: [Message] { return pinnedMessages + normalMessages }