最近在学习edge ML。试着把Craft + OCR Reader model从云端移植到iOS上,结果发现很多现代model基本要不是object c要不是swift。而之前一直是在用Java。就不得不在此从语言开始学习swift。遂有了如下的swift笔记。

swift-lang

1. Constants and Variables

1.1 Declaring Constants and Variables

  • You declare constants with the let keyword and variables with var keyword.
let attempts = 10
var currentAttempt = 0

1.2 Type Annotations

let attempt: Int 
var currentAttempt: String

1.3 Printing Constants and Variables

print("The current value of friendlyWelcome is \(friendlyWelcome)")

1.4 Type Aliases

Type aliases define an alternative name for an existing type. You define type aliases with the typealias keyword

typealias AudioSample = UNIT16
var maxAmplitudeFound = AudioSample.min

1.5 Booleans

Swift has a basic Boolean type, called Bool

1.6 Tuples

Tuples group multiple values into a single compound value. The values of a tuple can be of any type and don’t have to be of the same type as each other

let http404Error = (404, "Not Found")
let (statusCode, statusMessage) = http404Error
// ignore parts of the tuple with an underscore(_)
let (justTheStatusCode, _)  = http404Error

1.7 Optionals

Use optional in situations where a value maybe absent. An optional represents two possibilities: Either there is a value, and you can unwrap the optional to access the value, or there isn’t a value at all.

// serverResponseCode contains an actual Int value of 404
var serverResponseCode: Int? = 404

// serverResponseCode now contains no value
serverResponseCode = nil

1.8 Optional Binding

You use optional binding to find out whether an optional contains a value, and if so, to make that value available as a temporary constant or variable.

if let constantName = someOptional {
    statements
}

1.9 Error Handling

You use error handling to respond to error conditions your program may encounter during execution.

Behavior same as Java.

func makeASandwich() throws {
    // ...
}

do {
    try makeASandwich()
    eatASandwich()
} catch SandwichError.outOfCleanDishes {
    washDishes()
} catch SandwichError.missingIngredients(let ingredients) {
    buyGroceries(ingredients)
}

1.10 Assertions and Preconditions

Assertions and preconditions are checks that happen at runtime. You can also use assert for debugging purpose.3

2. Basic Operators

2.1 Nil-Coalescing Operator

// unwraps an optional a if it contians a value, or returns a default value b if a is nil
a ?? b

2.2 Range Operators

Closed Range Operator

a...b defines a range that runs from a to b, and includes the value a and b.

a..<b defines a range that runs from a to b, but doesn’t include b.

3. Strings & Characters

4. Collection Types

Swift provides three primary collection types, known as arrays, sets and dictionaries, for storing collections of values.

  • Arrays are ordered collection of values
  • Sets are unordered collections of unique values
  • Dictionaries are unordered collections of key-value associations

You can create an empty set of a certain type using initializer syntax:

var letters = Set<Character>()
// We can also create a Set with an Array Literal
var favoriteGenres: Set<String> = ["Rock", "Classical", "Hip hop"]

Dictionary

As with arrays, you can create an empty Dictionary of a certain type by using initializer syntax:

var namesOfIntegers = [Int: String]()
// nameOfIntegers is an empty [Int: String] dictionary
nameOfIntegers = [:] 
// namesOfIntegers is once again an empty dictonary of type [Int: String]

5. Control Flow

Swift provides a variety of control flow statements.

5.1 For-In Loops

let names = ["Anna", "Alex", "Brian", "Jack"]
for name in names {
    print("hello, \(name)")
}

5.2 While

A while loop starts by evaluating a single condition.

5.3 Repeat-While

The other variation of the while loop, known as repeat-while loop, performs a single pass through the loop block first, before considering the loop’s condition.

repeat {
    statements
} while condition

5.4 Conditional Statements

if, switch, where, a switch case can use a where clause to check for additional conditions.

5.5 Control Transfer Statements

  • continue
  • break
  • fallthrough
  • return
  • throw

5.6 Checking API Availability

The compiler uses availability information in the SDK to verify that all of the APIs used in your code are available.

if #available (iOS 10, macOS 10.12, *) {
} else {
}

6. Functions

6.1 Defining and Calling Functions

func greet (person: String) -> String {
    let greeting = "Hello"
    return greeting
}

Screen Shot 2022-07-14 at 3.27.05 PM.png

6.2 Functions with Multiple Return Values

You can use a tuple type as the return type for a function to return multiple values as part of one compound return value.

6.3 Specifying Argument Labels

You write an argument label before the parameter name, separated by a space:

func someFunction(argumentLebel parameterName: Int) {
    // in the function body, parameterName refers to the argument value for that parameter.
}

7. Closures

Closures are self-contained blocks of functionality that can be passed around and used in your code. Closures can capture and store references to any constants and variables from the context in which they are defined. This is known as closing over those constants and variables. Swift handles all of the memory management of capturing for you.

  • Global and nested functions, as introduced in Functions, are actually special cases of closures. Closures take one of the three forms:
    • Global functions are closures that have a name and do not capture any values.
    • Nested functions are closures that have a name and can capture values from their enclosing function
    • Closure expressions are unnamed closures written in a lightweight syntax that can capture values from their surrounding context.
  • Swift closure expressions have a clean, clear style, with optimizations that encourage brief, clutter-free syntax in a common scenarios.
    • Inferring parameter and return value types from context.
    • Implicit returns from single-expression closures.
    • Shorthand argument names
    • Trailing closure syntax.

7.1 Closure Expressions

