How do you store data in a program? Well, you store it in variables, but you already knew that didn’t you? Here is my first post about Swift variables, where we discuss their declaration and definition. In particular, we will mostly be discussing the concept of Swift variables and constants.
Swift Variables and Constants
There are 2 ways to store a value in Swift, as a variable, or a constant. Here is how to create each:
var myNumber = 45 //Variable let theAnswer = 42 //Constant
That seems simple enough. From other programming languages, one might think, var is a type for a variable and let is the type for a constant, right? Well, while the first may be true in C#, it is not in Swift. In Swift, these are just keywords defining whether the stored value (irrelevant of its specific type) is stored as a variable or a constant.
That leads us to the next point, notice the lack of an explicit type there? Swift has implicitly typed these stored values. You CAN set the type if you want, particularly if you do not initialize them, but that is not the case here. Here, the compiler saw that I wanted to store 45 or 42, and realized, “Well, 42 is an Int, so ‘theAnswer’ must be storing an Int!”
If you really want to type your variables, you would do so this way:
var theNumber: Double
You must always initialize your let constants, even if you explicitly type them. One reason to explicitly type a constant, as suggested in Apple’s Swift Language Reference, is if you wanted a double, but only wanted to type an Int literal, i.e.:
let myExpValue: Double = 29
So it would actually store 29.0 as the value for myExpValue, even though you only typed 29. Just for fun, I tried the opposite, doesn’t work so well. It gives the error, “Cannot convert value of type ‘Double to specified type ‘Int’.” The error does make sense though. You have to explicitly convert it to work.
Use of Swift Constants
As one would expect, a numeric constant is a constant, so when you try to edit it, a compiler error is shown:
let theAnswer = 42 theAnswer = 21 //error: cannot assign to value: 'theAnswer' is a 'let' constant
That makes sense, but really seems to limit the use for let stored values? I mean, constants are great and all, but I don’t tend to have them all over my code, usually just a few per class, usually for stringly typed (not a typo, but a nickname) things like Notifications.
Apple seems to use let all over the place, so why would you want to use constants everywhere?
Convenience Variables
Well, for one, I’m sure most of us have made temporary variables that do not change after their initialization. Something like this example:
CGFloat PADDING_OUTER = 5; CGFloat textLabelHeight = [@"0" sizeWithAttributes:@{NSFontAttributeName : [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline]}].height; CGFloat detailLabelHeight = [@"0" sizeWithAttributes:@{NSFontAttributeName : [UIFont preferredFontForTextStyle:UIFontTextStyleCaption1]}].height; CGFloat totalHeight = PADDING_OUTER + textLabelHeight + detailLabelHeight + PADDING_OUTER; self.tableView.rowHeight = totalHeight;
Sure, we could have done:
self.tableView.rowHeight = 5 + [@"0" sizeWithAttributes:@{NSFontAttributeName : [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline]}].height + [@"0" sizeWithAttributes:@{NSFontAttributeName : [UIFont preferredFontForTextStyle:UIFontTextStyleCaption1]}].height + 5;
But which is more readable? PADDING_OUTER, textLabelHeight, detailLabelHeight, and totalHeight are all PERFECT places to use let.
Class References
Secondly, the assignment is constant, but are its contents? For reference types (and Classes are reference types), the contents usually aren’t. As such, you could do something like this:
let nf = NumberFormatter() nf.numberStyle = .currency if let formattedNumber = nf.string(from: 7.145) { print(formattedNumber) //Output: $7.14 }
We never reassign “nf” to another NSNumberFormatter, but we do change some of its properties, in this case the numberStyle. This another great use of let in Swift. If you are curious about that “if let” statement, that is something called Optional Binding, which you can read about in the post Swift Optionals – Declaration, Unwrapping, and Binding. It’s basically a fancy way to check if an optional is equal to nil, and if it is not, to store it to a constant for later use. The stringFromNumber method returns an optional string, so if it can make a valid string, the optional contains that String, if it cannot, it returns nil. This is why we needed this optional binding, to get the real Swift String out of that Optional.
Conclusion
In this post, I have often used the term “stored value” to refer to variables and constants, as opposed to saying variable variables and variable constants, (suddenly I am reminded of “Mario Mario” and “Luigi Mario” from the Mario Bros. Movie). For future posts though, unless I am talking about the differences again, I will probably just refer to them both as variables for the sake of simplicity. I will refer to constants as such when I need to specify the difference, but more often than not, I will probably refer to our NSNumberFormatter “nf” from above as variable, even if I do make it a constant let, in the code.
I hope you found this article helpful. If you did, please don’t hesitate to share this post on Twitter or your social media of choice, every share helps. Of course, if you have any questions, don’t hesitate to contact me on the Contact Page, or on Twitter @CodingExplorer, and I’ll see what I can do. Thanks!