SoFunction
Updated on 2025-04-11

Swift Learning Documents (Notes)

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.

Variables and constants

Variable definition uses var, constants use let, type-safe, automatic type derivation, note that there must be spaces on both sides of the = sign assigned. Variables and constant names are available for almost all characters, and these are very similar to javascript. Chinese programming is awesome.

var a = 123 //a is Intlet b = "helo" //b is Stringvar Cats croak = "Meow"

number

  • Decimal
  • Binary 0b101
  • Octal 0o5
  • Hexadecimal 0x5

A relatively long number can be added to improve the readability of the program. For example, 0_0 is actually 0, and the line cannot be added to the beginning.

Boolean type

true and false. When the process controls if, the judgment statement must return a Bool value, such as:

let i = 1
if i {
 //Compilation error}

This way it can pass

if i == 1 {
}

It doesn't have automatic type conversion like js

Type alias

Adding an alias to the current type can also improve the readability of the program, such as

typealias Audio sampling = UInt16

Can be used elsewhere var discovered maximum amplitude = audio sampling.min

Tuples

It can be a set of values ​​that do not have to be of the same type, for example, define myself:

var jserme = ("183cm", 26, "76kg")

Can be accessed like an array

println(jserme.0) //Return 183cm

Restore tuples to independent variables or constants

let jserme = ("183cm",26,"76kg")
let (height, age, weight) = jserme
println("height是 \(height)")

You can also name each value (it's like turning an array into an object in JS...)

let jserme = (height:"183cm",age:26,weight:"76kg")
println("height是 \(jserme.height)")

String

String literals can only be defined by "", and String is essentially an ordered collection of Characters.

for char in "A word is released"{
 println(char)
}
 
/*
 one
 Word
 now that
 out
 */

Literal and judgment whether it is empty

var String = "I'm a string"
var 空String = ""
 
if 空String.isEmpty {
 println("This is an empty string")
}
 
if 空String == "" {
 println("This is an empty string")
}

There are two methods for string instances that havePrefix and haveSuffix, such as:

var Idiom array = [
 "A word is released",
 "It's about to break out",
 "One call and a hundred responses",
 "One hammer to make a sound",
 "Nothing",
 "A lifetime",
 "love at first sight"
]
 
var count = 0
for idiom in Idiom array {
 if(idiom.hasPrefix("one")){
  count++
 }
}
 
println(count) //Output 7

Like js, string is also a reference to pass a value. The modification of the following two variables will not affect each other.

var A string = "I'm String One"
var Two strings = A string
 
Two strings = "I'm String Two"
 
println("String one:\(A string), String two:\(Two strings)")

Interval operator

Closed intervals use a...b, from a to b, including a and b, half intervals a..b, from a to b, without b, for example:

var Idiom array = [
 "A word is released",
 "It's about to break out",
 "One call and a hundred responses"
]
 
for i in 0..Idiom array.count {
 println("The\(i)Idioms are:\(Idiom array[i])")
}
//How to use it here... will report an error because the idiom array [3] has no value

Two sets, array and dictionaries

Compared with JS's loose requirements for arrays and object members, Swift requires that the member types in arrays and dictionaries must be consistent.

var Shopping list: String[] = ["egg", "milk"]
//It can also be the following//var Shopping List = ["Egg", "Milk"]

The array can be modified using the append method or +=

var Shopping list = ["egg", "milk"]
 
Shopping list.append("apple")
 
Shopping list += "strawberry"
 
println("\(Shopping list)") //[Egg, Milk, Apple, Strawberry]

The acquisition of arrays can be obtained through indexes or interval operators.

var Shopping list = ["egg", "milk"]
 
println("\(Shopping list[0])") //eggprintln("\(Shopping list[0..1])") //[egg]println("\(Shopping list[0...1])") //[Eggs, Milk]println("\(Shopping list[0...2])") //[Egg, Milk,]

Definition of dictionaries

var airports: Dictionary<String, String> = ["TYO": "Tokyo", "DUB": "Dublin"]
 
//It can also be simplified to//var airports = ["TYO": "Tokyo", "DUB": "Dublin"]

Its modification and reading use [], but cannot be used.

airports["BJ"] = "Beijin"

Control statements

As shown in the previous examples, the conditions of the control statement do not have brackets like js

for var index = 0; index < 3; index++ {
 println("index is \(index)")
}
//index is 0
//index is 1
//index is 2

function

Function declaration and call:

func sayHello(personName: String) -> String {
 let greeting = "Hello, " + personName + "!"
 return greeting
}
 
println(sayHello("jserme"))

The function without return is essentially a Void, which is equivalent to an empty tuple()

Functions with multiple return values ​​and default parameters:

func info(word:String = "aha") -&gt; (length:Int, containA:Bool){
 var containA = false
 for char in word {
  if( char == "a") {
   containA = true
   break
  }
 }
 
 return (word.utf16count, containA)
}
 
println(info(word: "Bobo")) //(2, false)
println(info()) //(3, true)

The external parameter name that is easy to read is separated from the parameter definition by spaces before the parameter definition, such as the following multiple parameters

func join(string s1: String, toString s2: String, withJoiner joiner: String)
 -&gt; String {
 return s1 + joiner + s2
}
 
//When callingjoin(string: "hello", toString: "world", withJoiner: ", ")
// returns "hello, world"

The parameter name is the same as the external parameter name. You can add a # mark to the parameter name:

func containsCharacter(#string: String, #characterToFind: Character) -> Bool {
 for character in string {
  if character == characterToFind {
   return true
  }
 }
 return false
}
let containsAVee = containsCharacter(string: "aardvark", characterToFind: "v")
// containsAVee equals true, because "aardvark" contains a "v"

The parameters of the function are constants and cannot be modified. If modified within the function, add var before the variable definition.

func alignRight(var string: String, count: Int, pad: Character) -> String {
 let amountToPad = count - countElements(string)
 for _ in 1...amountToPad {
  string = pad + string
 }
 return string
}
 
let originalString = "hello"
let paddedString = alignRight(originalString, 10, "-")
// paddedString is equal to "-----hello"
// originalString is still equal to "hello"

If you want to modify the passed parameters in the function, you can use the inout keyword to identify them. The passed parameters need to be prefixed &, and this internal implementation should be a pointer.

func swapTwoInts(inout a: Int, inout b: Int) {
 let temporaryA = a
 a = b
 b = temporaryA
}
var someInt = 3
var anotherInt = 107
swapTwoInts(&someInt, &anotherInt)
println("someInt is now \(someInt), and anotherInt is now \(anotherInt)")
// prints "someInt is now 107, and anotherInt is now 3"

Function type, you can use functions as parameters and return values ​​like js

func addTwoInts(a: Int, b: Int) -&gt; Int {
 return a + b
} //The function type is (Int, Int) -> Intfunc multiplyTwoInts(a: Int, b: Int) -&gt; Int {
 return a * b
}//The function type is (Int, Int) -> Int 
//Receive a function type named mathFunctionfunc printMathResult(mathFunction: (Int, Int) -&gt; Int, a: Int, b: Int) {
 println("Result: \(mathFunction(a, b))")
}
printMathResult(addTwoInts, 3, 5)
// prints "Result: 8"
 
