Saturday, March 28, 2015

Optionals

Declaring

// Use question mark to say this variable can be nil.
var myLastName: String?
myLastName = nil

// Check if nil (null)
if (myLastName == nil) {
    myLastName = "Moeykens"
}

// Using the Nil Coalescing Operator to get a value
let lastName = myLastName ?? "No last name found"
// Note: If myLastName is nil then "No last name found" is used.

Getting Value from Optional

Check for value using Optional Binding (if let)
if let lastName = myLastName {
    // It's guaranteed to have a value.
    print("Last name was found:\(lastName)") 
}
else {
    print("No last name found.")
}

Unwrapping

"Unwrap" or "Unwrapping" refers to getting a non-nil value of the optional. There are a few different ways to do this without having to write an if statement every time to check if a value exists.

// Force Unwrap with exclamation point
print(myLastName!) // This will generate an ERROR if myLastName is nil

// A different way might be to use a ternary conditional operator to avoid the error
let lastName = myLastName == nil ? "none" : myLastName
print(lastName)

// An even easier way is to use the Nil Coalescing Operator (??)
let lastName = myLastName ?? "none"
print(lastName)
// The Nil Coalescing Operator automatically unwraps the optional if there is a value

print(myLastName) // This will NOT generate an error if myLastName is nil
// Will just print: "nil"
(Updated for Swift 2.2)

Tuples

Declaring

// Combine any values/types together into one variable/constant
let myNameTuple = ("Mark", "Moeykens", 44)

// Values in a tuple are called "elements" or "element values"

Access elements

// By Index
print("My first name is \(myNameTuple.0)")

// By naming the elements
let (myFirstName, myLastName, myAge) = myNameTuple
print("My first name is \(myFirstName)")

// Ignore elements with underscore (_)
let (justFirstName, _, _) = myNameTuple
print("My first name is \(justFirstName)")

// You can name the elements in a tuple too
let personTuple = (firstName: "Mark", lastName: "Moeykens", age: 44)

// Accessing elements in a tuple
var firstName = personTuple.firstName
(Updated for Swift 2.2)

Tuesday, March 24, 2015

Collections

Array

Declaring

// Explicitly
var myArrayOfNames: [String]
// Or Explicitly initialized
var myArrayOfNames: [String] = [String]()
// Or Explicitly initialized with values
var myArrayOfNames: [String] = ["Mark", "Bob", "Matt"]

// Implicitly
var myArrayOfNames = [String]()
// Or Implicitly initialized with values
var myArrayOfNames = ["Mark", "Bob", "Matt"]
// Or with values (3 values with "No name yet")
var myArrayOfNames = [String] (count: 3, repeatedValue: "No name yet")

Modifying

// Add 3 names
myArrayOfNames = ["Mark", "Bob", "Matt"]
// Add one more to the end of the array
myArrayOfNames.append("Jeff")
// Add two more to the end of the array
myArrayOfNames += ["Julie", "Patty"]
// Add a name so it's the 2nd in the array
myArrayOfNames.insert("Patrick", atIndex: 1)
// Change the 4th name
myArrayOfNames[3] = "Courtney"
// Remove the 5th name
myArrayOfNames.removeAtIndex(4)

print("I have \(myArrayOfNames.count) items in my array")
print("The 2nd name is \(myArrayOfNames[1]).")

Iterating

for name in myArrayOfNames {
    print(name)
}

// Just a range of indexes
for name in myArrayOfNames[0...2] {
    print(name)
}

// Get the index position and the value
for (index, name) in myArrayOfNames.enumerate() {
    print("\(name) is at position \(index)")
}

Dictionary

Declaring

// Say I want to hold Name and Age of a person.
// Explicitly
var peopleDictionary: [String:Int]
// Explicitly initialize an empty dictionary
var peopleDictionary: [String:Int] = [String:Int]()
// Implicitly
var peopleDictionary = [String:Int]()
// Implicitly with values
var peopleDictionary = ["Mark":44, "Bob":51, "Matt":45]

Modifying

// Add 3 people
peopleDictionary = ["Mark":44, "Bob":51, "Matt":45]
// Add one more
peopleDictionary["Jeff"] = 44
// Change Courtney's age
peopleDictionary["Courtney"] = 30
// Change Courtney's age and get the previous age
if let oldValue = peopleDictionary.updateValue(32, forKey: "Courtney") {
    print("The old value for Courtney was \(oldValue).")
}
// Remove Jeff
peopleDictionary["Jeff"] = nil

print("I have \(peopleDictionary.count) items in my dictionary")
print("The age of Mark is \(peopleDictionary["Mark"]!).")

Set

Note: Not going to cover too much because I will probably use this less than arrays and dictionaries.
How they are different:
  • Stores unique values (can not store duplicate values)
  • Not ordered (You insert an item, no guarantee where it will end up in the collection.)

Declaring

// Explicitly
var mySetOfNames: Set<String>
// Or Explicitly initialized
var mySetOfNames: Set<String> = Set<String>()
// Or Explicitly initialized with values
var mySetOfNames: Set<String> = ["Mark", "Bob", "Matt"]

// Implicitly
var mySetOfNames = Set<String>()
// Or Implicitly initialized with values (Still need to say it is a Set)
var mySetOfNames: Set = ["Mark", "Bob", "Matt"]

