If I have a uiviewcontroller with a instance variable "direction". I can do
MyViewController.direction
but if I don't want the value but a string with the variable name, so I want #"direction".
Is it possible?
You can retrieve the list of properties using class_copyPropertyList and you can use property_getName to retrieve the name of the property passing the struct returned by the first method.
You can read more on that in Objective-C Runtime programming guide in the Declared Properties section.
Related
What does the underscore mean before momentDate? Why is it needed?
The underscored variable name refers to the underlying storage for the Binding struct. This is part of a language feature called Property Wrappers.
Given one variable declaration, #Binding var momentDate: Date, you can access three variables:
self._momentDate is the Binding<Date> struct itself.
self.momentDate, equivalent to self._momentDate.wrappedValue, is a Date. You would use this when rendering the date in the view's body.
self.$momentDate, equivalent to self._momentDate.projectedValue, is also the Binding<Date>. You would pass this down to child views if they need to be able to change the date.
For Binding, the "projected value" ($) is just self, and the difference between _ and $ is only in the access level. However, other property wrappers may project a different type of value (see the #SmallNumber example in the language guide).
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.
As I started developing with Swift and searching through different tutorials and documentations about the language, I'm not sure about one thing.
You can declare an object / value with a specific data type like this:
var aString:String = "Test"
var anObject:SKScene = ASceneClass()
Or you can just do it like this:
var aString = "Test"
var anObject = ASceneClass()
The result will be exactly the same (ASceneClass inherits from SKScene of course)
As everyone is doing it different I wonder if there's a logical reason behind it or you do it for readability ?
Declaring type right after variable name is called Type Annotation
When you don't do that, you have to provide initial value
var aString = "Test"
Often value is not known at that moment, or you are not even sure if it's going to be not nil value, then you can declare it as optional
var aString:String?
If you would like to declare variable without any initiaization but you are sure it's not going to evaluate to nil, you force unwrap it
var aString:String!
This is the definition. In practice, it's always better to use type annotations even when you initialize variable with value, because later in your program you will notice anytime you mess something with the type of the variable.
Also, When you declare an array or dictionary, usually nested ones, Xcode might expect them to have type annotations since it might have some issues with writing values when the type is not known in advance.
To recap
You will want to use type annotations whenever you can, which means whenever you are sure about the variable's type in advance
Recommended/Documented way to declare a variable in swift is as follow:
var <variable name>: <type> = <initial value/expression>
Note: Given form declares a stored variable or stored variable property. Its used when you are clear about type annotation of it.
Though its valid to declare variable without its Type.
var variableName = <initial value>
Note: When you don't know type annotation its mandatory to assign 'Initial value' to that variable.
Refer Swift Documentation on Declaration for more details.
Im new to learn swift.I recently found that the variables or constants are needed to be initialized with an initial number or by the initializer.But in struct they don't need to be initialized?
They do need.
From the Swift Language Guide:
Classes and structures must set all of their stored properties to an
appropriate initial value by the time an instance of that class or
structure is created. Stored properties cannot be left in an
indeterminate state.
You can set an initial value for a stored property within an
initializer, or by assigning a default property value as part of the
property’s definition.
Source: Initialization
An example to #vadian 's answer:
struct S {
init() {}
let a: String
}
This will not compile:
Playground execution failed: Test.xcplaygroundpage:11:13:
error: return from initializer without initializing all stored properties
init() {}
^
How does Swift implement ARC in property attributes? For example, how do I make my String variable use copy instead of strong in Swift?
You can use the #NSCopying attribute when you want the copy behaviour from Objective-C.
From the Swift Book:
Apply this attribute to a stored variable property of a class. This
attribute causes the property’s setter to be synthesized with a copy
of the property’s value—returned by the copyWithZone method—instead of
the value of the property itself. The type of the property must
conform to the NSCopying protocol.
The NSCopying attribute behaves in a way similar to the Objective-C
copy property attribute.
However, in the specific case of String properties, it's not necessary to do so.
Strings are a value type in Swift. As such, when an existing String is assigned to a new variable, the variable actually stores a copy of the String, rather than a reference to the existing one.
Swift’s String type is a value type. If you create a new String value,
that String value is copied when it is passed to a function or method,
or when it is assigned to a constant or variable. In each case, a new
copy of the existing String value is created, and the new copy is
passed or assigned, not the original version.
So, the #NSCopying attribute is to be used when you have properties of a reference type that you want to set using the copy behaviour.