Simple values

  • Multi-line string with three double quotation marks (“””)
var name = """ "1111 2222222222 3333333333333" """;
Copy the code
  • To create an empty array or dictionary, use the initialization syntax.
let emptyArray = [String] ()let emptyDictionary = [String: Float] ()Copy the code

The control flow

for-in

// Normal for loop
let individualScores = [75.43.103.87.12]
var teamScore = 0
for score in individualScores {
    if score > 50 {
        teamScore + = 3
    } else {
        teamScore + = 1}}// You can use for-in to iterate over items in the dictionary by providing a pair of names for each key-value pair. Dictionaries are an unordered collection, so their keys and values will be iterated over in any order.
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
        }
    }
} 

// You can use... Save indexes in a loop to generate index ranges.
var total = 0
for i in 1.3 {
    total + = i
}
print(total) // Prints "6"

// Ignore the range of values above
var total = 0
for i in 1..<3 {
    total + = i
}
print(total) // Prints "2"

Copy the code

guard

A syntactic sugar for control flow that simplifies code action and is used to express “early exit” intent

If filePath is nil, execute else
guard let filePath: String = FilePath(a)else {
    return 
}

// TODO, code to execute when filePath is not nil
Copy the code

function

  • Functions use their parameter names as parameter labels. Write a custom parameter label before the parameter name, or write _ to omit the parameter label.
func greet(_ person: String.on day: String) -> String {
    return "Hello \(person), today is \(day)."
}
greet("John", on: "Wednesday") 
Copy the code
  • Setting default Parameters
func makecoffee(name :String = "Cappuccino") -> String {
    return "Make a cup\(type)Coffee."
}

let coffee1 = makecoffee("Latte") / / latte
let coffee2 = makecoffee()		// Cappuccino
Copy the code
  • Variable parameter
func sum(numbers:Double...). -> Double {
    var total: Double = 0
    for number in numbers {
        total + = number
    }
    return total
}

sum(100.0.20.30)
sum(30.80)
Copy the code
  • Reference types (passing of Pointers)
By default, function arguments are passed by value. If you want to change an external variable, you need to pass the address of the variable to be a variable because you need to change its value internallyThe inout keyword provided by Swift does this

// Function 2: pass pointer
func swap1(inout a : Int.inout b : Int) {
    let temp = a
    a = b
    b = temp

    print("a:\(a), b:\(b)")
}

swap1(&a, b: &b)
print("a:\(a), b:\(b)")
Copy the code
  • The constructor
    • Before the custom constructor calls super.init, ensure that all properties are initialized, or declare Property self.titles not initialized… error
  • Functions are of a type. This means that a function can return another function as its value.
Sum returns ((Int, Int) -> Int), which is a function
func sum(a: Int.b: Int)- > ((Int.Int) - >Int) {
    func inner(innerA: Int.innerB: Int) -> Int {
        return innerA + innerA
    }

    return inner
}

var cal = sum(a: 2, b: 3)
let c = cal(3.4);
Copy the code
  • A function can take another function as one of its arguments
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(list: numbers, condition: lessThanTen) 
Copy the code
  • closure
func loadData(id: String.callback: (_ data: AnyObject? ._ error: NSError?). - > ()) {
        
}

loadData(id: "1") { (data: AnyObject? , error:NSError?).in
    //
}
Copy the code
  • Escape closure: When a closure is passed to a function as an argument, but may be used after the function returns, the closure is called from the functionThe escape
    • The escape closure needs to be added@escapingTo indicate that the closure is allowed to “escape” from the function
    • Mark a closure as@escapingThat means you have to reference it explicitly in the closureselfNon-escape closures do not. It’s a reminder that you might accidentally catch itselfNotice circular references.
var completions: [() -> Void] = []
func testEscapingClosure(completion: @escaping() - >Void) {
    completions.append(completion)
} 
Copy the code

Object, class, structure

Class and struct

Similarities: We can use exactly the same syntax rules to define attributes, methods, subscripts, constructors for classes and structs, and we can provide functionality through extension and protocol.

