SoFunction
Updated on 2025-04-11

Swift programming language introduction tutorial

Original address:/blog/2075324

Table of contents

1   Introduction
2  Getting started with Swift
3   Simple value
4   Control flow
5   Functions and closures
6 Objects and Classes
7   Enumeration and Structure

1   Introduction

Apple just released the Swift programming language early this morning. This article was excerpted and extracted from its published book "The Swift Programming Language". I hope it will be helpful to your iOS&OSX development.

Swift is a new programming language for iOS and OS X applications. It is based on C and Objective-C, but does not have some compatibility constraints of C. Swift adopts a secure programming mode and adds modern features to make programming easier, more flexible and fun. The interface is based on the Cocoa and Cocoa Touch frameworks that are widely loved by the people, showing a new direction of software development.

Swift has been around for many years. Apple is based on existing compilers, debuggers, and frameworks as its infrastructure. Simplify memory management through ARC (Automatic Reference Counting). Our framework stack has always been based on Cocoa. Objective-C evolution supports blocks, collection literals, and modules, allowing frameworks in modern languages ​​to be used without deeper. (by gashero) Thanks to these basic work, which enables the introduction of new programming languages ​​in Apple's software development.

Objective-C developers will feel that Swift is familiar. Swift adopts the named parameters and dynamic object model of Objective-C. Provides interoperability to the Cocoa framework and mix-and-match. Based on these foundations, Swift introduces many new features and combines process-oriented and object-oriented capabilities.

Swift is also friendly to new programmers. It is an industrial-grade system programming language, but it is as friendly as a scripting language. It supports playground, allowing programmers to experiment with a piece of Swift code functionality and see the results immediately without having to worry about building and running an application.

Swift integrates modern programming language ideas and the wisdom of Apple's engineering culture. The compiler is optimized for performance, while the language is optimized for development without compromise on each other. (by gashero) can start learning from "Hello, world" and transition to the entire system. All of this makes Swift a source of innovation for Apple software developers.

Swift is a fantasy way to write iOS and OSX applications, and will continue to advance the introduction of new features. We can't wait to see what you use him to do.

2  Getting started with Swift

Learning a new language should start with printing "Hello, world". In Swift, it's a line:

println("Hello, world")

If you have written C or Objective-C code, this syntax looks familiar, and in Swift, this is the complete program. You do not need to import a separate library for input and output and string processing. Globally-wide code is used for the entry of the program, so you don't need to write a main() function. You don't need to write a semicolon after each statement either.

This introduction will give you enough information to teach you how to complete a programming task. There is no need to worry that you don’t understand something yet. Everything that has not been explained clearly will be explained in detail in the subsequent book.

Note

As a best practice, this chapter can be opened in Xcode's playground. Playground allows you to edit the code and see the results immediately.

3   Simple value

Use let to define constants, var to define variables. The value of a constant does not need to be specified at compile time, but must be assigned at least once. This means you can use constants to name a value, which you find only needs to be determined at once, but is used in multiple places.

var myVariable = 42
myVariable = 50
let myConstant = 42

Note

Gashero notes

The constant definition here is similar to variables in functional programming languages ​​and cannot be modified after one assignment. It is good for health if you use it more.

A constant or variable must have the same type as when assigned. Therefore you don't have to strictly define the type. Provide a value to create a constant or variable and let the compiler infer its type. In the example above, compiling it will infer that myVariable is an integer type because its initialization value is an integer.

Note

Gashero notes

Types are bound to variable names and belong to statically typed languages. Helps with static optimization. It is different from Python, JavaScript, etc.

If the initialization value does not provide enough information (or does not have an initialization value), you can write the type after the variable name, separated by a colon.

Copy the codeThe code is as follows:

let imlicitInteger = 70
let imlicitDouble = 70.0
let explicitDouble: Double = 70

Note

practise

Create a constant with type Float and value 4.

Values ​​are never implicitly converted to other types. If you need to convert a value to a different type, explicitly construct an instance of the desired type.

Copy the codeThe code is as follows:

let label = "The width is "
let width = 94
let widthLabel = label + String(width)

Note

practise

Try to delete the String conversion of the last line, what error do you get?

There are also easier ways to include values ​​in strings: write values ​​in brackets and place them in front of brackets with backslashes (""). For example:

Copy the codeThe code is as follows:

let apples = 3
let oranges = 5     //by gashero
let appleSummary = "I have \(apples) apples."
let fruitSummary = "I have \(apples + oranges) pieces of fruit."

Note

practise

Use () to include a floating point number to the string and to include someone's name to greet.

Create an array and dictionary using square brackets "[]" and accessing its elements is through the index or key in square brackets.

Copy the codeThe code is as follows:

var shoppingList = ["catfish", "water", "tulips", "blue paint"]
shoppingList[1] = "bottle of water"
 
