Closed dalewking closed 8 months ago
I was thinking about the same feature and found this issue.
I've been working to accomplish this and I think I have got something at a good level but still needs some refinement that needs some discussion.
Given a data class like:
data class DataClass(
val stringValue: String,
val optionalStringValue: String?,
val intValue: Int,
val optionalIntValue: Int?,
val booleanValue: Boolean,
val optionalBooleanValue: Boolean?
)
the plugin will generate the following extension function for Swift
extension MultiPlatformLibrary.DataClass {
func betterCopy(
stringValue: (() -> Swift.String)? = nil,
optionalStringValue: (() -> Swift.String?)? = nil,
intValue: (() -> Swift.Int32)? = nil,
optionalIntValue: (() -> MultiPlatformLibrary.KotlinInt?)? = nil,
booleanValue: (() -> Swift.Bool)? = nil,
optionalBooleanValue: (() -> MultiPlatformLibrary.KotlinBoolean?)? = nil
) -> MultiPlatformLibrary.DataClass {
return MultiPlatformLibrary.DataClass(stringValue: (stringValue != nil) ? stringValue!() : self.stringValue,optionalStringValue: (optionalStringValue != nil) ? optionalStringValue!() : self.optionalStringValue,intValue: (intValue != nil) ? intValue!() : self.intValue,optionalIntValue: (optionalIntValue != nil) ? optionalIntValue!() : self.optionalIntValue,booleanValue: (booleanValue != nil) ? booleanValue!() : self.booleanValue,optionalBooleanValue: (optionalBooleanValue != nil) ? optionalBooleanValue!() : self.optionalBooleanValue)
}
}
For each constructor argument of the data class there is a closure parameter in the betterCopy
function (yeah, we might need to discuss about its name!). I decided to use a closure to also support optional parameters, so it works this way:
nil
(so you can set nil
for an optional parameter)A small example of how it can be used:
let dataClass = DataClass(
stringValue: "aValue",
optionalStringValue: nil,
intValue: 0,
optionalIntValue: 1,
booleanValue: false,
optionalBooleanValue: nil
)
let dataClassWithNewValues = dataClass.betterCopy(stringValue: {"aNewValue"}, optionalIntValue: {nil}, booleanValue: {true})
dataClassWithNewValues
will have new values for:
stringValue
-> "aNewValue"
optionalIntValue
-> nil
booleanValue
-> true
At the same time optionalStringValue
, intValue
and booleanValue
are left unchanged.See the related PR for more examples.
I think we need to discuss it with @Alex009 if the idea is cool and can be integrated officially into this library.
@ema987 it's intresting way, i will check pr later
Similar to #8, but requires a different solution There is no good Swift way to call a copy methods on a Kotlin data class because the default parameter values are not provided, but it isn't possible to actually have parameters default to values based on the object so it is not possible to write an exact replica of the copy function. It isn't important that what is generated be the same syntactically. It is more important to get the same functionality, e.g to make a copy of the data class changing only part of the object without having to specify every property.
Here is a SO post that talks about how to write such a method in Dart, which I know is not Swift, but the same concepts and limitations apply: https://stackoverflow.com/questions/68009392/dart-custom-copywith-method-with-nullable-properties
The best alternative is probably the one that takes nullable parameters that default to nil and if it is nil the property is unchanged. The wrinkle is for properties that were nullable, in which case you add a boolean parameter for each such property that says whether to treat null as null or unchanged.