Difference:

  • In contrast to structs, classes have the following functions: 1. Inheritance allows a class to inherit features from another class. Type conversions allow the type of an instance of a class to be checked and interpreted at run time. 3. Reference counting allows multiple references to a class. The destructor allows a class instance to release any resources it allocates.
  • In Swift, struct is a value and class is a reference. If a method changes its properties, the method needs to be marked mutating to generate a new value to replace the old one (this step may be optimized by the compiler and does not necessarily produce a new struct). Class is the same object no matter how you pass it.

Extension

  • To extend the constructor in Extension, you must extend the convenience constructor
    • You must add convenience before init
    • You must call one of the original constructors of self.init()
convenience init(a)  {
	self.init()}Copy the code

For agreement

  • Object oriented problems: Multiple inheritance cannot be implemented, and the inheritance relationship becomes complicated

  • To avoid circular references, the agent uses the weak modifier, but the weak modifier returns an error because weak only modifiers class, so the protocol needs to inherit from class

  • Struct enums can comply with the protocol

  • Protocol-oriented examples:

protocol SportProtocol {
    var hot: Double  {get set} // {get set} can be read or written
    
    func playFootBall(a)
    @objc optional func playBasketBall(a) // The @objc optional method above is optional
}

// In the protocol, attributes/methods can be implemented in Extension by default
extension SportProtocol {
    var price: Double { // If you want to modify the property, you must overwrite it
        return 100.0
    }
    
    func playFootBall(a) {
        print("T football")}}Copy the code
  • Implement unified niB loading protocol
import Foundation
import UIKit

protocol NibLoadProtocol {}// where Self: UIView indicates that the call must be UIView and its subclasses
extension NibLoadProtocol where Self: UIView {
    // Static represents a class method
    static func loadFromNib(a) -> Self {
        return Bundle.main.loadNibNamed("\ [self)", owner: nil, options: nil)?.first as! Self}}Copy the code

The enumeration

  • Syntax for enumerations, beginning with enum. Members of each row are defined starting with case keywords. Multiple keywords can be defined on a line
enum CompassPoint {
    case North
    case South
    case East
    case West
}
 
enum CompassPoint {
    case North.South.East.West
}

In the above example, the values of North,South,East, and West are not equal to 0,1,2,3, but they are their own values and the type of the value is CompassPoint
Copy the code
var directionToHead = CompassPoint.West 
DirectionToHead is a CompassPoint type that can be assigned to other values of that type
// When setting the value of directionToHead, its type is known, so you can omit the type of East
directionToHead = .East
Copy the code
  • Use switch to separate enumerated values for different operations. A case within a switch must contain all branches of the enumeration or the compilation will fail. Of course, when listing all the enumerated values is inconvenient, you can use default
directionToHead = .South
switch directionToHead {
case .North:
    println("Lots of planets have a north")
case .South:
    println("Watch out for penguins")
case .East:
    println("Where the sun rises")
case .West:
    println("Where the skies are blue")}Copy the code
  • Enumeration elements can be associated values, as illustrated by an example of an enumeration bar code that can store both a one-dimensional bar code (consisting of three integers) and a two-dimensional bar code (consisting of strings)
enum Barcode {
    case UPCA(Int.Int.Int)
    case QRCode(String)}// Define a variable. This variable can be assigned to three integers or a string, but both are enumerated values of type Barcode
var productBarcode = Barcode.UPCA(8.85909 _51226.3)
productBarcode = .QRCode("ABCDEFGHIJKLMNOP")
 
// When using switch, the type of bar code can be distinguished in case, and the combined value can be obtained by using variables or constants
switch productBarcode {
case .UPCA(let numberSystem, let identifier, let check):
    println("UPC-A with value of \(numberSystem).\(identifier).\(check).")
case .QRCode(let productCode):
    println("QR code with value of \(productCode).")}// Print "QR code with value of ABCDEFGHIJKLMNOP."

