First, I understand the difference between value and reference types -this isn't that question. I am rewriting some of my code in Swift, and decided to also refactor some of the classes. Therefore, I thought I would see if some of the classes make sense as structs.
Memory: I have some model classes that hold very large arrays, that are constantly growing in size (unknown final size), and could exist for hours. First, are there any guidelines about a suggested or absolute size for a struct, since it lives on the stack?
Refactoring Use: Since I'm refactoring what right now is a mess with too much dependency, I wonder how I could improve on that. The views and view controllers are mostly easily, it's my model, and what it does, that's always left me wishing for better examples to follow.
WorkerManager
: Singleton that holds one or two Worker
s at a time. One will always be recording new data from a sensor, and the other would be reviewing stored data. The view controllers get the Worker
reference from the WorkerManager
, and ask the Worker
for the data to be displayed.
Worker
: Does everything on a queue, to prevent memory access issues (C array pointers are constantly changing as they grow). Listening: The listening Worker
listens for new data, sends it to a Processor
object (that it created) that cleans up the data and stores it in C arrays held by the Worker
. Then, if there is valid data, the Worker
tells the Analyzer
(also owned by the worker) to analyze the data and stores it in other C arrays to be fed to views. Both the Processor
and Analyzer
need state to know what has happened in the past and what to process and analyze next. The pure raw data is stored in a separate Record
NSManaged object. Reviewer Takes a Record
and uses the pure raw data to recreate all of the analyzed data so that it can be reviewed. (analyzed data is massive, and I don't want to store it to disk)
Now, my second question is, could/should Processor
and Analyzer
be replaced with structs? Or maybe protocols for the Worker
? They aren't really "objects" in the normal sense, just convenient groups of related methods and the necessary state. And since the code is nearly a thousand lines for each, and I don't want to put it all in one class, or even the same file.
I just don't have a good sense of how to remove all of my state, use pure functions for all of the complex mathematical operations that are performed on the arrays, and where to put them.
In Swift, structs are value types whereas classes are reference types. When you copy a struct, you end up with two unique copies of the data. When you copy a class, you end up with two references to one instance of the data. It's a crucial difference, and it affects your choice between classes or structs.
When choosing between structs and classes, it's important to remember the key differences: Classes are reference types, and structs are value types. If class inheritance is not needed, structs are faster and more memory efficient. Use structs for unique copies of an object with independent states.
So based on the above theory we can say that Struct is faster than Class because: To store class, Apple first finds memory in Heap, then maintain the extra field for RETAIN count.
While the struct itself lives on the stack, the array data lives on the heap so that array can grow in size dynamically. So even if you have an array with million items in it and pass it somewhere, none of the items are copied until you change the new array due to the copy-on-write implementation. This is described in details in 2015 WWDC Session 414.
As for the second question, I think that 2015 WWDC Session 414 again has the answer. The basic check that Apple engineers recommend for value types are:
Use a value type when:
- Comparing instance data with == makes sense
- You want copies to have independent state
- The data will be used in code across multiple threads
Use a reference type (e.g. use a class) when:
- Comparing instance identity with === makes sense
- You want to create shared, mutable state
So from what you've described, I think that reference types fit Processor
and Analyzer
much better. It doesn't seem that copies of Processor
and Analyzer
are valid objects if you've not created new Producer
s and Analyzer
s explicitly. Would you not want the changes to these objects to be shared?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With