*Declaring things with let whenever possible is best practice, because that will allow the compiler to perform optimizations that it wouldn't be able to do otherwise.
*We believe it's better practice to let the compiler infer types automatically where possible, because then you get one of the main advantages of Swift: concise and easy to read code.
*Note that in Swift you use true/false for boolean values(unlike the convention of using YES/NO in Objective-C).
*If statement: the parentheses around the condition are optional, and braces are required even for 1-line statements.
*String interpolation: whenever you want to substitute something in a string in Swift, simply use this syntax: \(your expression).
*Note that you do not necessarily need to subclass anything(unlike in Objective-C, where you must subclass NSObject or something that derives from NSObject).
*Note that any properties you declare must be set to an initial value when you declare them, or in your initializer. If you don't want to set your properties to an initial value, you'll have to declare them as optional.
*Initializers are always named init in Swift -- you can have more than one if you want, but they need to take different parameters.
*To declare a method, you use the func keyword. You then list the parameters(you must be explicit with the types), add the -> symbol, and finally list the return type.
*Note that when you call a method on an instance of a class, the first parameter does not need to be named(but the rest do).
*let possibleTipsInferred = [0.15, 0.18, 0.20]
let possibleTipsExplicit:[Double] = [0.15, 0.18, 0.20]
This shows an example of creating an array of doubles, with both inferred and explicit typing. Note that [Double] is a shortcut for Array<Double>.
*for possibleTip in possibleTipsInferred { }
for i in 0..<possibleTipsInferred.count { }
The ..< operator is a non-inclusive range operator and doesn't include the upper bound value. There's also a ... operator which is inclusive.
*You will see a warning on the line for possibleTipsExplicit saying the variable isn't used. It recommends you replace the variable name with _, which is Swift 2 way to make an unnamed variable, so that it's a very clear that you don't intend to use this for anything.
*Note that [Int: Double] is just a shortcut for Dictionary<Int, Double>.
*
var subtotal: Double { get { return total / (taxPct + 1) } set(newSubtotal) { //... } } |
A computed property does not actually store a value. Instead, it is computed each time based on other values. Here, you calculate the subtotal each time it is accessed based on the current values of total and taxPct.
*Note that you do not have to put a class prefix on your class names like you did in Objective-C to avoid namespace collisions (i.e. you don't have to name this RWTViewController). This is because Swift has namespace support, and the classes you create in your project are in their own namespace.
*Whenever you override a method in Swift, you need to mark it with the override keyword. This is to help you avoid a situation where you override a method by mistake.
*You're prefixing these variables with the @IBOutlet keyword. Interface Builder scans your code looking for any properties in your view controller prefixed with this keyword. It exposes any properties it discovers so you can connect them to views.
**You're marking the variables with an exclamation mark (!). This indicates the variables are optional values, but they are implicitly unwrapped. This is a fancy way of saying you can write code assuming that they are set, and your app will crash if they are not set.
Implicitly unwrapped optionals are a convenient way to create variables you know for sure will be set up before you use them (like user interface elements creates in the Storyboard), so you don't have to unwrap the optionals ever time you want to use them.
*In Swift you must be explicit when converting one type to another.
*tipCalc.total = Double((totalTextField.text! as NSString).doubleValue)
Swift's String class does not have access to every method that NSString has. In particular, Swift's String class does not have a method to convert to the string to a double; however NSString does. You can call (xxx as NSString)() on a Swift String to convert it to an NSString. Then, you can call any method that is available on NSString, such as a method to convert to a double.
*
var keys = Array(possibleTips.keys) keys.sortInPlace() for tipPct in keys { let tipValue = possibleTips[tipPct]! let prettyTipValue = String(format:"%.2f", tipValue) results += "\(tipPct)%: \(prettyTipValue)\n" } |
Any Dictionary access (subscripting or using updateValue(forKey:) method) returns nil when the key is absent. In our case, we are sure that the key will have a value. For this, we put an exclamation mark "!" at the very end of the tipValue assignment, which is called forced unwrapping.
Using an initializer on String that accepts a format string (like stringWithFormat in Objective-C).
*
let tipAndTotal:(Double, Double) = (4.00, 25.19)
let (theTipAmt, theTotal) = tipAndTotal theTipAmt theTotal
To access the individual elements of your tuple, you have two options: accusing by index, or decomposing by name. This syntax allows you to make a new constant that refers to each element in the tuple, with a particular name.
*If you want to have a protocol with optional methods, you must prefix the protocol with the @objc tag (even if your class is not interoperating with Objective-C). Then, you prefix any method that can be optional with the optional tag.
Not that you marked the protocol with @objc, you must annotate all the methods that implement that protocol with @objc as well to satisfy the compiler.
*
speaker.TellJoke?()
speaker = Dog()
speaker.TellJoke?()
These lines use a technique called optional chaining to do this. If you put a ? mark after the method name, it will check if it exist before calling it. If it does not exist, it will behave as if you've called a method that returns nil.
Optional chaining is a useful technique anytime you want to test if an optional value exists before using it, as an alternative to the if let(optional binding) syntax.
*One of the requirements of implementing UITableViewDataSource is that your class extends NSObject (either directly or through intermediate classes).