*incaseInternal, if both of their types areletorvar, the keyword can be arrived in advancecaseAnd enumeration types, such as:case let .UPCA(numberSystem, identifier, check):
Copy the code
  • An enumeration of an original value type follows the enumeration name by the data type, and its enumeration members are assigned initial values at definition and cannot be changed, in contrast to an enumeration of an associative value type, where the enumeration value is set when the enumeration value is assigned to a variable.
// The type of the primitive value enumeration follows the enumeration name, and the data type of the primitive value of its members is the specified type
enum ASCIIControlCharacter: Character {
    case Tab = "\t"
    case LineFeed = "\n"
    case CarriageReturn = "\r"
}
// The primitive values of enumerators of type Int are incremented, for example, Venus is 2 and Earth is 3
enum Planet: Int {
    case Mercury = 1.Venus.Earth.Mars.Jupiter.Saturn.Uranus.Neptune
}
// The original value of the enumerator can be obtained using the toRaw method
let earthsOrder = Planet.Earth.toRaw()
// the earthsOrder value is 3 and the data type is Int
 
// The enumerator corresponding to the original value can be obtained from the fromRaw method
let possiblePlanet = Planet.fromRaw(7)
// possiblePlanet data type Planet? Value is the Planet Uranus
 
// Because the original fromRaw value may not have a corresponding enumerator, the type returned is an optional variable value
let positionToFind = 9
if let somePlanet = Planet.fromRaw(positionToFind) {
    switch somePlanet {
    case .Earth:
        println("Mostly harmless")
    default:
        println("Not a safe place for humans")}}else {
    println("There isn't a planet at position \(positionToFind)")}// There is no member in the enumeration definition whose original value is 9, so print "There isn't a planet at position 9"
Copy the code

The enumeration function

// Enumerate functions
enum mobileLanguageFun{
     case IOS (String.String)
     case Android (String)
     // Define the enumeration function
     var description: String{
         switch self {
             case  mobileLanguageFun.IOS(let language1, let language2):
                 return "language1 = \(language1), language2 = \(language2)"
                 
             case mobileLanguageFun.Android(let temp):
                 return temp
             default:
                 return ("NO")}}}var myMobile: mobileLanguageFun = mobileLanguageFun.IOS("objc"."swift")
 println(myMobile.description)  //language1 = objc, language2 = swift
Copy the code

# # keywords

Access control

In Swift, there are five types of access modifiers: private, Fileprivate, internal, public, and open. Fileprivate and Open are newly added to Swift 3. Since the previous access control characters were file-based, not class-based. This can be problematic, so Swift 3 adds two modifiers that subdivide the original private and public.

In order from highest to lowest:

open > public > interal > fileprivate > private

  • Private:Modified properties or methods are accessible only in the current class and in an Extension.
  • Fileprivate:Modified properties or methods can only be accessed in the current file. If a file contains more than one class, it is also accessible.
  • Internal:Default access level, which can be ignored.
    • The modified properties and methods are accessible throughout the module in the source code.
    • If it is framework or library code, it is accessible throughout the framework, but not outside it.
    • If it’s App code, it’s accessible throughout the App.
  • Public:Can be accessed by any code. However, other modules cannot be overridden or inherited; modules can be overridden or inherited.
    • For things like constructors, you can only use public instead of open. Only public can be used to declare enum and protocol.
  • Open:Can be accessed by any module’s code, including Override and inheritance.
final:
  • Declares that the class, function, or attribute cannot be inherited or overridden.

#####filter: The conditions are met

  • Used to select elements in an array that meet certain criteria
intArray = [1.3.5]
let filterArr = intArray.filter {
  // $0 represents the first argument and an analogy
  return $0 > 2
}
/ / [3, 5]
Copy the code

# # # # # the map: conversion

  • Map is a method of the Array class that we use to convert each element of the Array
let intArray = [1.3.5]
let stringArr = intArray.map {
  return "\ [$0)"
}
/ / / "1", "3", "5"]
Copy the code

# # # # # reduce: calculation

  • Evaluates a combination of array elements to a value
let intArray = [1.3.5]
let result = intArray.reduce(0) {
	return $0 + The $1
}
/ / 9
Copy the code

Error handling and exception throwing

