Difference between declaring a variable in ios Swift? - ios

I am learning Swift recently and I found that there are two types of declaration for a variable.
var indexArray = NSMutableArray() //and
var indexArray : NSMutableArray = NSMutableArray()
Am just wondering what is the difference between them? Will it replicate in any kind of assigning values to the variable?

Here is a simple explanation
var indexArray = NSMutableArray()
As the above, indexArray variable can be any one , String , Int , ....... You didn't specifically give any type for that variable.
var indexArray : NSMutableArray = NSMutableArray()
In here you specifically give that indexArray is a NSMutableArray
You can provide a type annotation when you declare a constant or variable, to be clear about the kind of values the constant or variable can store. Write a type annotation by placing a colon after the constant or variable name, followed by a space, followed by the name of the type to use.
This example provides a type annotation for a variable called welcomeMessage, to indicate that the variable can store String values:
var welcomeMessage: String
The colon in the declaration means “…of type…,” so the code above can be read as:
Declare a variable called welcomeMessage that is of type String.
The phrase “of type String” means “can store any String value.” Think of it as meaning “the type of thing” (or “the kind of thing”) that can be stored.
The welcomeMessage variable can now be set to any string value without error:
welcomeMessage = "Hello"
You can define multiple related variables of the same type on a single line, separated by commas, with a single type annotation after the final variable name:
var red, green, blue: Double”
* Note *
It is rare that you need to write type annotations in practice. If you provide an initial value for a constant or variable at the point that it is defined, Swift can almost always infer the type to be used for that constant or variable, as described in Type Safety and Type Inference. In the welcomeMessage example above, no initial value is provided, and so the type of the welcomeMessage variable is specified with a type annotation rather than being inferred from an initial value.
Excerpt From: Apple Inc. “The Swift Programming Language (Swift 2
Prerelease).” iBooks. https://itun.es/us/k5SW7.l

One of the important language feature of Swift is Type Inference. What it means is that a variable can identify what is its type based on the value its assigned with.
var indexArray = NSMutableArray()
By the above statement, it is implicitly known that the variable indexArray is of type NSMutableArray without being specified.
Whereas in the other type of declaration,
var indexArray : NSMutableArray = NSMutableArray()
you are explicitly specifying that the variable indexArray is of type NSMutableArray before assigning a value to it. If you assign a different type to it, the compiler is throw an error.
var indexArray : NSMutableArray = NSString() // This is wrong
A very good starting point is to go over the Swift Language document by Apple.

No difference, both are same..
there is difference between the follwing declarations,
var welcomeMessage: String? - can be nil or assigned nil at any point of time
var welcomeMessage: String! - can never be nil at any point of time when using that variable.
var welcomeMessage: String - will throw error saying, class has no initializers
But there is no difference between the following two,
var welcomeMessage: String = String()
var welcomeMessage = String()

In the first case, indexArray takes the type of the assignment source automatically, so in your example case the statements are exactly the same.
The difference besides the second version being more explicit is that you could tweak the type of indexArray - for example to a base class - in the second case;
var indexArray = NSMutableArray() // indexArray is type NSMutableArray
var indexArray : NSArray = NSMutableArray() // indexArray is type NSArray
// but contains an NSMutableArray
Of course, if you declare a variable without assigning it you can't take the type automatically from the assignment source, so then you need the explicit type declaration.

Related

Why does iterating through a series of variables in a for-in loop throw a conditional warning, but setting them individually does not? [duplicate]

