Well, now they can add ~Copyable to the struct and avoid that. With Rust-like ownership and borrow constructions.
Theoretically, yes, but then you need explicitly use
borrowing
/
consuming
for every function that handles those types. If you do it for all application models, it will become unwieldy. From what I understood, the ownership and noncopyable enhancements to the language came from a need to improve Swift's performance predictability: you don't get unexpected copies of variables. As such, it
does make sense to use them in things like tight loops or things that are in a hot path, but they're not designed to be the default setting. Besides, and while this will change in the future, non-copyable types as of now can't be used with Swift Generics nor conform to protocols. You can't even do
var someVar: NonCopyableType?
because that's syntactic sugar for
Optional<NonCopyableType>
and, as I said, generics are not yet supported.
Realistically, you don't need to use any of that by default for a typical iOS app. You may even find out that true value types (like
struct
s) are more performant than the "optimized", reference-only type, even for medium-sized models. There are good WWDC talks on this (both
Understanding Swift Performance and
Optimizing Swift Performance). In fact, the issue with big struct types is not (usually) the stack size as they feared, but rather the increased Automatic Reference Counting (ARC) traffic you get (for
each reference-counted variable you have in a struct, like
Array
or
String
, you have to do a retain cycle, while if your model is class based you retain the entire class instead of the individual properties). The copying of the stack contents themselves is negligible unless you're building an exotic data structure.
For some big models you may see some benefit from implementing Copy on Write (CoW), like the Swift Standard Library does for
String
or
Array
, which would have also ensured that the models were always passed by reference, like Swift maintainers suggest
here. This would have kept the API of the model unchanged for external users, like a regular struct, while potentially reducing ARC traffic. But this is something that should be done IF the model has poor performance with the off-the-shelf solution (a regular struct), AND profiling/benchmarking shows that it's beneficial to adopt CoW. Implementing it by default in all models is a premature optimization that might not even turn out to be net-positive in performance (small structs are really fast, and you'd be adding another level of indirection (+ more ARC) by using a class instead).
Plus the compiler is smart enough to know not to copy entire structs if some properties are not needed (through function specialization), or to modify them in place if it can check at compile time that no other piece of code is using the same struct. Generally speaking, it's not something you need to worry about, IMHO.