Several cases of active withdrawal from the program

  • Fatal Errors
    • To terminate your application immediately, use fatalError(), which gives the termination information. Using fatalError(), which terminates your application without conditions, is also relatively simple, just a function call.
fatalError("Fatal error, call my program to terminate.")
Copy the code
  • Assertions
    • Prompt conditions in assertions are optional. Assertions work in Debug mode, but are ignored in the Release version.
// @param: condition, when true, the assertion is not executed and the corresponding assertion information is not printed. When false, the assertion is executed and the corresponding assertion information is printed.
assert(<#T##condition: Bool# #Bool#>.<#T##message: String# #String#>)
Copy the code
  • Preconditions
    • Preconditions are used in the same way as assertions, but it is important to note that Preconditions are executed in both debug and release mode unless compiled using -ounchecked.
precondition(<#T##condition: Bool# #Bool#>.<#T##message: String# #String#>)
Copy the code

Error handling in Swift

  • In Swift, if you want to define your own ErrorType, you just implement the ErrorType protocol. Once you have declared the error type, you can use your custom error type when handling the exception thrown by the error.

1. Use enumerations to create error types

  • 1.1 Follow the ErrorType protocol to define error types. Below we define an ErrorType enumeration that follows the ErrorType protocol, and we will use this MyCustomErrorType enumeration in the rest of the code
// Define an error type
enum MyErrorType: ErrorType {
    case ErrorReason1
    case ErrorReason2
    case ErrorReason3
}
Copy the code
  • 1.2 The throws keyword can be used in our function definition, as well as in functionsthrowKeyword to throw an error, throw the error type can use our own error type defined above.
func throwError(a) throws {
    let test: Int? = nil

    guard test ! = nil else {
        throw MyErrorType.ErrorReason2}}Copy the code
  • 1.3 The above function is used to throw an errordo-catchTo handle thrown errors. usetryTo catch errors, usedo-catchHandle errors.
do {
    try throwError()
} catch MyErrorType.ErrorReason1 {
    print("Error cause: 1")}catch MyErrorType.ErrorReason2 {
    print("Error cause: 2")}catch {
    print("Error cause: 3")}do {
    try throwError()
} catch MyErrorType.ErrorReason1.MyErrorType.ErrorReason2 {
    print("Error cause:")}catch {
    print("Error cause: 3")}Copy the code

2. Use a structure to add Reason to error handling

  • Using a structure to follow the ErrorType protocol provides a reason for a custom ErrorType when an error is thrown.
  • 2.1 create an ErrorType using a structure. The structure named MyErrorType follows the ErrorType protocol and a reason constant is declared in the MyErrorType structure. The reason constant stores the cause of the error
struct MyErrorType2: ErrorType {
    let reason1: String
    let reason2: String
}
Copy the code
  • 2.2 After the error type structure is defined above, it can be used in error throwing. When an error is thrown, you can pass in a reason for the error
func throwError2(a) throws {
    let test: Int? = nil

    guard test ! = nil else {
        throw MyErrorType2(reason1: "1", reason2: "For 2")}}Copy the code
  • 2.3 At last, do catch processing should be carried out for the thrown error. During the processing, error causes can be printed and stored in error
do {
    try throwError2()
} catch {
    print(error)
}
Copy the code

3. Make the String type follow the ErrorType protocol and use String directly to provide the cause of the error

  • This is the easiest way
extension String: ErrorType {}func throwError3(a) throws {
    let test: Int? = nil
    
    guard test ! = nil else {
        throw "error"}}do {
    try throwError3()
} catch {
    print(error)
}
Copy the code
The try? And the try! What does that mean?
  • try? : indicates that exceptions are ignored. If a subsequent expression throws an exception, it is ignored and returns nil.
  • try! : assert that no exception is thrown here. If the following expression has an exception thrown, it crashes.
func someThrowingFunction(a) throws -> Int {
    // ...
}

let x = try? someThrowingFunction() 

let y: Int? 
do {
    y = try someThrowingFunction()
} catch {
    y = nil
} 
Copy the code