//Return function typefunc stepForward(input: Int) -&gt; Int {
 return input + 1
}
func stepBackward(input: Int) -&gt; Int {
 return input - 1
}
func chooseStepFunction(backwards: Bool) -&gt; (Int) -&gt; Int {
 return backwards ? stepBackward : stepForward
}
var currentValue = 3
let moveNearerToZero = chooseStepFunction(currentValue &gt; 0)
// moveNearerToZero now refers to the stepBackward() function

Closure

A function is called a closure together with a variable of the context it contains. Such as sort function:

let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
 
func backwards(s1: String, s2: String) -> Bool {
 return s1 > s2
}
var reversed = sort(names, backwards)
println(reversed)
// reversed is equal to ["Ewa", "Daniella", "Chris", "Barry", "Alex"]s

Use closures can be expressed as:

let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
 
var reversed = sort(names, {(s1:String, s2:String) -> Bool in
 return s1 > s2
})
println(reversed)
// reversed is equal to ["Ewa", "Daniella", "Chris", "Barry", "Alex"]

It can also be simplified to

let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
 
var reversed = sort(names, { s1, s2 in s1 > s2 } )
 
println(reversed)

enumerate

By the following syntax statement

enum Barcode {
 case UPCA(Int, Int, Int) = (1,2,3)
 case QRCode(String) = "hello"
}

Classes and structures

It is recommended to use capital letters to name them

struct Resolution {
 var width = 0
 var heigth = 0
}
class VideoMode {
 var resolution = Resolution()
 var interlaced = false
 var frameRate = 0.0
 var name: String?
}

Generate an instance:

let someResolution = Resolution()
let someVideoMode = VideoMode()

Attribute access and modification, use. Syntax:

println("The width of someVideoMode is \()")
 = 12880
println("The width of someVideoMode is now \()")

The structure has an automatic member initializer, but the class instance does not:

let vga = resolution(width:640, heigth: 480)

Structures and enumerations are both value types, and classes are reference types

For values ​​that reference the same instance, you can use === and !== to make judgments

Delay attribute, @lazy, set to initialize specific attributes when called