var occupations = [
   "Malcolm": "Captain",
   "Kaylee": "Mechanic",
]
occupations["Jayne"] = "Public Relations"

To create an empty array or dictionary, use the initialization syntax:

let emptyArray = String[]()
let emptyDictionary = Dictionary<String, Float>()

If the type information cannot be inferred, you can write an empty array as "[]" and an empty dictionary as "[:]", for example, you set a know variable and pass the arguments to the function:

shoppingList = []   //Go shopping and buy something by gashero

4   Control flow
Use if and switch as conditional control. Use for-in , for , while , do-while as loop. Braces are not required, but braces for the body are required.

Copy the codeThe code is as follows:

let individualScores = [75, 43, 103, 87, 12]
var teamScore = 0
for score in individualScores {
    if score > 50 {
        teamScores += 3
    } else {
        teamScores += 1
    }
}
teamScore

In an if statement, the condition must be a boolean expression, which means that if score { ... } is wrong and cannot be compared implicitly with 0.

You can use if and let together to prevent the loss of values. These values ​​are optional. Optional values ​​can contain a value or include a nil to specify that the value does not exist yet. Write a question mark "?" after type indicating that the value is optional.

Copy the codeThe code is as follows:

var optionalString: String? = "Hello"
optionalString == nil
 
var optionalName: String? = "John Appleseed"
var greeting = "Hello!"
if let name = optionalName {
    greeting = "Hello, \(name)"
}

Note

practise

Change optionalName to nil . What happens when greetings? Add an else clause to set a different value when optionalName is nil.

If the optional value is nil , the condition is that the code in the braces will be skipped. Otherwise, the optional value is not wrapped and assigned to a constant, which will be a variable with an unwrapped value into the code block.

switch supports multiple data and multiple comparisons, without limiting that integers and tests must be equal.

Copy the codeThe code is as follows:

let vegetable = "red pepper"
switch vegetable {
case "celery":
    let vegetableComment = "Add some raisins and make ants on a log."
case "cucumber", "watercress":
    let vegetableComment = "That would make a good tea sandwich."
case let x where ("pepper"):
    let vegetableComment = "Is it a spicy \(x)?"
default:    //by gashero
    let vegetableComment = "Everything tastes good in soup."
}

Note

practise

Try to remove default and see what error is getting.

After executing a matching situation, the program will jump out of the switch instead of continuing to execute the next situation. So no longer need to break to jump out of switch.

You can use for-in to iterate over each element in the dictionary, providing a pair of names to use each key-value pair.

Copy the codeThe code is as follows:

let interestingNumbers = [
    "Prime": [2, 3, 5, 7, 11, 13],
    "Fibonacci": [1, 1, 2, 3, 5, 8],
    "Square": [1, 4, 9, 16, 25],
]
var largest = 0
for (kind, numbers) in interestingNumbers {
    for number in numbers {
        if number > largest {
            largest = number
        }
    }
}

Note

practise

Add another variable to track which category has the largest number, which is where the largest number is.

Use while to repeat the code block until the conditions change. The conditions of the loop can be placed at the end to ensure that the loop is executed at least once.

Copy the codeThe code is as follows:

var n = 2
while n < 100 {
    n = n * 2
}
n
 
var m = 2
do {
    m = m * 2
} while m < 100
m

You can keep an index in a loop, representing the index range through ".." or explicitly declare an initial value, condition, increment. These two loops do the same thing:

Copy the codeThe code is as follows:

var firstForLoop = 0
for i in 0..3 {
    firstForLoop += i
}
firstForLoop
 
var secondForLoop = 0
for var i = 0; i < 3; ++i {
    secondForLoop += 1
}
secondForLoop

The highest value is ignored by constructing the range with ..., while the range constructed with ... contains two values.

5   Functions and closures
Use func to declare a function. Calling the function uses its name plus the parameter list in brackets. Use -> to separate the name of the parameter and the return value type.

Copy the codeThe code is as follows:

func greet(name: String, day: String) -> String {
    return "Hello \(name), today is \(day)."
}
greet("Bob", "Tuesday")

Note

practise

Remove the day parameter and add a parameter to include today's lunch selection.

Use tuples to return multiple values.

Copy the codeThe code is as follows:

func getGasPrices() -> (Double, Double, Double) {
    return (3.59, 3.69, 3.79)
}
getGasPrices()

Functions can accept variable parameters and collect them into an array.

Copy the codeThe code is as follows:

func sumOf(numbers: Int...) -> Int {
    var sum = 0
    for number in numbers {
        sum += number
    }
    return sum
}
sumOf()
sumOf(42, 597, 12)

Note

practise

Write a function to calculate the average value of its parameters.