I met a strange issue today. Please look at this code:
class A {
var button1: UIButton!
var button2: UIButton!
func foo() {
let array = [button1, button2]
}
}
Xcode says that array is [UIButton?] type. For some reason Swift4 casts UIButton! elements to UIButton?. Why?
EXPLANATION
ImplicitlyUnwrappedOptional is not a distinct type, rather a normal Optional with an attribute declaring its value may be implicitly forced (based on SE-0054):
However, the appearance of ! at the end of a property or variable declaration's type no longer indicates that the declaration has IUO type; rather, it indicates that (1) the declaration has optional type, and (2) the declaration has an attribute indicating that its value may be implicitly forced. (No human would ever write or observe this attribute, but we will refer to it as #_autounwrapped.) Such a declaration is referred to henceforth as an IUO declaration.
Thus when you use this:
let array = [button1, button2]
The compiler derives the array type to [UIButton?], because the type of the button1 and button2 is Optional<UIButton>, not ImplicitlyUnwrappedOptional<UIButton> (even if only one of the buttons was optional, it would derive the optional type).
Read more in SE-0054.
Side note:
This behavior is not really related to arrays, in the following example the type of button2 will be derived to UIButton? even though there is the ! and there is a value set in button:
var button: UIButton! = UIButton()
func foo() {
let button2 = button // button2 will be an optional: UIButton?
}
SOLUTION
If you want to get an array of unwrapped type, you have two options:
First, as Guy Kogus suggested in his answer, use explicit type instead of letting swift derive it:
let array: [UIButton] = [button1, button2]
However, if per chance one of the buttons contains nil, it will cause Unexpectedly found nil crash.
While by using implicitly unwrapped optional instead of optional (! instead of ?) you are claiming that there never will be nil in those buttons, I would still prefer the second safer option suggested by EmilioPelaez in his comment. That is to use flatMap (compactMap in Swift 4+) which will filter out nils, if there are any, and will return an array of unwrapped type:
let array = [button1, button2].flatMap { $0 }
Because UIButton! is not a type, or rather it is a UIButton? with some conventions. The ! means always implicitly unwrap the optional. The following
var x: UIButton!
// Later
x.label = "foo"
Is syntactic sugar for
var x: UIButton?
// Later
x!.label = "foo"
When you create an array of them. The compiler has the choice of implicitly unwrapping them and inferring [UIButton] or leaving them as optional and inferring [UIButton?]. It goes for the safer of the two options.
Swift is playing it safe by assuming them to be optionals, rather than unwrapping them by default, since they can technically be nil. If you try to explicitly mark them as implicitly-unwrapped like this
let array: [UIButton!] = [button1, button2]
you will receive the following error:
error: implicitly unwrapped optionals are only allowed at top level and as function results
In that case, if you want them to be unwrapped then just define it as
let array: [UIButton] = [button1, button2]
I'm finding Swift blog as really the best source for such changes so:
Before Swift 4:
A mental model many people have for implicitly unwrapped optionals is that they are a type, distinct from regular optionals. In Swift 3, that was exactly how they worked: declarations like var a: Int? would result in a having type Optional, and declarations like var b: String! would result in b having type ImplicitlyUnwrappedOptional.
Swift 4
The new mental model for IUOs is one where you consider ! to be a
synonym for ? with the addition that it adds a flag on the declaration
letting the compiler know that the declared value can be implicitly
unwrapped.
In other words, you can read String! as “this value has the type
Optional and also carries information saying that it can be
implicitly unwrapped if needed”.
This mental model matches the new implementation. Everywhere you have
T!, the compiler now treats it as having type T? , and adds a flag in
its internal representation of the declaration to let the type checker
know it can implicitly unwrap the value where necessary.
All the quotes taken from Swift blog

Difference between property and class instance swift

I am new to swift programming, and i have a question as follows:
I have a class named Weather
class Weather {
}
then i define 2 things:
var currentWeather1 = Weather()
var currentWeather2: Weather!
Are they different syntax or the same meaning? What are they actually created in memory with these 2 statements?
var currentWeather1 = Weather()
This declares a variable of type Weather and assigns a new instance of Weather to it. The syntax Weather() creates an instance and runs its initialiser. The compiler infers the type of currentWeather1 to be Weather. The statement above is exactly equivalent to
var currentWeather1: Weather = Weather()
The other statement:
var currentWeather2: Weather!
declares an implicit optional variable. This variable is of optional type i.e. it's type is Optional<Weather>. This means that it needs to be unwrapped if you want to get at the value. However, the ! means that the compiler will put in the unwrapping code for you. A normal optional would look like this:
var currentWeather3: Weather?
but when you need to use it, you have to unwrap it e.g.
if let foo = currentWeather3
{
// foo is the unwrapped weather
}
let string = currentWeather3?.description // string is an optional String
let string2 = currentWeather3!.description // string2 is a String
The last example with the ! is a forced unwrapping. If currentWeather3 is nil, when the line executes, the program will crash. The declaration of currentWeather2 means the compiler treats every mention of currentWeather2 as if it has an implicit ! after it.
The simple answer is
var currentWeather2: Weather!
Declares a variable by creating a references of the Weather in system table. But does not allocate any memory for the variable
var currentWeather1 = Weather()
Weather object is created by allocating memory and the location of the variable is assigned to the system table entry of age.
var currentWeather2: Weather!
The above statement does not allocate memory for an instance of Weather, it only allocates a stack variable currentWeather2. The reference pointers only are allocated on stack. The time it hits the currentWeather2 = Weather(), it allocates on "heap".
To access class properties & methods refer directly from the class name rather than with an instance of the class.
it will be helpful to understand more,it's in C# but concept is same
https://www.codeproject.com/Articles/76153/Six-important-NET-concepts-Stack-heap-value-types

Determining from Objective-c if a Swift property is declared as dynamic