class DataImporter {
 /*
  DataImporter is a class that imports data from external files.
  This class will take a lot of time to initialize.
  */
 var fileName = ""
 // This provides data import function}
 
class DataManager {
 @lazy var importer = DataImporter()
 var data = String[]()
 // This provides data management functions}
 
let manager = DataManager()
 += "Some data"
 += "Some more data"
// The importer property of the DataImporter instance has not been created yet

Classes, structures, and enumerations can be set and getter.

struct AlternativeRect {
 var origin = Point()
 var size = Size()
 var center: Point {
 get {
  let centerX =  + ( / 2)
  let centerY =  + ( / 2)
  return Point(x: centerX, y: centerY)
 }
 set { //The setter does not define the parameter name that represents the new value, so the default name newValue can be used.   =  - ( / 2)
   =  - ( / 2)
 }
 }
}

Remove get and set

Attribute monitoring can be handled using willset and didset

Type attributes are a bit like static variables declared with static keywords

struct SomeStructure {
 static var storedTypeProperty = "Some value."
 static var computedTypeProperty: Int {
 // Return an Int value here }
}

Subscript

Classes, structures, and enums can all have subscripts, and it adds a shortcut to them, as follows:

struct TimesTable {
 let multiplier: Int
 subscript(index: Int) -&gt; Int {
  return multiplier * index
 }
}
let threeTimesTable = TimesTable(multiplier: 3)
println("3of6Double yes\(threeTimesTable[6])")
// Output "6 times 3 is 18"

inherit

Define a class

class Vehicle {
 var numberOfWheels: Int
 var maxPassengers: Int
 func description() -> String {
  return "\(numberOfWheels) wheels; up to \(maxPassengers) passengers"
 }
 init() {
  numberOfWheels = 0
  maxPassengers = 1
 }
}

Inheritance class

class Bicycle: Vehicle {
 init() {
  ()
  numberOfWheels = 2
 }
}

Rewrite properties and methods

class Car: Vehicle {
 var speed: Double = 0.0
 override var speed: Double {
 get {
  return 
 }
 set {
   = min(newValue, 40.0)
 }
 }
 init() {
  ()
  maxPassengers = 5
  numberOfWheels = 4
 }
 override func description() -> String {
  return () + "; "
   + "traveling at \(speed) mph"
 }
}

Prevent rewriting, add the keyword @final before methods and attributes, and errors will occur during compilation

Constructor

You can write multiple inits in the statement, which is a bit like overloading

struct Celsius {
 var temperatureInCelsius: Double = 0.0
 init(fromFahrenheit fahrenheit: Double) {
  temperatureInCelsius = (fahrenheit - 32.0) / 1.8
 }
 init(fromKelvin kelvin: Double) {
  temperatureInCelsius = kelvin - 273.15
 }
}
 
let boilingPointOfWater = Celsius(fromFahrenheit: 212.0)
// Yes 100.0let freezingPointOfWater = Celsius(fromKelvin: 273.15)
// Yes 0.0”

Class destruction

Some places are called anti-initialization, a very awkward name

class Player {
 var coinsInPurse: Int
 init(coins: Int) {
  coinsInPurse = (coins)
 }
 
 func winCoins(coins: Int) {
  coinsInPurse += (coins)
 }
 
 deinit {
  (coinsInPurse)
 }
}
 
var player = Player(coins:200)
player = nil //Calling the deinit method

Extended

For classes, structures, enums, everything they can be expanded

class Player{
 var age:Int
}
 
extension Player{
 func repetitions(task: () -> ()) {
  for i in 0..self {
   task()
  }
 }
}

protocol

It's actually an interface description

 protocol SomeProtocol {
  var mustBeSettable: Int { get set }
  var doesNotNeedToBeSettable: Int { get }
  func someTypeMethod()
 }

Agreement inheritance

 protocol InheritingProtocol: SomeProtocol, AnotherProtocol {
  // protocol definition goes here
 }

Generics

The generic version of this function uses node type naming (usually represented by the letter T in this case) instead of the actual type name (such as Int, String, or Double). The node type name does not mean that T must be of any type, but it stipulates that a and b must be T of the same type, regardless of whether T represents any type. Only the actual type passed in by the swapTwoValues ​​function every time it is called determines the type represented by T.

 func swapTwoValues<T>(inout a: T, inout b: T) {
  let temporaryA = a
  a = b
  b = temporaryA
 }

Operator overloading

Here is a demonstration of overloading + operator

struct Vector2D {
 var x = 0.0, y = 0.0
}
@infix func + (left: Vector2D, right: Vector2D) -> Vector2D {
 return Vector2D(x:  + , y:  + )
}
  • Prefix
  • Post-operator @postfix
  • Combination assignment operator @assignment
  • Comparison operator @infix
@prefix @assignment func ++ (inout vector: Vector2D) -> Vector2D {
 vector += Vector2D(x: 1.0, y: 1.0)
 return vector
}

Custom operators

Personalized operators can only use these characters /= - + * % < >! & | ^. ~

operator prefix +++ {}
@prefix @assignment func +++ (inout vector: Vector2D) -> Vector2D {
 vector += vector
 return vector
}

The value of association is none by default, and can be left, right, and none by default, and the priority is 100 by default.

operator infix +- { associativity left precedence 140 }
func +- (left: Vector2D, right: Vector2D) -&gt; Vector2D {
 return Vector2D(x:  + , y:  - )
}
let firstVector = Vector2D(x: 1.0, y: 2.0)
let secondVector = Vector2D(x: 3.0, y: 4.0)
let plusMinusVector = firstVector +- secondVector
// The value of plusMinusVector at this time is (4.0, -2.0)

From: