1. Overview after reading

After reading “The Swift Programming Language Chinese edition”, I have a preliminary understanding of swift language. Swift is not only a programming language for project development, but also has the characteristics of scripting language. In terms of learning: Swift can be written on the playground of Xcode. What you see is what you get, which is very suitable for grammar learning. As for Swift, I personally think it is a language “standing on the shoulders of giants” and the strengths of many families. As long as you’re familiar with a major programming language, learning swift’s syntax shouldn’t be too difficult. Swift is very similar to the Java language in some syntax and keywords, so it is not difficult to learn. Of course, for those of you who are familiar with C++, you can make an analogy. At the same time, SWIFT is a new language, most of the trend of The Times are included in it, and it has its own unique skills in it, which is worth learning.

2. Grammar notes

2.1 illustrates

The programming languages are the same, so the basic syntax is the same. The following are mainly notes on different and important grammars, with no detailed descriptions of known or similar grammars.

2.2 Basic Types

(1) Variables and constants

Swift uses lets to define constants and var to define variables. For data types, swift makes its own inferences (the type is a placeholder for the type auto in C++). Constants cannot be changed once they are set, but variables can.

If a type needs to be specified, a type annotation is used

Var welcomeMessage: String // You do not need to write a type annotation. Swift can infer the type of a constant or variable that is assigned an initial valueCopy the code

Constant and variable names can contain almost any character, including Unicode characters:

Let PI = 3.14159 let hello = "Hello world" let 🐶🐮 = "dogcow" 'Copy the code

It is worth noting that:

A) In the actual project development, it should be defined as let type first. If it needs to be modified, the type should be modified to var

B) let means that the address is not modifiable, but the contents of the object are modifiable (constants are not modifiable)

(2) tuples

Swift provides tuples: multiple values combined into a compound value.

Values in tuples can be of any type and do not have to be the same type. With tuples, the return value of a function can return multiple values of different types.

Var tuple1 = (1, 2.0, "string", true) // 2. Var tuple2 = (parameter1:int, parameter2:double parameter3:String) tuple2 = (1, 2.0, Let tuple3 = (parameter1: 1, parameter2: "string") // Tuple value // 1. 0, tuple.1, tuple.2 // 2. Tag value tuple2.parameter1 tuple2.parameter2Copy the code

(3) Optional type

Make the program more secure!

In OC, there’s one way to write it.

NSString *str = [obj getSomeStr] ? : @ "";Copy the code

So just to make sure that STR is not nil, let’s make sure when we assign. Swift provides optional types to handle possible missing cases. Note that the optional type is a type.

var surveyAnswer: String? = "123" // surveyAnswer: The optional value is "123" // Note: The optional type is +?Copy the code

Constructor returns an optional value type

Let convertedNumber = Int(possibleNumber) // Since the constructor may fail, convertedNumber is presumed to be of type "Int? , or type "optional Int" // the constructor is the constructor, as it is called in C++ and JavaCopy the code

Use if or while to determine whether there is a value. This process is also known as optional binding

Let value = surveyAnswer! If newString = surveyAnswer {} if newstring = surveyAnswer {} if newstring = surveyAnswer {} Var a:Int! = 10 var b:Int = a var b:Int = a // var a:Int = 10 // var a:Int = 10Copy the code

(4) Value types and reference types

Value type: When it is assigned to a constant, variable, or passed in a function/method, the value is copied.

Reference type: Increases the reference count without copying.

(5) Others

(5.1) Type alias:

Swift does not use typedefs and has an equal sign.

typealias AudioSample = UInt16
Copy the code

(5.2) Semicolon

Semicolons are not used in Swift, but two statements on the same line do.

2.3 the operator

(1) Empty combination operator

Unpack if A contains a value, otherwise return a default value b

a ! = nil ? a! : b // A must be optional //Copy the code

(2) Interval operators

Swift provides several interval operators to conveniently express the value of an interval.

The closed interval operator (a… B) Define an interval containing all values from a to b, including a and b. The value of A cannot exceed the value of B.

