First:
Use Func to declare a function, using the name and arguments to invoke the function. Use to specify the function return value.
Use a tuple to return multiple values.
The number of arguments to the function is variable, with an array to fetch them: Func sumof (Numbers:int ...), Int
Functions can be nested. Nested functions can access variables of the outer function, and you can use nested functions to refactor a function that is too long or too complex.
A function is a class citizen, which means that a function can be used as a return value for another function, and a function can also be passed as a parameter to another function.
function is actually a special kind of closure, you can use {} to create an anonymous closure. Use in to split the parameter and return the type.
There are many ways to create closures. If a type of closure is known, such as a callback function, you can ignore the type and return value of the parameter. A single statement closure will return the value of its statement as a result.
You can refer to parameters by parameter location instead of parameter name-this method is very useful in very short closures. When a closure is passed to a function as the last argument, it can be followed directly by the parentheses.
If you do not need to calculate a property but need to run some code before or after setting a new value, use Willset and Didset.
var variable:type
{
get{}
set{}willset{}
didset{}}
There is an important difference between a method in a class and a general function, the parameter name of the function is used only inside the function, but the parameter name of the method needs to be explicitly stated at the time of the call (except for the first argument). By default, the parameter name of the method is the same as its name inside the method, but you can also define a second name, which is used inside the method.
When working with optional values for variables, you can add them before actions such as methods, properties, and sub-scripts. If the previous value is nil, then everything behind will be ignored and the entire expression returns nil. Otherwise, everything after that will be run. In both cases, the value of the entire expression is also an optional value.
Use the Toraw and Fromraw functions to convert between the original value and the enumeration value.
Use a struct to create a struct body. Structs and classes have many of the same places, such as methods and constructors. One of the biggest differences between the structures is that the struct is a value, and the class is a reference.
Classes, enumerations, and structs can all implement interfaces.
Use extension to add functionality to an existing type, such as adding a method that calculates a property. You can use extensions to add protocols to any type, even types that you import from external libraries or frameworks.
Write a name in angle brackets to create a generic function or type.
Basic part:
Optional is somewhat like using nil in objective-c, but it can be used on any type, not just a class.
Swift is a type-safe language (or strongly typed language).
There is a case where you have to use a semicolon, that is, you intend to write multiple separate statements within the same line.
Swift?? 8,16,32 and 64-bit signed and unsigned integer types are provided.
-Double represents a 64-bit floating-point number. Use this type when you need to store large or very high-precision floating-point numbers. -Float indicates a 32-bit floating-point number. This type can be used if the accuracy requirement is not high.
Type aliases is the definition of another name for an existing type. You can use the Typealias keyword to define type aliases.
Tuples (tuples) combine multiple values into a single composite value. Values within a tuple can be of any type and are not required to be of the same type.
Tuples are useful when organizing values temporarily, but they are not suitable for creating complex data structures.
Use an optional binding (optional binding) to determine whether an optional value is included, and if so, assign the value to a temporary constant or variable. Optional bindings can be used in the IF and while statements to judge an optional value and assign a value to a constant or variable.
Nil cannot be used for non-optional constants and variables. If you have constants or variables in your code that need to deal with missing values, declare them as the appropriate optional type.
Any type of optional can be set to nil, not just the object type.
Implicit parsing optional (implicitly unwrapped optionals)-implicit parsing is useful when you can determine after the first assignment that the value is always there. Implicit parsing can be chosen primarily in the construction of classes in Swift.
Operators have a single eye, binocular, and three-mesh operators.
Addition operation + also used for concatenation of strings:
Each comparison operation returns a Boolean value that identifies whether the expression is true
2. Single-byte Unicode scalar, written as \xnn, where nn is a two-bit hexadecimal number. 3. Double-byte Unicode scalar, written as \unnnn, where nnnn is a four-bit hexadecimal number. 4. Four-byte Unicode scalar, written as \unnnnnnnn, where nnnnnnnn is a eight-bit hexadecimal number.
Swift's String type is a value type.
Swift?? There are three ways to compare the values of strings: strings are equal, prefixes are equal, and suffixes are equal.
Swift language?? For the classic array and dictionary collection types to store collection data.
The write Swift array should follow a form like array<sometype>, where SomeType is the only data type allowed in this array. We can also use simple syntax like sometype[].
Array<sometype> = = sometype[]
Type checking and type inference
Swift's switch statement is more powerful than the C language. In the C language, what if?? A case accidentally misses a break, and it "falls into" the next Case,swift no need to write a break, so this "fall in" situation does not occur. The case can also match more type patterns, including scope (range) matching, tuple (tuple), and specific types of?? Described The matching value in a switch case statement can be determined by a temporary constant or variable inside the case body, or by the WHERE clause?? The more complex matching conditions are described.
The pattern of case blocks allows the matching values to be bound to a temporary constant or variable that can be referenced in that block of arguments-a behavior called value binding.
Strictly speaking, the Saygoodbye function does return a value even if the return value is not defined. A function that does not define a return type returns a special value of type Void. This is only an empty tuple, where there are no elements and can be written ().
?? Example: The return value can be ignored, but a function that defines the return value must have a return value. For a function that defines a return type, if there is no return value, the control flow is not allowed to leave the bottom of the function.
This parameter type name is called the local parameter name, because they can only be used in the body of the function.
External parameter name: Sometimes it is useful to call a function to name each parameter to indicate that you are passing each argument to the function's purpose. If you are a formal parameter?? For an external parameter name, the external parameter name must be used at the time of invocation.
Place a formal parameter with a default value at the end of the function parameter list. This ensures that all function calls use the same sequence of no default value arguments and that the same function is called clearly in each case.
A function can have a maximum of one deformable parameter, and it must appear at the end of the argument list to avoid using multiple parameter invocation functions to cause ambiguity. If your function has one or more formal parameters with default values, and there are deformable parameters, place the deformable parameter after all default parameters, that is, the end of the list.
The changes you make to the parameter parameters are not more persistent than the calling function and are not visible outside the body of the function. Variable parameters exist only in the declaration period of a function call.
When you pass a variable as an argument to an in-out parameter, you need to add the & symbol directly before the variable to indicate that it can be modified by the function. The In-out parameter cannot have a default value, and the parameters of a mutable parameter cannot be marked as inout. If you mark a parameter as inout, it cannot be marked as VAR or let at the same time.
Different functions with the same matching type can be assigned to the same variable, as are non-function types. As with other types, when you assign a constant or variable to a function, you can let Swift infer the type of the function.
The global and nested functions described in the Functions section are actually special closures, and closures take one of the following three forms: 1. A global function is a closed 2 that has a name but does not capture any value. A nested function is a closed 3 that has a name and can capture the value in its enclosing function domain. A closure expression is a non-named closure that uses lightweight syntax to capture variables or constant values in its context.
The closure expression syntax can use constants, variables, and inout types as arguments, but not?? For default values. You can also use variable parameters at the end of the parameter list. Tuples can also be used as parameters and return values. Single-line expression closure can omit return
The closure expression syntax has the following general form: {(parameters)-ReturnType in
Statements}
If you need to pass a long closure expression as the last argument to a function, you can use the trailing closure to enhance the readability of the function.
The Trailing closure is a closure expression that is written outside the function brackets (after), and the function supports calling it as the last argument. If the function needs only one parameter of the closure expression, you can even omit () when you use the trailing closure.
Capture (Caputure)
Swift's simplest form of closure is a nested function, that is, a function defined in another function body. A nested function captures all parameters of its outer function, as well as the constants and variables defined.
Closures can capture constants or variables in the context in which they are defined. Even if the original scope for defining these constants and variables no longer exists, the closures can still reference and modify these values in the closure function body.
Whether you assign a function/closure to a constant or a variable, you are actually setting the value of the constant/variable to a reference to the corresponding function/closure.
Enumeration
In Swift, the enumeration type is a-first-class type. They employ many features that have traditionally been supported only by classes, such as computed attributes (computed properties). For additional information about enumerating the current values, instance methods (instance methods), for the?? The function that is associated with the value represented by the enumeration. Enumeration can also define the constructor (initializers) to come?? For an initial member value; You can extend their functionality on the basis of the original implementation; Can abide by the Protocol (protocols) to?? For standard functions.
Note that the original value and the associated value are not the same. When you start defining enumerations in your code, the original values are pre-populated values like the above three ASCII codes. For a particular enumeration member, its original value is always the same. The associated value is set when you create a new constant or variable based on an enumeration member, and each time you do so, its value can be different.
Structure and class
Note: Structs are passed through the code in a way that is copied, so do not use reference counting.
Unlike the Objective-c language, Swift allows you to directly set child properties of a struct property.
All structs have an automatically generated member-by-initializer that initializes the properties of members in the new struct instance. The initial values for each property in the new instance can be passed to the member-by-initializer by the name of the property:
1. Let VGA = Resolution (width:640, heigth:480) Unlike structs, class instances do not have a default member-by-initializer.
Structs and enumerations are value types
A value type is assigned to a variable, and the constant or itself is passed to a function, and the copy is actually manipulated. In fact, in Swift, all the basic types: integers, floating-point numbers (floating-point), Boolean values (Booleans), strings (string), arrays (array), and dictionaries (dictionaries) are value types , and are implemented in the background in the form of structs.
It is important to note that Teneighty and Alsot Eneighty are declared as constants (constants) instead of variables. However, you can still change teneighty.framerate and alsoteneighty.framerate, because these two constants do not change themselves. They do not store this Videomode instance, which is simply a reference to the Videomode instance in the background. So, the change is the framerate parameter of the referenced base videomode, without changing the value of the constant. The value of the constant here is a reference, and the reference cannot be changed.
The array and dictionary (Dictionary) types in Swift are implemented in the form of structs. However, when an array is assigned a constant or variable, or is passed to a function or method, its copy behavior is slightly different from that of the dictionary and other structures.
Whenever a dictionary instance is assigned to a constant or variable, or is passed to a function or method, the dictionary is copied when the assignment or invocation occurs.
If the keys and/or values stored in the dictionary instance are value types (struct or enum), they are copied when the assignment or invocation occurs. Conversely, if the keys and/or values are reference types, the copy will be a reference, not a class instance or function referenced by them. The copy behavior of the dictionary's keys and values is the same as the copy behavior of the properties stored by the struct.
If you assign an array instance to a variable or constant, or pass it as a parameter to a function or method call, the contents of the array will not be copied when the event occurs. Instead, the array is common with the same sequence of elements. When you modify within an array?? One element, the result of the modification is also displayed in another array. For arrays, copy behavior occurs only if the operation has the potential to modify the length of the array. This behavior includes attaching (appending), inserting (inserting), deleting (removing), or using a range subscript (ranged subscript) to replace the elements in this range.
It is necessary to make sure that the array has a unique copy before manipulating an array or passing it to a function and a method call. The uniqueness of the array reference is determined by calling the Unshare method on the array variable. (You cannot call the Unshare method when an array is assigned to a constant) if an array is referenced by more than one variable, and the Unshare method is called on one of the variables, the array is copied, and the variable will have its own independent array copy. When an array is referenced by only one variable, no copy occurs.
Store properties, computed properties, type properties, deferred store properties
Property associates a value with a specific class, struct, or enumeration. A store property stores a constant or variable as part of an instance, and computes a value for the property calculation instead of storing it. Computed properties can be used in classes, structs, and enumerations, and stored properties are used only for classes and struct bodies.
This behavior is because the struct (struct) belongs to a value type. When an instance of a value type is declared as a constant, all its properties are also constants. Classes that belong to reference types are different, and you can still modify the instance's variable properties after assigning an instance of a reference type to a constant.
A deferred store property is a property whose initial value is evaluated when it is first called. Use @lazy to mark a deferred storage property before the property declaration. Note: The deferred storage attribute must be declared as a variable (using the var keyword) because the value of the property may not be available until the instance construction is complete. The constant property must have an initial value before the construction process is complete, and therefore cannot be declared as a deferred attribute.
Note: You must use the var keyword to define calculated properties, including read-only computed properties, because their values are not fixed. The Let keyword is used only to declare a constant property, indicating a value that cannot be modified after initialization.
You can add property monitors for storage properties other than deferred storage properties, or you can add property monitors for inherited properties, including storage properties and computed properties, by overloading the properties.
Note: Willset and Didset monitors are not called during property initialization, they are called only when the value of the property is set outside of the initialization. Note: If you assign a value to a property in the Didset monitor, this value replaces the value set before the monitor.
In addition, both global and local scopes can define computed variables and define monitors for stored-type variables, which, like computed properties, return a computed value instead of a stored value, and the declaration format is exactly the same. Note: Global constants or variables are deferred, similar to deferred store properties, except that global constants or variables do not need to be tagged with the @lazy attribute; local scope constants or variables do not delay calculations.
For value types (refers to structs and enumerations) you can define both the storage type and the computed Type property, and for the class, only the computed Type property. A stored Type property of a value type can be a variable or constant, and a computed type property is defined as a variable property as the computed property of an instance.
Note: Unlike the storage properties of an instance, you must specify a default value for the stored Type property, because the type itself cannot use the constructor to assign a value to the Type property during initialization.
Use the keyword static to define the Type property of a value type, and the keyword class to define the Type property for the class.
Swift defaults to only a local parameter name for the first parameter name of the method; The default gives both the second and subsequent parameter names the local parameter name and the external parameter name.
Sometimes the first parameter of a method?? It is useful to have an external parameter name, although this is not the default behavior. You can add an explicit external name yourself or use a pound sign (#) as the prefix for the first parameter to take the local name as an external name. Conversely, if you do not want the second and subsequent parameters for the method?? For an external name, you can override the default behavior by using an underscore (_) as an explicit external name for the parameter. Structs and enumerations are value types. In general, a property of a value type cannot be modified in its instance method.
But what if you really need to be in?? A specific method of modifying a struct or enumeration property, you can choose the mutation (mutating) method, then the method can change its properties from within the method, and any changes it makes will remain in the original structure at the end of the method. The method can also assign an entirely new instance to its implied self property, and the new instance will replace the original instance after the method finishes.
Declare the type method of the class, precede the Func keyword of the method with the keyword class, declare the struct body and the type method of the enumeration, and precede the Func keyword of the method with the keyword static.
In the method body (body) of a type method, self points to the type itself, not the type's?? An instance. For structs and enumerations, this means that you can use self to disambiguate between static and static method parameters (similar to what we did when we processed the instance properties and instance method parameters earlier).
A type method can invoke the name of another type method in this class without prefixing the method name with the type name. Similarly, struct and enum type methods can also access static properties directly from the name of a static property without requiring a type name prefix.
Depending on the usage scenario, different subordinate scripts also have different meanings. Usually a subordinate script is used to access the collection (collection), for example, the Swift dictionary (Dictionary) implements the access operation of the value stored in its instance through the satellite scripts. Use the same type of value as the dictionary index in the satellite script, and assign the value of a dictionary value type to the subordinate script to set a value for the dictionary: a shortcut to the element in list or sequence (sequence). Can you implement satellite scripts freely in your own particular class or struct? For the right function.
The work of the constructor is to prepare a new instance for use and to ensure that all properties in the instance have valid initialization values.
Unlike Objective-c, in Swift, the initializer is not inherited by default, see initialization and rewriting of the initializer
Subclasses can be inherited from instance methods (instance method), class methods, instance properties (instance property), or satellite scripts (subscript)?? Implementation (Implementation) for your own customization. We call this behavior rewriting (overriding).
You can rewrite an inherited read-only property as a read-write property, just in the properties of the rewritten version?? For getter and setter. However, you cannot override an inherited read-write property to a read-only property.
You can not at the same time?? For overridden setters and overridden property observers.
You can mark an entire class as final by adding the @final attribute (@final Class) before the keyword class, so that the class is not inherited, or a compilation error is reported.
is the construction process for use?? A class, struct, or instance of an enumeration type. This procedure includes setting an initial value for each property in the instance and performing the necessary preparation and initialization tasks for it. Their primary task is to ensure that the new instance completes the correct initialization before first use. Classes and structs When an instance is created, the appropriate initial values must be set for all stored-type properties. The value of a stored-type property cannot be in an unknown state.
As long as the value of the constant is determined before the end of the construction process, you can modify the value of the constant property at any point in the construction process. Right?? class instance, its constant property can only be modified during the construction of the class in which it is defined, and cannot be modified in a subclass.
Default constructors, one-by-one object constructors, self-custom constructors
Swift will be for all properties already?? struct or base class for default values that do not have any constructors defined by themselves,?? For a default constructor. This default constructor will simply create an instance where all the property values are set to the default values.
Except for the top?? To the default constructor, if "struct" for all stored-type properties?? Default value and does not own it?? For custom constructors, they can automatically obtain a one-to-member constructor.
Constructors can perform part of the construction of an instance by invoking other constructors. This process, called the constructor agent, reduces code duplication between multiple constructors.
Note that if you are?? A value type defines a custom constructor, you will not be able to access the default constructor (one-by-one object constructor, if it is a struct). This restriction prevents you from defining a more complex one for a value type, and after you have completed the important preparation constructor, someone else mistakenly uses the autogenerated constructor.
Swift?? Two types of class constructors are available to ensure that the stored-type properties in all class instances can get the initial values, which are the specified constructors and convenience constructors, respectively. Specifies that the constructor is the primary constructor in the class. A specified constructor is initialized in the class?? The parent class is initialized by invoking the constructor of the parent class on the parent class chain. Each class must have at least one specified constructor.
Rule 1
Specifies that the constructor must call the specified constructor of its immediate parent class. Rule 2 The convenience constructor must call other constructors defined in the same class. Rule 3 The convenience constructor must end with a call to a specified constructor.
A more convenient way to remember is to specify that the constructor must always be up-to-the-proxy facilitation constructors must always be horizontal proxies
Two-stage construction process
The construction process for classes in Swift consists of two stages. In the first stage, each stored-type property sets the initial value by introducing the constructor of their class. When each stored-type attribute value is determined, the second phase begins, giving each class a chance to further customize their storage-type properties before the new instance is ready to be used.
The Swift compiler performs 4 effective security checks to ensure a smooth completion of the two-stage construction process: Security Check 1 specifies that the constructor must ensure that all properties introduced by its class must be initialized before the other construction tasks can be proxied up to the constructor in the parent class. As mentioned above, the memory of an object can be fully initialized only after all of its stored-type properties have been determined. To satisfy this rule, the specified constructor must ensure that the property introduced by its class is initialized before it is proxied. Security Check 2 specifies that the constructor must first call the parent class constructor on the proxy, and then set the new value for the inherited property. If this is not done, the new value given by the specified constructor is overwritten by the constructor in the parent class. Security Check 3 The convenience constructor must first invoke the other constructors in the same class, and then assign a new value to any property. If this is not done, the new value given by the convenience constructor will be overwritten by the other specified constructors in the same class. Security Check 4 The constructor cannot call any instance method, cannot read the value of any instance property, or reference the value of self until the first stage of construction is complete.
Stage 1?? A specified constructor or a convenience constructor is called; The allocation of the new instance memory is completed, but the memory is not initialized at this time, and the constructor is specified to ensure that all stored-type properties introduced by the class are assigned an initial value. The memory that the storage property belongs to is initialized; The constructor that invokes the parent class is called to complete initialization of the parent class's property, and the process that invokes the parent class constructor is executed along the chain of the constructor until it reaches the top of the constructor chain, and when the top of the constructor chain is reached, and has ensured that all instances contain stored-type properties that have been assigned, and that the memory of this instance is considered fully initialized. Phase 1 is complete at this time. Phase 2 continues from the top of the constructor chain, and the specified constructors of classes in each constructor chain have the opportunity to further customize the instance. The constructor can now access self, modify its properties, invoke instance methods, and so on. Finally, the convenience constructors in any constructor chain can have the opportunity to customize the instance and use self.
Suppose you want to introduce any new attributes into a subclass?? For default values, observe the following 2 rules: Rule 1 If the subclass does not define any of the specified constructors, it automatically inherits the specified constructors for all the parent classes. Rule 2 if subclass?? For all parent classes to specify the implementation of the constructor-whether inherited through rule 1 or by custom implementations-it automatically inherits the convenience constructors of all the parent classes.
Initialize the properties in the subclass ————— > Call the constructor of the parent class ————— > Modify the values of the properties in the child class and the parent class.
If you use closures to initialize the value of a property, remember that when the closure is executed, the rest of the instance is not initialized. This means that you are not able to access other properties in the closure, even if the property has a default value. Similarly, you cannot use the implicit Self property, or call other instance methods.
The inverse initialization function applies only to class types. Subclasses inherit the parent class's anti-initialization function, and at the end of the subclass's inverse initialization function implementation, the parent class's anti-initialization function is automatically called. Even if the subclass does not have?? For your own anti-initialization function, the parent class's anti-initialization function is always called.
The reference count is applied only to instances of the class. struct (Structure) and enum types are value types, not reference types, and are not stored and passed in a reference way.
Swift?? There are two ways to resolve strong reference rings: Weak references and no master references.
Use a weak reference for instances in which the reference in the lifecycle is nil, use a non-primary reference for instances where the reference is never assigned to nil after the initialization is assigned.
A weak reference can only be declared as a variable type, because its value may change at run time. A weak reference must never be declared as a constant.
Because a weak reference can have no value, it must be an optional type when declaring a weak reference. In the Swift language, it is recommended to use an optional type as a reference type that may not have a value.
A no-primary reference can only be defined as a non-optional type (non-optional type). You can declare a non-primary reference by adding the unowned keyword before the property or variable.
All two attributes must have a value and cannot be nil after initialization is complete. In this scenario, you want a class with a non-primary reference property, and another class with an optional property that is implicitly expanded.
A self-judging link (Optional Chaining) is a procedure that can request and invoke properties, methods, and sub-scripts whose self-judgment is that the target of the request or call is currently possible to be empty (nil). If the self-judged target has a value, then the call succeeds, whereas if the target chosen is null (nil), the call returns Null (NIL). Multiple requests or calls can be chained together to form a chain, if any one of the nodes is empty (nil) will cause the entire chain to fail.
Type conversions are implemented in Swift using the IS and as operators.
Any and anyobject convert Swift to indeterminate type?? Two special types of aliases are available: 1. Anyobject can represent instances of any class type. 2. Any can represent any type except the method type (function types).
Extended
The extension in Swift can be: 1. Add calculated properties and evaluate static properties 2. Define instance methods and type Method 3. ?? For the new constructor 4. Define subscript 5. Define and use the new nested type 6. Make an existing type conform?? An interface
If you define an extension to add new functionality to an existing type, this new feature is available for all existing instances of that type, even if they are defined earlier in your extension.
Note: The extension can add new computed properties, but you cannot add storage properties or add property observers to an existing attribute.
The Protocol (protocol) is used to unify the names of methods and properties without implementing any functionality. A protocol can be implemented by classes, enumerations, structs, classes, enumerations, and structs that meet the requirements of a protocol, which is known as the compliance of the Protocol.
When implementing a protocol with a class, use the Class keyword to represent the property as a class member, and when implementing the protocol with a struct or enumeration, the static keyword is used to represent:
The protocol method supports variable-length parameters (variadic parameter), and does not support default parameters (defaults parameter).
When using class to implement the Mutating method in the protocol, it is not necessary to write the mutating keyword, and the mutating keyword must be written when implementing the Mutating method in the protocol with the struct.
The protocol itself does not implement any functionality, but you can use it as a type. Usage Scenario: 1. Returns a value of type 2 as a parameter type in a function, method, or constructor. As a constant, a variable, a property of type 3. As an array, an element type in a dictionary or other container
A delegate is a design pattern that allows a class or struct to delegate to other types the functions that require them to be responsible. The implementation of the delegate pattern is simple: Define the protocol to encapsulate the functions and methods that need to be delegated, so that their followers have these delegated functions and methods. Can the delegate mode be used to respond to specific actions or to receive external data sources?? Data sources, without having to know the type of the external data source.
When a type has implemented all of the requirements in the agreement without declaring it, the Protocol declaration can be supplemented by an extension:
The protocol composition does not generate a new protocol type, but instead makes multiple protocols into a temporary protocol that is invalidated immediately after it is out of range.
@objc is used to indicate that the protocol is optional, it can also be used to represent code that is exposed to objective-c, and @objc protocol is only valid for classes, so the consistency of the protocol can only be checked in the class
Note: An optional protocol can only take effect in an agreement that contains a @objc prefix. And the @objc protocol can only be followed by class.
The Swaptwovalues function and the Stack type can be applied to any type, but sometimes it is mandatory to constrain the use of types on generic functions and generic types to?? Specific types are very useful. A type constraint specifies a type parameter that must inherit from the specified class, or follows a specific protocol or protocol composition.
Swift Reading Records