Functions can be nested. An embedded function can access the variables that define the function it is located in. You can use inline functions to organize your code to avoid being too long and too complicated.

Copy the codeThe code is as follows:

func returnFifteen() -> Int {
    var y = 10
    func add() {
        y += 5
    }
    add()
    return y
}   //by gashero
returnFifteen()

Functions are of the first type. This means that the function can return another function.

Copy the codeThe code is as follows:

func makeIncrementer() -> (Int -> Int) {
    func addOne(number: Int) -> Int {
        return 1 + number
    }
    return addOne
}
var increment = makeIncrementer()
increment(7)

One function can accept other functions as parameters.

Copy the codeThe code is as follows:

func hasAnyMatches(list: Int[], condition: Int -> Bool) -> Bool {
    for item in list {
        if condition(item) {
            return true
        }
    }
    return false
}
 
func lessThanTen(number: Int) -> Bool {
    return number < 10
}
var numbers = [20, 19, 7, 12]
hasAnyMatches(numbers, lessThanTen)

Functions are actually special cases of closures. You can write a closure without the name, just put it in braces. Use in to the return value of a specific parameter and body.

Copy the codeThe code is as follows:

({
    (number: Int) -> Int in
    let result = 3 * number
    return result
    })

Note

practise

Rewrite a closure to return 0 for all odd numbers.

There are several options when writing closures. When the type of a closure is known, for example, represents a callback, you can ignore its parameters and return values, or both. A closure of a single statement can directly return a value.

({number in 3 * number})

You can refer to a parameter by number instead of name, which is useful for very short closures. A closure passes its last argument to the function as the return value.

sort([1, 5, 3, 12, 2]) { $0 > $1 }

6 Objects and Classes
Use class to create a class. A property declaration is declared as a constant or variable in the class, except in the context of the class. The same is true for methods and functions.

Copy the codeThe code is as follows:

class Shape {
    var numberOfSides = 0
    func simpleDescription() -> String {
        return "A shape with \(numberOfSides) sides."
    }
}

Note

practise

Adding a constant attribute through "let" and adding another method can accept parameters.

Create an instance of the class by adding brackets after the class name. Use dot syntax to access the properties and methods of an instance.

Copy the codeThe code is as follows:

var shape = Shape()
= 7
var shapeDescription = ()

Something important is not the case with this version of the Shape class: a constructor to set the class when creating an instance. Use init to create one.

Copy the codeThe code is as follows:

class NamedShape {
    var numberOfSides: Int = 0
    var name: String
 
    init(name: String) {
        = name
    }   //by gashero
 
    func simpleDescription() -> String {
        return "A Shape with \(numberOfSides) sides."
    }
}

Note that self is used to distinguish name attribute from name parameters. The life of a constructor is the same as a function, except that it creates instances of the class. Each attribute needs to be assigned, both in the declaration and in the constructor.

Use deinit to create a destructor to perform cleanup work during object destruction.

Subclasses include the names of their superclasses, separated by colons. There is no need to declare when inheriting the standard root class, so you can ignore the superclass.

Subclass methods can be overloaded by tagging override implementations in superclasses, while those without override will be regarded as errors by the compiler. The compiler will also check for methods that are not overloaded.

Copy the codeThe code is as follows:

class Square: NamedShape {
    var sideLength: Double
 
    init(sideLength: Double, name: String) {
        = sideLength
        (name: name)
        numberOfSides = 4
    }
 
    func area() -> Double {
        return sideLength * sideLength
    }
 
    override func simpleDescription() -> String {
        return "A square with sides of length \(sideLength)."
    }
}
 
let test = Square(sideLength: 5.2, name: "my test square")
()
()

Note

practise

Write another subclass of NamedShape called Circle , which accepts radius and name to its constructor. Implement area and describe methods.

Attributes can have getter and setter.

Copy the codeThe code is as follows:

class EquilateralTriangle: NamedShape {
    var sideLength: Double = 0.0
 
    init(sideLength: Double, name: String) {
        = sideLength
        (name: name)
        numberOfSides = 3
    }
 
    var perimeter: Double {
    get {
        return 3.0 * sideLength
    }
    set {
        sideLength = newValue / 3.0
    }
    }
 
    override func simpleDescription() -> String {
        return "An equilateral triangle with sides of length \(sideLength)."
    }
}
 
var triangle = EquilateralTriangle(sideLength: 3.1, name: "a triangle")

= 9.9

In the perimeter setter, the name of the new value is newValue . You can provide a name that does not conflict after set.

Note that the EquilateralTriangle constructor has 3 different steps:

Set the value of the attribute
Calling the superclass constructor
Change the value of the attribute defined by the superclass, add additional work to use methods, getters, and setters.
If you don't need to compute properties, but still want to provide the work to be performed after setting the value, use willSet and didSet . For example, the following class must ensure that the side length of the triangle is equal to the change length of the rectangle.