I have been trying for some time to inspect a Swift class, and determine if any of the properties are declared as dynamic. My example class is as below:
class SwiftTestClass : DBObject {
dynamic var SwiftTestString : String!
dynamic var SwiftTestNumber : NSNumber!
dynamic var lowercaseField : String!
var nonDynamicVariable : String!
func testThyself() {
SwiftTestClass.query().fetchLightweight().removeAll()
let newObject = SwiftTestClass();
newObject.SwiftTestString = "hello, world"
newObject.SwiftTestNumber = 123
newObject.lowercaseField = "lowercase"
newObject.nonDynamicVariable = "should not be persisted"
newObject.commit()
let result = SwiftTestClass.query().fetch().firstObject;
print(result)
}
}
I am basically trying to pick out the fact that the property nonDynamicVariable is not declared as dynamic as the rest of them are.
DBObject is a subclass of NSObject.
I have tried:
Looking at the type encoding of the property, they are identical (type for type)
Seeing if they have a difference in the method implementations, they do not. (e.g. class_getMethod), the dynamic properties still have getter/setter methods.
Grabbing the Ivars to see if there is any difference there
Looking at all of the property attributes, also identical.
What I do know:
If I try to class_replaceMethod for the <propertyName>/set<propertyName>, it works for a dynamic property (as you would expect, because it adds objc compatibility) but fails to work (but does replace?, well, the memory address of the method changes!) or be actioned on the non dynamic property.
Does anyone know how to differentiate the two property declarations in swift from objc?
Thanks

How can NSMutableArray add object using let in swift

I created a NSMutableArray in swift using let and
when I add addObject in the mutableArray then it will add it even though I
used the let to assign a constant. Can anyone explain how let works in swift? If it doesn't allow you to add value in later then how is the following
code working?
let arr : NSMutableArray = [1,2,3,4,5]
arr.addObject(6)
println(arr)
Classes are reference types, and NSMutableArray is a class.
Foundation's NSMutableArray is different from Swift's Array: the latter is a value type.
If you create a constant NSMutableArray:
let ns: NSMutableArray = ["a", "b"]
then this works:
ns.addObject("c")
but this doesn't:
ns = ["d", "e"] // nope!
because you can change the content of the reference but you can't change what is assigned to the constant.
On the other hand, with Swift's Array:
let sw: [String] = ["a", "b"]
the constant can't be changed because it's a value, not a reference.
sw.append("c") // nope!
Doc: Structures and Enumerations Are Value Types and Classes Are Reference Types
disclaimer: this answer only applies to NS type data structures, please see #Eric D's answer for the full picture
let when used with a class just means the variable cant be changed, eg, to another array. If you dont want the array to be editable, use a normal NSArray and not a mutable one
let arr : NSMutableArray = [1,2,3,4,5]
arr = [1,2,3,4,5] //error trying to assign to a let variable that has already been assigned
arr.addObject(6) //fine because we are not changing what is assigned to arr, but we are allowed to change the object that is assigned to arr itself
I think your understanding of what a constant variable is, is a bit too strict.

Struct value types in Swift

I understand the difference between 'Value Types' and 'Reference Types'. I know 'Structures' are 'Value Types' and according to the Swift documentation all the values stored by the structure are themselves value types. Now my question is what if I have a stored property in a Struct that is an instance of a class. In that case, would the whole class would be copied or just its address?
Any help would be appreciated.
It copies the pointer to the instance. I just tested this in a playground.
struct MyStruct {
var instance: MyClass
}
class MyClass {
var name: String
init(name: String) {
self.name = name
println("inited \( self.name )") // Prints "inited Alex" only once
}
}
var foo = MyClass(name: "Alex") // make just one instance
var a = MyStruct(instance: foo) // make a struct that contains that instance
var b = a // copy the struct that references the instance
foo.name = "Wayne" // Update the instance
// Check to see if instance was updated everywhere.
a.instance.name // Wayne
b.instance.name // Wayne
What is different though, is that it's now two different references to the same object. So if you change one struct to a different instance, you are only hanging it for that struct.
b.instance = MyClass(name: "Vik")
// a and b no longer reference the same instance
a.instance.name // Wayne
b.instance.name // Vik
The playground is a great way to test out questions like these. I did not know the answer definitively when I read this question. But now I do :)
So don't be afraid to go play.
I think you misread the documentation. According to the The Swift Programming Language,
All structures and enumerations are value types in Swift. This means that any structure and enumeration instances you create—and any value types they have as properties—are always copied when they are passed around in your code.
Since classes are reference types, not value types, they are not copied even if they are properties of a value type, so only the address is copied.

Resources