Swift: Classes are reference types? - swift

I wanted to know why can't you hold instances of a class in a variables -> why does it have to be a reference. That's a bit problematic because if I want to store a object in a two variables it any changes made to the object will change the values of my variables. Is there a way around it ?
thanks,

you can use struct instead of class because structures pass by value
Why Choose Struct Over Class?

Related

Stopping reference variables changing the value of the original variable

I am assigning the value of a custom class to another variable. Updating the value of the new variable is affecting the value of the original variable. However, I need to stop the reference variable from updating the original variable.
Here's a basic representation of what's happening:
var originalVariable = CustomClass()
originalVariable.myProperty = originalValue
var referenceVariable = originalVariable
referenceVariable.myProperty = updatedValue
print("\(originalVariable.myProperty)") //this prints the ->updatedValue<- and not the ->originalValue<-
I've tried wrapping the referenceVariable in a struct to make it a value type but it hasn't solved the problem.
I've found information regarding value and reference types but I haven't been able to find a solution.
My question in a nutshell: How do I stop an update to a reference variable from updating the original variable that it got its value assigned from?
Thanks in advance.
The whole point of reference semantics (as used by classes) is that all variables point to the same (i.e., they reference the same) object in memory. If you don't want that behaviour, you should use value types (Struct, Enum, Array...) or create copies of your object.
If CustomClass implements the NSCopying protocol you can do:
var referenceVariable = originalVariable.copy()
If it doesn't, you'll have to find some other way to copy it or implement the protocol yourself.
Wrapping the class in a struct will just make two different structs each containing a different reference to the same object.

Swift - what should the default values of properties be in the parent class?

Not sure if I worded this question correctly, but here's my issue: I have a base class and a subclass, and my base class should never be instantiated on its own (in other languages it would be abstract). I know abstract classes aren't a thing in Swift. I have some computed read-only properties that change what they return in each subclass; they are more or less customized constants. Firstly, are overridden computed properties the best way to handle this kind of thing? Secondly, if these variables need to get initialized, i.e. can't be nil, what should they be initialized to in the parent class? Is there a way to otherwise indicate that the parent class shouldn't be initialized on its own?
You probably should use protocol instead of base class in your case. All common implementation can be done in protocol extensions and you won't need to provide default values for constants - just specify required get methods in the protocol.

Should I use Class, Struct or Dictionary for an object containing some simple config parameters?

In an IOS project, I want the user to be able to config their UI.
The user will pick:
"backgroundColor", "fontColor", "fontSize", "font", "lineSpace"
in UIConfigViewController and when user hit done, the result will be stored in an object and passed back into ReadingViewController.
Should I use Struct, Class or Dictionary for this result object?
Can I use the Struct like this?
Ended up using NSManagedObject
You could simply implement NSUserDefaults.standardUserDefaults, which is basically a dictionary for user settings. The main advantage for that is it's designed to be accessible at the global scope so no need to pass the object around.

dynamic setting and getting values from Swift class

I'd like to copy all properties from a NSManagedObject over to a "regular" Swift class. I don't want to do this manually, i.e. make a regular class with all the properties for every NSManagedObject and then manually copy all those values.
I do know how to read property names and values dynamically from my managed object, but how to set them on a Swift class in a way that I can then use those values like
mySwiftObject.name
which returns a String or
mySwiftObject.age
which returns a Number (as those are the types on the Managed Object). Custom subscripting and stuff like that came to my mind, but I didn't manage to achieve this... Is there a nice way to do exactly that?

How to share a Dictionary instance in Swift?

According to the Swift Programming Language reference, Dictionary instances are copied whenever they are passed to a function/method or assigned to a constant or variable. This seems inefficient. Is there a way to efficiently share the contents of a dictionary between two methods without copying?
It's true the documentation says that but there are also various notes saying it won't affect the performance. The copying will be performed lazily - only when needed.
The descriptions below refer to the “copying” of arrays, dictionaries, strings, and other values. Where copying is mentioned, the behavior you see in your code will always be as if a copy took place. However, Swift only performs an actual copy behind the scenes when it is absolutely necessary to do so. Swift manages all value copying to ensure optimal performance, and you should not avoid assignment to try to preempt this optimization.
Source: Classes & Collections
Meaning - don't try to optimize before you actually encounter performance problems!
Also, don't forget that dictionaries are structures. When you pass them into a function, they are implicitly immutable, so no need for copying. To actually pass a mutable dictionary into a function, you can use an inout parameter and the dictionary won't be copied (passed by reference). The only case when a mutable dictionary passed as a parameter will be copied is when you declare the parameter as var.
You always have the option to define a custom, generic class with a Dictionary attribute:
class SharedDictionary<K, V> {
var dict : Dictionary<K, V>
// add the methods you need, including overloading operators
}
Instances of your SharedDictionary will be passed-by-reference (not copied).
I actually talked to someone on the Swift team today about "pass by reference" in Swift. Here is what I got:
As we all know, struct are pass by copy, classes are pass by
reference
I quote "It is extremely easy to wrap a struct in a class.
Pointing to GoZoner's answer.
Even though though a struct is copied, any classes defined in
the struct will still be passed by reference.
If you want to do traditional pass by reference on a struct, use
inout. However he specifically mentioned to "consider adding in
another return value instead of using inout" when saying this.
Since Dictionary defines KeyType and ValueType as generics:
struct Dictionary<KeyType : Hashable, ValueType>
I believe this means that if your KeyType and ValueType are class objects they will not be copied when the Dictionary itself is copied, and you shouldn't need to worry about it too much.
Also, the NSDictionary class is still available to use!
As other said "Swift only performs an actual copy behind the scenes when it is absolutely necessary to do so." so performance should not be a big problem here. However you might still want to have a dictionary passed by reference for some other reasons. In that case you can create a custom class like below and use it just like you would use a normal dictionary object:
class SharedDictionary<K : Hashable, V> {
var dict : Dictionary<K, V> = Dictionary()
subscript(key : K) -> V? {
get {
return dict[key]
}
set(newValue) {
dict[key] = newValue
}
}
}
Trust the language designers: the compiler is usually smarter than you think in optimizing copies.
You can hack around this, but I don't frankly see a need before proving it's inefficient.