Note: Use let
instead of var
to create a constant. It is best practice to use let
as much as possible. In Swift, let
is immutable, var
is mutable.
var faveNumber = 666 //type inferred as Int
var firstName = "Lucifer" // type iniferred as String
var isAwesome = true // type inferred as Bool
// Basic data types
var myInt : Int // type annotation (: == is of Type Int)
var myFloat : Float // 32-bit floating point
var myDouble : Double // 64-bit floating point
var myString : String
var myChar : Character
var myBool : Bool // true or false
...
- closed range operator
// Examples
0...100 35...66 0...someVar
..<
- half-open range operator. This does not include the last number on the right
0..<100 35..<66 0..<someArray.count
Use \()
for string interpolation
let location = "Hell"
var temperature = 666
println("It is \(temperature) degrees today in \(location)")
let quantity = 22
let unitPrice = 45.64
println("The amount is \(Double(quantity) * price)")
if myVar < 666 {
// do something
} else {
// do something else
}
var x = 0 // typed as Int
if x { //will not compile, as it is not a boolean.
// doSomething()
}
// logical AND: &&
if a > 50 && b < 80 { ... }
// logical OR: ||
if isActive || isAdmin { ... }
// use parentheses with complex conditions
if (quantity < 10 && isAvailable) || quantity >= 10 { ... }
...
operatorlet quantity = 5
switch quantity {
case 1:
println("Do this for case 1")
case 2:
println("Do this for case 2")
case 3...10: //3 dots is the range operator
println("DO this for 3 to 10")
default:
break //to explicitly end this otherwise empty case
}
The preferred way is using for-in
loop
var total = 0
for index in 1...10 { //for each-item in some-collection
total = total + index
}
println("The total is \(total")
var name = "karlo"
for eachChar in name {
println(eachChar)
}
// while loop
while condition {}
//...
}
//Do loop
do {
// ...
} while condition
By default, function parameters are treated as constants, not variables
// simple function
func myFunction() {
println("This is a simple function")
}
// with 1 param, ':' memans is type of
func myFunction(name : String) {
}
func myFunction(age : Int) {
age = age + 1 // not allowed - age is constant
}
// function with mutable parameter
func myFunction(var age : Int) { // to set fxn param as a variable
age = age + 1 // age va can now be updated
}
// function that return values
func myFunction() -> String {
return "Hello"
}
// using a default value param
func myFunction(name : String = "John Doe") {
println("Hello, \(name)")
}
// to call
myFunction("Jane") // Errror - will not work
myFunction() // OK - uses default param value
myFunction(name:"Lucy") // OK - provide named argument
var
or let
let daysInMonth = [34,2,34,345,45,5]
var colors = ["red","black","white"]
var bands : [String] // array of strings
bands = ["Motorhead", "Slayer", "Cannibal Corpse"]
//adding to end of array
flavors.append("Nepolitan") //add to end of array
flavors += ["Wintergreen"]
// Insert at specific position
flavors.insert("Coconut", atIndex: 3)
var countries = ["US" : "United Sates", "PH" : "Philippines", "GB" : "United Kingdom"]
// declare dictionary of Int as String values
var products : [Int:String]
// Accessing dictionary values
println(countries["PH"])
// updating or inserting
countries["CA"] = "Canada" // will change OR insert
countries.updateValue("Singapore", forKey:"SG") // longhand method of above syntax
countries.updateValue("France", forKey:"FR")
//to delete a key/value pair
countries["FR"] = nil
countries.removeValueForKey("FR")
// loop a dictionary
for (key, value) in countries { // a tuple
println("\(key) is short for \(value)")
}
struct
or class
for more formal data structuresvar str = "Lucy"
let num = 666
var myTuple = (str, num)
var myOtherTuple = (str, num, 9876, "Evil One")
// return a tuple from a function
func getNameAndNumber() -> (name: String, number: Int) {
return("Lucy Fer", 666)
}
// call function
let result = getNameAndNumber()
// decomposing - option 1
println("The name is \(result.0) and the number is \(result.1)")
// option 2 (using a label)
println("The name is \(result.name) and the number is \(result.number)")
// option 3, assign to a constant
let (name, number) = getNameAndNumber()
println("The name is \(name) and the number is \(number)")
var temperature : Int? // optional Int, the `?` declares that the variable to be a valid `Int` or `nil`
temperature = 65
if temperature != nil {
// forced unwrapping, use `!`
println("The temperature is \(temperature!) degrees")
}
var countries = ["US" : "United Sates", "PH" : "Philippines", "GB" : "United Kingdom"]
// Optional binding
if let result = countries["XX"] {
println("The country name is \(result)")
} else {
println("No matching key found")
}
var result = countries["XX"] // since XX does not exist
enum
as capitalisedenum SeatPreference {
case Window
case Middle
case Aisle
case NoPreference
// or: case Window, Middle, Aisle, NoPreference
}
var myPref : SeatPreference
myPref = SeatPreference.Aisle // .Aisle for shorthand
var otherPref = .Window
// a simple closure
{
println("This is the simplest closure in the world.")
}
func performSixTimes( myClosureParameter : ()->() ) {
for i in 1...6 {
myClosureParameter()
}
}
performSixTimes { ()->() in
println("This is the simplest closure in the world.")
}
// A function that explicitly takes no parameters and returns nothing
func myFunction ()->() // alternative way of declaring a function that returns nothing
// A closure that explicitly takes no parameters and returns no values
{ ()->() in
println("This is a simple closure.")
}
// Using sorted function
let unsortedArray = [9182,223,1,244,227,34,11,234,44]
let sortedArray = sorted(unsortedArray, { (first : Int, second : Int) -> Bool in
return first < second
})
sortedArray
class AdminUser : User
. :
character is read as is of type
final
before a method name, variable, or class name to prevent override of a subclassclass
keyword at the beginning of property/methodclass User {
// STORED properties
var firstName : String
var lastName : String
var score : Int
// COMPUTED properties, get & set blocks are optional and can be omitted
var fullName : String {
// return the computed propery
return firstName + " " + lastName
}
// methods
func description() -> String {
return("User \(firstName) has the score of \(score)")
}
// default initializer, init is a reserved keyword
init() {
firstName = "John"
lastName = "Doe"
score = 0
}
// custom initializer with parameters
init(first : String, last : String) {
self.firstName = first // use self to refer to current instance of this class' name
self.lastName = last
self.score = 20
}
deinit {
// any necessary cleanup code; automatically called when object reach end of its lifetime
// takes no parameter
// not needed for majority of classes, but useful if you have a class that iopens a connection to a database or file
//
}
}
// instatntiate a new Player object
var firstUser = User()
// use dot syntax
firstUser.firstName = "Player 1"
firstUser.score = 66
println(firstUser.description())
var secondUser = User(first: "Ozzy", last: "Osbourne")
println(secondUser.fullName)
class EliteUser : User {
//additional properties
var userLevel : String
// override required when you subclass a superclass because an init() already exists in the superclass
override init() {
userLevel = "Elite"
super.init() //this is required to also initialize the superclass variables
}
override func description() -> String {
let originalMessage = super.description()
return("\(originalMessage) and is a \(userLevel) user")
}
// additional methods
func calculateBonus() {
self.score += 1000
println("New score is \(self.score)")
}
}
var newPlayer = EliteUser()
newPlayer.description()
newPlayer.calculateBonus()
import UIKit
class Gamer {
// properties
var name : String = "John Doe"
var score = 0
lazy var bonus = getDailyRandomNumber()
// methods
func description() -> String {
return("Player \(name) has a score of \(score)")
}
}
var anotherGamer = Gamer()
println(anotherGamer.bonus)
class Gamer {
// properties
var name : String = "John Doe" {
// these two methods are automatically called when the poroperty name changes
willSet {
// called just before the property changes
//'newValue is an implict parameter
println("About to chnage name to \(newValue)")
}
didSet {
// called right after the property changes
// oldValue is an implicit parameter
println("Have changed name from \(oldValue)")
}
}
var score = 0
lazy var bonus = getDailyRandomNumber()
// methods
func description() -> String {
return("Player \(name) has a score of \(score)")
}
}
var anotherGamer = Gamer()
anotherGamer.name = "Kerry King"
private
- only accessible within the same source code fileinternal
- This is the default, and means the class, method, or property is accessible across mutiple code files but must be compiled together into the same module.public
- accessible from any module that has imported your codeString
, Int
, Bool
, and Float
.//Pass by value
//function that changes an Int
func changeValue(var number : Int) -> Int {
number += 1000
return number
}
var myNumber = 666
//define an Int variable (value type)
changeValue(myNumber)
//original var is unchanged = 666
myNumber
// Pass by reference
class SimpleClass { //change class to struct will keep original value of 'value'
var value : Int = 99
}
// Simple function that chnages an object
func changeObject(var object : SimpleClass) -> Int {
object.value += 1000
return object.value
}
// create a new instance (reference type)
var myObject = SimpleClass()
// pass the object into the function - Pass By Reference
changeObject(myObject)
// the original object has been changed.
myObject.value
&+ &- &* &/ &%
// Note: this will not work on structures, only on objects
=== // identical to
!== // not identical to
var dateA = NSDateComponents()
dateA.year = 2015
dateA.month = 01
dateA.day = 01
var dateB = NSDateComponents()
dateB.year = 2015
dateB.month = 01
dateB.day = 01
// check equality: ==
if dateA == dateB {
println("Yes dateA and dateB are equal to each other")
}
// check Identity
if dateA === dateB {
println("Yes dateA and dateB are equal to each other")
} else {
println("They might be equal, but not identical")
}
??
var website = personalSite ?? defaultSite
* Remainder operator - `%`
- can also work with negative numbers and floats, unlike in other languages where only positive integers are allowed
## Advanced Language Features
### Type Casting & Casting
* There are times when the data types you use needs to be treated as a different data type.
* Use `?` and `!` to check and unwrap properties of a variable typecasted to a different object type
```swift
let myButton = UIButton()
let mySlider = UISlider()
let myTextField = UITextField()
let myDatePicker = UIDatePicker()
let controls = [myButton, mySlider, myTextField, myDatePicker]
for item in controls {
//option 1: check type with "is"
// if item is UIDatePicker {
// println("We have a UIDatePicker")
// // downcast with "as"
// let picker = item as UIDatePicker
// picker.datePickerMode = UIDatePickerMode.CountDownTimer
// }
// option 2: try to downcast with as?
// let picker = item as? UIDatePicker
// //then check if works, and unwrap the original
// if picker != nil {
// // use ! to force unwrap it to get to its properties
// picker!.datePickerMode = UIDatePickerMode.CountDownTimer
// }
// option 3 - most succint way, combination of option 1 & 2
if let picker = item as? UIDatePicker {
picker.datePickerMode = UIDatePickerMode.CountDownTimer
}
}
AnyObject
and Any
when dealing with non-specific dataNSArray
can hold any type of object at any position. In Swift, when you use existing frameworks, what you get returned is an array of any objects.id
maps to Swift AnyObject
is
, as
, as?
to check and downcast types into something more specificUIKit
, Swift String
, which are structures and not objects, is bridged to Objective-C’s NSString
ObjectAnyObject
var someObject : AnyObject // needs to be an object
var something : Any // means any object or any data type
var arrayOfObjects : [AnyObject] // array of any type of objects
var arrayOfAnything : [Any] // array of any type of objects or non-object types including tuples, closures
import UIKit
someObject = "This is a simple message"
someObject = 666
if someObject is String {
let wordsArray = someObject.componentsSeparatedByString(" ")
}
var
:
in the class declarationprotocol ExampleProtocol {
//method signatures
func simpleMethod() -> Bool
var simpleProperty : Int { get }
}
class MyClass : ExampleProtocol {
// provide anything else you need this class to do
func simpleMethod() -> Bool {
// do some work
return true
}
var simpleProperty : Int {
return 666
}
}
extension String {
func reverseWords() -> String {
let wordsArray = self.componentsSeparatedByString(" ")
let reversedArray = wordsArray.reverse()
var newString = ""
for eachWord in reversedArray {
newString += eachWord + " "
}
return newString
}
}
var message = "I want to reverse all the words in this string"
message.reverseWords()
import UIKit
class SimpleClass {
var singleProperty : String = "A string"
}
let myNumbers = [666, 113, 34, 45, 12, 456, 234]
let myStrings = ["death", "hell", "grave"]
let myObjects = [SimpleClass(), SimpleClass(), SimpleClass(), SimpleClass()]
func displayArray<T>(theArray : [T]) -> T{
println("Printing the array:")
for eachItem in theArray {
print(eachItem)
print(" : ")
}
println()
let finalElement : T = theArray[theArray.count-1]
return finalElement
}
var finalInt = displayArray(myNumbers)
++finalInt
var finalString = displayArray(myStrings)
finalString.uppercaseString
displayArray(myStrings)
displayArray(myNumbers)