The half-open interval operator (a..

One side interval operator (a… /… B) Can express an interval that extends indefinitely to one side

2.4 Characters and Strings

Swift’s String and Character types provide a fast and Unicode compatible way to process the text content in your code, so any Character can be used. Interestingly, variables or constants can be named in emoji or Chinese characters.

for character in "Dog! 🐶" {print(character)} // D // o // g //! / / 🐶Copy the code

In the book, String is based on Unicode scalars. Therefore, you need to understand Unicode code points, UTF-8 and other concepts. When we talk about count and Objective-C length returning different values, it’s also due to the encoding.

String is a value type, so the use of String is omitted.

2.5 the control flow

If (1)

The if condition must be a Boolean expression — this means something like if score {… } code that passes the value directly will report an error, and swift will not implicitly compare it to 0.

let individualScores = [75, 43, 103, 87, 12] var teamScore = 0 for score in individualScores {// swift If (score > 50) {//... ~ if score > 50 {teamScore += 3} else {teamScore += 1}} print(teamScore) // Guard can also be used as an optional binding. Let STR: String? ; Guard let value = STR else {//Copy the code

(2) the switch

Switch supports any type of data (ranges, tuples …………) And all kinds of comparison operations — not just integers and tests for equality.

Case also supports multiple conditions

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

In Swift, when the code in the matched case branch finishes executing, the program terminates the switch statement rather than proceeding to the next case branch. That is, there is no need to explicitly use a break statement in a case branch. If you need to generate case penetration, you can add fallthrough after the end of the case

2.6 the function

(1) Definition of function

// Define the format func funcName(parameters) -> returnType {function body} String) -> String { let greeting = "Hello, " + person + "!" return greeting }Copy the code

The format of the function is similar to that of JavaScript, except that the return value type is added

(2) Parameter list

The argument list is highlighted here.

(a) Parameter label and parameter name: Each function parameter has an argument label and a parameter name. Parameter labels are used when the function is called; When you call the function, you need to write the parameter labels before the corresponding parameters. Parameter names are used in the implementation of the function. By default, parameter names are used as their parameter labels.

Func someFunction(parameterName: Int) {// someFunction(parameterName: Int) {Copy the code

(b) If you don’t want a tag for an argument, use an underscore (_) instead of an explicit parameter tag.

func someFunction(_ firstParameterName: Int, secondParameterName: Int) {firstParameterName and secondParameterName represent the first and second parameter values in the function body} someFunction(1, secondParameterName: 2)Copy the code

(c) You can also use default parameters like C++, that is, provide default values

func someFunction(parameterWithoutDefault: Int, parameterWithDefault: Int = 12) {// if you do not pass a second parameter on the call, parameterWithDefault will be passed with a value of 12 in the function body. } someFunction(parameterWithoutDefault: 3, parameterWithDefault: 6) // parameterWithDefault = 6 someFunction(parameterWithoutDefault: 4) // parameterWithDefault = 12Copy the code

(d) Of course, you can also use variadic arguments to specify that function arguments can be passed an indefinite number of input values. By adding (…) after the variable type name To define variable parameters. The passed value of a variadic becomes an array of that type in the body of the function. For example, a Double called numbers… In the body of the function, it can be used as an array constant of type [Double] called numbers.

func arithmeticMean(_ numbers: Double...) -> Double { var total: Double = 0 for number in numbers { total += number } return total / Double(numbers.count) } arithmeticMean(1, 2, 3, 4, 5) // Return 3.0, which is the average of these 5 numbers. ArithmeticMean (3, 8.25, 18.75) // Returns 10.0, which is the average of these three numbers.Copy the code

(e) Function arguments are constant by default. Trying to change parameter values in the body of a function will result in a compilation error. If you want a function that can change the value of its arguments, and you want those changes to persist after the function call ends, you should define the argument as an input/output argument

When defining an input or output parameter, precede the parameter definition with the inout keyword, and the value needs to be a variable rather than a constant

When a parameter is passed as an input or output parameter, precede the parameter name with an ampersand (&) to indicate that the value can be modified by the function.

func swapTwoInts(_ a: inout Int, _ b: inout Int) {
    let temporaryA = a
    a = b
    b = temporaryA
}
Copy the code

(3) Function type

Function types are like function Pointers. In fact, as usual, “Everything is an object”.

In Swift, each function has a specific function type, which consists of the parameter type and return type of the function. Using function types is just like using any other type.

func addTwoInts(_ a: Int, _ b: Int) -> Int {
    return a + b
}

func multiplyTwoInts(_ a: Int, _ b: Int) -> Int {
    return a * b
}

var mathFunction: (Int, Int) -> Int = addTwoInts
Copy the code

Function types can be parameter types, return value types, and so on.

2.7 the closure

(1) Closure introduction

OC has blocks, C++ has lambda expressions, and swift has closures.

Closures take one of three forms:

  • A global function is a closure that has a name but does not capture any value
  • A nested function is a closure that has a name and can capture the value in its enclosing function field
  • A closure expression is an anonymous closure written with lightweight syntax that captures the value of a variable or constant in its context

Syntax for closures

{(parameters) -> return type in statements} var blockOne:(String, Int) = {(parma1:String, Int); parma2:Int) -> void in }Copy the code
Let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"] // A single-line expression closure can implicitly return the result of a single-line expression by omitting the return keyword reversedNames = names.sorted(by: {s1, s2 in s1 > s2}) // call the closure arguments directly through $0, $1, $2, and so on. reversedNames = names.sorted(by: {$0 > $1}) // Swift's String type defines a String implementation for the greater-than sign (>), It takes two String arguments as a function and returns a Bool value reversedNames = names.sorted(by: >)Copy the code

Also note that the closure expression is a reference type.

(2) Escape closure

When a closure is passed as an argument to a function, but the closure is not executed until the function returns, the closure is said to escape from the function. When you define a function that accepts a closure as an argument, you can say before the argument name, @escaping, to indicate that the closure will allow “escaping” out of the function.

// @escaping, which is used to indicate that the closure allows "escaping" out of the function. var completionHandlers: [() -> Void] = [] func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) { completionHandlers.append(completionHandler) }Copy the code

(3) Tag closures

If you need to pass a long closure expression as the last argument to a function, you can write the closure after the function parentheses, and the function can call it as the last argument. When using a trailing closure, you don’t have to write out its parameter tags

func someFunctionThatTakesAClosure(closure: () - > Void) {/ / function body part} func mySug () {/ / here is not to use following the closure of the function call someFunctionThatTakesAClosure (closure: Main part} {/ / closure) / / the following is the use of following the closure of the function call someFunctionThatTakesAClosure () {/ / closures body}}Copy the code

2.8 Enumerations, structs, classes

(1) enumeration

Enumerations in Swift are more flexible and do not have to provide a value for each enumeration member. If you provide a value (called a raw value) to an enumeration member, the value’s type can be a string, a character, or an integer value or a floating point number.

Enum SomeEnumeration {// Put enumeration definition here // Use case keyword to define a new enumeration member value. Compspoint {case North Case South case East Case West} // You can define a set of related enumeration members in an enumeration. Each enumeration member can have an associated value of the appropriate type. enum Barcode { case upc(Int, Int, Int, Int) case qrCode(String)} enum TestEnum:CaseIterable {} for item in TestEnum. AllCases {}Copy the code

(2) Structures and classes

Define syntax:

Struct SomeStructure {// define struct SomeStructure} class SomeClass {// define class SomeClass} // Define class SomeClass {// define class SomeClass} It is not recommended that you have many similarities, but class is what defines classes, so I don't need to talk about structs too muchCopy the code

Note:

  • Inheritance allows a class to inherit the characteristics of another class
  • Type casting allows the type of a class instance to be examined and interpreted at run time
  • A destructor allows a class instance to release any resources it has been allocated
  • Reference counting allows multiple references to a class

(3) Attributes and methods of the class

(a) properties

The attributes of a class in SWIFT are divided into storage attributes and computing attributes.

A storage property is a constant or variable stored in an instance of a particular class or structure.

class FixedLengthRange {
    var firstValue: Int
    let length: Int
}
Copy the code

To evaluate a property is to not store a value directly, but to provide a getter and an optional setter to indirectly get and set the value of other properties or variables.

Struct Point {var x = 0.0, y = 0.0} struct Size {var width = 0.0, Struct Rect {var origin = Point() var size = size () var center: Point { get { let centerX = origin.x + (size.width / 2) let centerY = origin.y + (size.height / 2) return Point(x: centerX, y: centerY) } set(newCenter) { origin.x = newCenter.x - (size.width / 2) origin.y = newCenter.y - (size.height / 2) } } }Copy the code

Swift also has a class attribute that is similar to C++ static members.

Use the keyword static to define type attributes. When you define a computed type attribute for a class, you can use the keyword class to enable a subclass to override the implementation of the parent class.

struct SomeStructure { static var storedTypeProperty = "Some value." static var computedTypeProperty: Int { return 1 } } enum SomeEnumeration { static var storedTypeProperty = "Some value." static var computedTypeProperty:  Int { return 6 } } class SomeClass { static var storedTypeProperty = "Some value." static var computedTypeProperty: Int { return 27 } class var overrideableComputedTypeProperty: Int { return 107 } }Copy the code

(b) method

Instance methods, like normal methods, can use the self keyword for the method body

Class methods specify type methods by adding the keyword static before the func keyword of the method. Classes can also be specified with the keyword class, allowing a child class to override a parent class’s implementation of the method.

2.9 Construction and destruction of classes

(1) Basic description

Class construction and destruction are similar to C++ construction and destruction, except perhaps in syntax. For example: full default construct, default construct, etc. Here are some of the more important constructor syntax:

// Default init() {// Default init() {// default init() {// default init() {// default init() {// default init() {// default init()} Type) {// add self self. XXX = parmaterNmae; } init? Required init(parmaterNmae: type){}Copy the code

Here are some examples:

Class Color {let red, green, blue: Double init() {// default constructor} init(red: Double, green: Double, blue: Double) {self.red = red self.green = green self.blue = blue} init(white: Double) {red = white green = white blue = white}}Copy the code

(2) Construct agent constructors can perform part of the construction of an instance by calling other constructors. This process is called constructor proxy, and it prevents code duplication across multiple constructors. As mentioned in Effective OC2.0, when a constructor is set, it provides a base constructor that can be used with other constructs. Because structs and enumerations are value types and cannot be inherited, they can only be proxied to their other constructors.

struct Rect {
    var origin = Point()
    var size = Size()
    init() {}

    init(origin: Point, size: Size) {
        self.origin = origin
        self.size = size
    }

    init(center: Point, size: Size) {
        let originX = center.x - (size.width / 2)
        let originY = center.y - (size.height / 2)
        self.init(origin: Point(x: originX, y: originY), size: size)
    }
}
Copy the code

Classes, on the other hand, can inherit from other classes. This means that it is the responsibility of the class to ensure that all of its inherited stored properties are properly initialized at construction time. There are two types of constructors for classes: the specified constructor and the convenience constructor. Swift’s design for constructors is really verbose. To summarize: If a class is a base class, then the constructor should be written as before. Uninitialized properties must be initialized. The point is not in the case of the base class: the specified constructor of a subclass must first initialize the properties of its own class before calling the specified constructor of its parent class. Let me rewrite the same thing. A convenience constructor is one where you can provide simplified arguments and then call the specified constructor in the class. Classes do not inherit from constructors. Inheritance occurs automatically if:

  1. This assumes that you provide default values for all new properties introduced in subclasses
  2. If a subclass does not define any specified constructors, it automatically inherits all specified constructors from its parent class.
  3. If a subclass provides an implementation of all of the parent class’s specified constructors — either inherited through Rule 1 or provided a custom implementation — it will automatically inherit all of the parent class’s convenience constructors.

(3) Can fail to construct

A constructor can fail if an invalid parameter is passed to it, a required external resource is missing, or a necessary condition is not met.

class Document { var name: String? // The constructor creates a document instance init() {// The constructor creates a document instance init() {// The constructor creates a document instance init() {// The constructor creates a document instance init(); (name: String) { if name.isEmpty { return nil } self.name = name } }Copy the code

(4) The necessary constructor

Adding the required modifier before the constructor of a class indicates that all subclasses of that class must implement the constructor

Class SomeClass {required init() {// constructor implementation}} class SomeClass {required init() {// constructor implementation}} The required modifier // must also be added before the constructor of a subclass to indicate that the constructor requirement also applies to subclasses later in the inheritance chain. Class SomeSubclass: SomeClass {required init() {// constructor implementation}} class SomeSubclass: SomeClass {required init();Copy the code

(5) the destructor

Destructors are only applicable to class types and are called immediately before an instance of a class is released. Destructors are marked with the keyword deinit, just as constructors are marked with init.

Deinit {// execute the destructor}Copy the code

2.10 Property listeners

class SomeClass : NSObject { var name : String {// Property is about to change willSet {} // Property has changed didSet {}}} // Triggered even if the same value is set // Cannot exist with the setter //Copy the code

2.11 Class inheritance

Inheritance, one of the three major features of object-oriented languages, is the same in Swift as a means of reusing code. Swift is different from OC, where all the classes in OC are based on NSObject. But the classes in Swift do not inherit from a generic base class. If you do not specify a superclass for your class, it will automatically become the base class. The basic syntax for inheritance:

Class SomeClass: SomeSuperclass {// here is the definition of the subclass}Copy the code

Here’s an example:

// Parent class Vehicle {var currentSpeed = 0.0 var description: String {return "traveling at \(currentSpeed) miles per hour"} func makeNoise() {return "traveling at \(currentSpeed) miles per hour"  Bicycle: Vehicle { var hasBasket = false }Copy the code

rewrite

// Override // Override a feature. You need to precede the override definition with the override keyword. Class Train: Vehicle {override func makeNoise() {print("Choo Choo")}} // If you provide setters in the override property, you must also provide getters. // If you don't want to change the inherited property value in the getter in the overridden version, you can return the inherited value directly via super.someProperty, where someProperty is the name of the property you want to override.Copy the code

You can prevent methods, properties, or subscripts from being overwritten by making them final by adding the final modifier before declaring keywords (for example: Final Var, Final Func, Final Class Func and Final SubScript). Any code that attempts to override a method, attribute, or subscript with a final tag will report an error at compile time. Methods, properties, or subscripts ina class extension can also be marked final in the extension’s definition. You can mark an entire class as final by adding the final modifier (final class) before the keyword class. Such a class is not inheritable, and attempts to inherit such a class will result in a compilation error.

2.12 extensions

Extensions can add functionality to an existing class, structure, enumeration, or protocol. It also has the ability to extend without access to the source code of the type being extended (i.e., reverse modeling)

  • Extensions in Swift can:
  • Add computational instance attributes and computational class attributes
  • Define instance methods and class methods
  • Provide a new constructor
  • Define the subscript
  • Define and use new nested types
  • Conform an existing type to an agreement
// extension SomeType {// add new functionality to SomeType} // Add multiple protocols to a class extension SomeType: SomeProtocol, AnotherProtocol {// the required implementation of the protocol is written here}Copy the code

2.13 protocol

The protocol keyword defines the protocol.

Protocol SomeProtocol {// this is the definition of the protocol}Copy the code

Make a class conform to a protocol

class SomeStructure: FirstProtocol, AnotherProtocol {// If a class has a parent class, it should be separated by commas before the names of the protocols it follows: class SomeClass: SomeSuperClass, FirstProtocol, AnotherProtocol {// here is the class definition part}Copy the code

Protocol-defined attributes

Var doesNotNeedToBeSettable: Int {get}}Copy the code

2.14 generics

(1) Basic grammar

For generics, the analogy can be made to C++ templates. C++ standard template library STL is the classic of generics programming.

Swift’s generic syntax is also similar to templates —

.

Func swapTwoValues<T>(_ a: inout T, _ b: Inout T) {let class SomeClass<T> {}Copy the code
// C++ // function template <class T>; void swapTwoValues(T& a, T& b) { T tmp = a; a = b; b = tmp; } // template <class T>; class SomeClass { T _someClass; };Copy the code

3. Summary

Due to the time, the summary is hasty, and there are many places to be added. For SWIFT language, it is only a simple study of the syntax. Its core idea still needs further in-depth study — practice + concept.

Ask like iOS small partner attention! Like words to a like it! Thank you very much! Thank you very much! Thank you very much!

— — — — — — — —

Click on the:For more information