Copy the codeThe code is as follows:

class TriangleAndSquare {
    var triangle: EquilaterTriangle {
    willSet {
        =
    }
    }
 
    var square: Square {
    willSet {
        =
    }
    }
 
    init(size: Double, name: String) {
        square = Square(sideLength: size, name: name)
        triangle = EquilaterTriangle(sideLength: size, name: name)
    }
}
var triangleAndSquare = TriangleAndSquare(size: 10, name: "another test shape")


= Square(sideLength: 50, name: "larger square")

There is an important difference between class methods and functions. The parameter name of a function is only used with the function, but the parameter name of the method can also be used to call the method (except the first parameter). By default, a method has a parameter with the same name, and the parameter itself is called. You can specify a second name to use inside the method.

Copy the codeThe code is as follows:

class Counter {
    var count: Int = 0
    func incrementBy(amount: Int, numberOfTimes times: Int) {
        count += amount * times
    }
}
var counter = Counter()
(2, numberOfTimes: 7)

When working with optional values, you can write "?" before the operator similar to the method attribute. If the value is nil before "?", everything after "?" will be automatically ignored, and the entire expression is nil. Additionally, optional values ​​are unwrapped, and all "?" after which are "?" are used as unwrapped values. In both cases, the value of the entire expression is an optional value.

let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square")
let sideLength = optionalSquare?.sideLength

7   Enumeration and Structure
Use enum to create an enum. For example, classes and other named types, enums can have methods.

Copy the codeThe code is as follows:

enum Rank: Int {
    case Ace = 1
    case Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten
    case Jack, Queen, King
    func simpleDescrition() -> String {
        switch self {
        case .Ace:
            return "ace"
        case .Jack:
            return "jack"
        case .Queen:
            return "queen"
        case .King:
            return "king"
        default:
            return String(())
        }
    }
}
let ace =   //by gashero
let aceRawValue = ()

Note

practise

Write a function to compare the values ​​of two Ranks by comparing their original values.

In the example above, the original value is of type Int so you can specify only the first original value. The original values ​​afterwards are all assigned in order. You can also use strings or floating-point numbers as the original values ​​of the enum.

Use the toRaw and fromRaw functions to convert raw and enum values.

Copy the codeThe code is as follows:

if let convertedRank = (3) {
    let threeDescription = ()
}

The member value of an enum is the actual value, not the original value written in other ways. In fact, some cases are the original value, which is when you don't provide it.

Copy the codeThe code is as follows:

enum Suit {
    case Spades, Hearts, Diamonds, Clubs
    func simpleDescription() -> String {
        switch self {
        case .Spades:
            return "spades"
        case .Hearts:
            return "hearts"
        case .Diamonds:
            return "dismonds"
        case .Clubs:
            return "clubs"
        }
    }
}
let hearts =     //by gashero
let heartsDescription = ()

Note

practise

Add a color method to Suit and return "black" when spades and clubs, and return "red" to hearts and diagrams.

Note the two methods above that refer to Hearts members: when assigning to the hearts constant, the enumerated members are referenced by the full name because the constant has no explicit type. In switch, enumerations are referenced via .Hearts because the value of self is known. You can use the convenient method at any time.

Use struct to create a structure. Structures support multiple identical behaviors to classes, including methods and constructors. One important difference is that passing between codes is always copy (value pass), while class passes references.

Copy the codeThe code is as follows:

struct Card {
    var rank: Rank
    var suit: Suit
    func simpleDescription() -> String {
        return "The \(()) of \
        (())"
    }
}
let threeOfSpades = Card(rank: .Three, suit: .Spades)
let threeOfSpadesDescription = ()

Note

practise

Add methods to the Card class to create a table of cards, each with a merged rank and suit. (It's just a typist's job, by gashero).

An enumerated instance member can have the value of an instance. The same enum member instance can have different values. You assign values ​​when creating an instance. The difference between a specified value and a primitive value: The original value of an enum is the same as its example, and you provide the original value when defining an enum.

For example, suppose the situation needs to obtain the sun rise and landing time from the server. The server can respond to the same information or some error message.

Copy the codeThe code is as follows:

enum ServerResponse {
    case Result(String, String)
    case Error(String)
}
 
let success = ("6:00 am", "8:09 pm")
let failure = ("Out of cheese.")
 
switch success {
case let .Result(sunrise, sunset):
    let serverResponse = "Sunrise is at \(sunrise) and sunset is at \(sunset)."
case let .Error(error):
    let serverResponse = "Failure... \(error)"
}

Note

practise

Add a third case to ServerResponse to choose.

Note that sunrise and sunset times are actually selected from partial matches to ServerResponse.