Closure expressions are a way to write inline closures in a brief, focused syntax.

7.2 The Sorted Method

Screen Shot 2022-07-14 at 3.55.32 PM.png

7.3 Closure Expression Syntax

Closure expression syntax has the following general form:

{ (parameters) -> return type in
    statements
}

// samples. 
reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in
    return s1 > s2
})

7.4 Trailing Closures

A trailing closure is written after the function call’s parentheses, even though it is still an argument to the function.

func someFunctionThatTakesAClosure(closure: () -> Void) {
    // function body goes here
}

Screen Shot 2022-07-14 at 4.05.53 PM.png

7.5 Capturing Values

A closure can capture constants and variables from the surrounding context in which it is defined. The closure can then refer to and modify the values of those constants and variables from within its body, even if the original scope that defined the constants and variables no longer exists

8. Enumerations

enum CompassPoint {
    case north
    case south
    case east
    case west
}

// You use the case keyword to introduce new enumeration cases.

enum Planet {
    case mercury, venus, earth, neptune
}

You indicate that an enumeration case is recursive by writing indirect before it, which tells the compiler to insert the necessary layer of indirection

Screen Shot 2022-07-14 at 4.18.00 PM.png

9. Structures and Classes

9.1 Structures and classes

Commons

  • Define properties to store values
  • Define methods to provide functionality
  • Define subscripts to provide access to their values using subscript syntax
  • Define initialize to set up their initial state
  • Be extended to expand their functionality beyond a default implementation
  • Conform to protocols to provide standard functionality of a certain kind

Classes have additional capabilities that structures don’t have:

  • Inheritance enables one class to inherit the characteristics of another.
  • Type casting enables you to check and interrupt the type of a class instance at runtime.
  • Deinitializers enable an instance of a class to free up any resources it has assigned.
  • Reference counting allows more than one reference to a class instance.

Structures and Enumerations are Value Types, Classes Are Reference Types

10. Subscripts

Classes, structures and enumerations can define subscripts, which are shortcuts for accessing the member elements of a collection, list, or sequence. You use subscripts to set and retrieve values by index without needing separate methods for setting and retrieval.

Swift’s Dictionary type implements a subscript to set and retrieve the values stored in a Dictionary instance.

var numberOfLegs = ["spider": 8, "ant": 6, "cat": 4]
numberOfLegs["bird"] = 2

10.1 Subscript Options

Subscripts can take any number of input parameters, and these input parameters can be of any type.

11. Inheritance

A class can inherit methods, properties and other characteristics from another class.

11.1 Subclassing

class SomeSubclass: SomeSuperclass {
    // subclass definition goes there
}

11.2 Overriding

A subclass can provide its own custom implementation of an instance method, type method, instance property, or subscript.

Screen Shot 2022-07-15 at 11.27.16 AM.png

11.3 Preventing Overrides

You can prevent a method, property or subscript from being overridden by marking it as final

12. Initialization

This process involves setting an initial value for each stored property on that instance and performing any other setup or initialization that is required before the new instance is ready for use.

Instances of class types can also implement a deinitializer, which performs any custom cleanup just before an instance of that class is deallocated.

12.1 Initializers

init() {
    // perform some initialization here.
}

12.2 Default Initializers

Swift provides a default initializer for any structure or class that provides default values for all of its properties and does not provide at least one initializer itself.

Screen Shot 2022-07-15 at 12.17.28 PM.png

13. Extensions

Extensions add new functionality to an existing class, structure, enumeration, or protocol type. This includes the ability to extend types for which you do not have access to the original source code.

Extensions in Swift can:

  • Add computed instance properties and computed type properties.
  • Define instance methods and type methods
  • Provide new initializers
  • Define subscripts
  • Define and use new nested types
  • Make an existing type conform to a protocol

13.1 Extension Syntax

extension SomeType {
    // new functionality to add to SomeType goes here
}

extension SomeType: SomeProtocol, AnotherProtocol {
    // implementation of protocol requirements goes here
}

13.2 Computed Properties

Extensions can add computed instance properties and computed type properties to existing types.

extension Double {
    var km: Double { return self * 1_000.0 }
    var m: Double {return self }
    var cm: Double { return self / 100.0 }
    ...
}

let onekm = 1000.m

13.3 Initializers

Extensions can add new initializers to existing types. This enables you to extend other types to accept your own custom types as initializer parameters.

13.4 Methods

Extensions can add new instance methods and type methods to existing types. **The following example adds a new instance method called repetitions to the Int type:

extension Int {
    func repetitions(task: () -> Void) {
    for _ in 0..<self {
    task()
        }
    }
}

// Print Hello! Hello! Hello!
3.repetitions {
    print("Hello!")
}

14. Protocols

A protocol defines a blueprint of methods, properties, and other requirements that suit a particular task or piece of functionality. The protocol can then be adopted by a class, structure, or enumeration to provide an actual implementation of those requirements.

// Protocol Syntax
protocol SomeProtocol {
}

struct SomeStructures: FirstProtocol, AnotherProtocol {
}

class SomeClass: SomeSuperClass, FirstProtocol, AnotherProtocol {
}

Screen Shot 2022-07-15 at 1.04.23 PM.png

15. Generics

Generic code enables you to write flexible, reusable functions and types that can work with any type, subject to requirements that you define.

16. Automatic Reference Counting

Swift uses Automatic Reference Counting(ARC) to track and manage your app’s memory usage.

17. Memory Safety

18. Access Control

19. Advanced Operators

So long, and thanks for all the fish.

参考

[1] Swift Lang Official Website.