Modifying

// Add a name
mySetOfNames.insert("Patrick")
// Remove a name
mySetOfNames.remove("Mark")

print("I have \(mySetOfNames.count) items in my set")

for name in mySetOfNames {
    print(name)
}
(Updated for Swift 2.2)

Sunday, March 1, 2015

Classes

Declaring

class PersonBaseClass {
    var firstName: String = ""
    var lastName: String = ""
    
    func getFullName () -> String {
        return "\(firstName) \(lastName)";
    }
}

Subclassing

Terminology in Swift

  • Subclassing = Inheriting "I need to subclass ObjectClass." (You need to inherit ObjectClass.)
  • Subclass = Derived Class, Child Class
  • Superclass = Base Class, Parent Class
In this example we are "subclassing" the PersonBaseClass:
class Mother : PersonBaseClass {
    
    var maidenName: String = ""
    
    func setIdentity (firstName: String, lastName: String) {
        // Find members of the superclass by using the word "super".
        super.firstName = firstName
        super.lastName = lastName
        
        // Find members in this class by using the word "self".
        self.maidenName = lastName
    }
    
    override func getFullName() -> String {
        return super.getFullName() + " (\(maidenName))"
    }
}

Instantiating and Using

var me = PersonBaseClass()
me.firstName = "Mark"
me.lastName = "Moeykens"
me.getFullName()

var mom = Mother()
mom.firstName = "Beth"
mom.lastName = "Moeykens"
mom.maidenName = "Marr"
mom.getFullName()

Monday, January 19, 2015

Functions

Declaration

func DoSomeWork(param1: String, param2: Int)
{
    println("I saw \(param1) \(param2) times.")
}
// How to call
DoSomeWork("Sally", 3)

// Default Parameters
func DoSomeWork(param1: String, param2: Int = 2)
{
    println("I saw \(param1) \(param2) times.")
}
// How to call
DoSomeWork("Sally")
// or
DoSomeWork("Sally", param2: 5)

// Note: With default parameters you HAVE to use the 
// parameter name.

//Multiple Default Parameters
func DoSomeWork(name: String, howMany: Int=1, didSee: Bool=false)
{
    if didSee {
        println("I saw \(name) \(howMany) times.")
    }
    else {
        println("I did not see \(name) at all.")
    }
}

// How to call
DoSomeWork("Sally")
// or
DoSomeWork("Sally", didSee: true)
// or
DoSomeWork("Mark", didSee: true, howMany: 3)

// Notice how I can reorder the default parameters.

External Parameter Names

// Add extra argument info (called "argument labels")
// to help developers better understand what is happening
func DoSomeWork(forThisPerson param1: String, thisManyTimes param2: Int)
{
    println("I worked for \(param1) \(param2) times.")
}
How to call
DoSomeWork(forThisPerson: "Sally", thisManyTimes: 3)

// Note: If you do not include the argument labels 
// (external parameter names) you will get this issue:
// "Missing argument label 'thisManyTimes:' in call"

// One Parameter Name
// If you just want one parameter name but you still want 
// to force developers to type it out when calling then 
// you can use the pound (#) symbol in front of the parameter name.
func DoSomeWork(#forThisPerson: String, #thisManyTimes: Int)
{
    println("I worked for \(forThisPerson) \(thisManyTimes) times.")
}
How to call

DoSomeWork(forThisPerson: "Sally", thisManyTimes: 3)
Return a variable
func ReturnVariable() -> Bool
{
    return true
}

Control Flow

If

if myFirstName == "Mark"{
    print("Hello, \(myFirstName). You are an admin.")
}
else {
    print("Welcome, guest!")
}

Ternary Conditional Operator

 
let isAdmin: Bool = myFirstName == "Mark" ? true : false
 

Switch

switch myFirstName {
    case "Mark":
    print("Hello, \(myFirstName). You are an admin.")
case "Mark", "Chase":
    print("Hello, \(myFirstName). You are a user.")
default:
    print("Welcome, guest!")
}

// Note: No "break" statement is necessary.

For In

let iterations = 5

for index in 1...iterations {
    print("This is iteration \(index)")
}

// Note: The for loop is kind of deprecated, replaced by the for in loop.
for var x = 0; x < iterations; ++x {
    print("This is iteration \(x)")
}
For more examples of for in loops see post on Collections

While

var x = 0

while x < 5 {
    print("This is iteration \(x)")
    x++
}

repeat {
    print("This is iteration \(x)")
    x++
} while x < 5
(Updated for Swift 2.2)

Member Declarations

Variable Members

var myFirstName = "Mark" // Implicit - Will make variable a string
var myLastName: String = "Moeykens" // Explicit
var accountBalance: Float = 5012.123456
var measure: Double = 1.123456789012345
var isBlogging = true // Implicitly converts "isBlogging" to boolean

Constant Members 

 
let thing = "tree"
thing = "stone" // This is invalid
 

SwiftUI Search & Filter with Combine - Part 3 (iOS, Xcode 13, SwiftUI, 2...

In part 3 of the Searchable video series, I show you how to use Combine in #SwiftUI for the search and filter logic connected to the searcha...