mercredi 27 janvier 2021

Strategies for adapting from copy-by-reference in Objective-C to copy-by-value in Swift

I'm converting a project from Objective-C to Swift, and am running into a lot of bugs based on the change from an NSDictionary being a class that copies by reference to a Dictionary being a struct that copies by value. Here's a simplified example:

var recentMessages = [String: [String]]()

func logMessage(_ message: String, forChannel channel: String) {
    let channelMessages = self.recentMessages[channel]
    channelMessages.append(message)
}

In Objective-C, that updated the recentMessages property. In Swift, that only updates the channelMessages variable in the function scope, and I have to copy the change back to the property:

var recentMessages = [String: [String]]()

func logMessage(_ message: String, forChannel channel: String) {
    let channelMessages = self.recentMessages[channel]
    channelMessages.append(message)
    self.recentMessages[channel] = channelMessages
}

This workaround isn't difficult, and this answer called it the best approach four years ago. But it is adding a lot of clutter and I'm afraid of forgetting to apply it every time. Is there a way to more directly replicate the previous behavior?

I could avoid creating the local variable and update the property directly, but that seems like a big limitation and in more complex cases that will make the code hard to read:

var recentMessages = [String: [String]]()

func logMessage(_ message: String, forChannel channel: String) {
    self.recentMessages[channel].append(message)
}

In cases where the dictionary will be used repeatedly and with predictable keys, I think creating a custom class with properties that support all the keys would solve it. But I have places where a dictionary could include arbitrary keys that aren't predefined, or where a dictionary is only used briefly and creating a class for it would be overkill.

Is there another approach I'm missing that would restore that "copy by reference" behavior my current codebase depends on?

Aucun commentaire:

Enregistrer un commentaire