Swift开发学习
Swift语言
基本类型
使用 let
创建一个常量,var
创建一个变量。
1 | var myVar = 100 |
每个常量和变量在Swift中都有一个类型,但是不需要显式地把类型写出来。当你声明一个常量或变量的时候,提供给这个常量或变量一个值,让编译器去推断它的类型。
如果初始值提供不了足够的信息(或没有初始值),那么就需要在变量名之后为其指定类型,中间通过冒号分隔。
1 | let implicitIntrger = 70 |
如果你需要进行类型转换,就显式声明:
1 | let label = "The width is " |
还有一种更简单的方法:
1 | let apple = 3 |
使用三引号(“””)表示占用多行字符串:
1 | let quotation = """ |
使用 []
创建数组和字典:
1 | var list = ["A", "B", "C"] //字符也要用"",因为是作为String类型的 |
向数组中添加元素时,数组自动增长:
1 | list.append("D") |
创建空数组或空字典:
1 | let empArr: [String] = [] |
如果数据类型可以被推断,只需简单地写成:
1 | empArr = [] |
条件控制
使用 if
和 switch
来创建条件语句,使用 for-in
, while
和 repeat-while
创建循环。条件加不加括号都可以,但是后面的内容必须用花括号括起来。
1 | let scores = [75, 43, 103, 87, 12] |
这里注意,条件必须是显式的布尔表达式,像C/C++里的 if(score)
是行不通的,而是要写为 if score != 0
。
在if语句中使用可选绑定来检查可选类型是否有值:
1 | var optionalName: String? = "John Appleseed" |
实际上,当optionalName = nil时,if的条件为false。其实很好理解,就是先让name等于optionalName,然后判断name是不是nil。An optional value either contains a value or contains nil
to indicate that a value is missing. Write a question mark (?
) after the type of a value to mark the value as optional.
Another way to handle optional values is to provide a default value using the ??
operator. If the optional value is missing, the default value is used instead.
1 | let nickname: String? = nil |
Switches support any kind of data and a wide variety of comparison operations—they aren’t limited to integers and tests for equality.
1 | let vegetable = "red pepper" |
After executing the code inside the switch case that matched, the program exits from the switch statement. Execution doesn’t continue to the next case, so you don’t need to explicitly break out of the switch at the end of each case’s code.
You use for
-in
to iterate over items in a dictionary by providing a pair of names to use for each key-value pair. Dictionaries are an unordered collection, so their keys and values are iterated over in an arbitrary order.
1 | let interestingNumbers = [ |
Use while
to repeat a block of code until a condition changes. The condition of a loop can be at the end instead, ensuring that the loop is run at least once.
1 | var n = 2 |
You can keep an index in a loop by using ..<
to make a range of indexes.
1 | var total = 0 |
Use ..<
to make a range that omits its upper value, and use ...
to make a range that includes both values.
1 | var total = 0 |
函数和方法
函数声明可以包含0个或者多个参数,格式如name:Type。这些参数是额外的信息,当你去调用方法的时候,你必须把这些额外的信息传递进去。另外,函数有可选的返回类型,格式如:->返回类型,这表明这个函数返回的结果。函数的视线写在大括号({})中。
1 | func greet(person: String, day: String) -> String { |
By default, functions use their parameter names as labels for their arguments. Write a custom argument label before the parameter name, or write _
to use no argument label.
1 | func greet(_ person: String, on day: String) -> String { |
Use a tuple to make a compound value—for example, to return multiple values from a function. The elements of a tuple can be referred to either by name or by number.
1 | func calc(scores: [Int]) -> (min: Int, max: Int, sum: Int) { |
Functions can be nested. Nested functions have access to variables that were declared in the outer function. You can use nested functions to organize the code in a function that’s long or complex.
1 | func returnFifteen() -> Int { |
Functions are a first-class type. This means that a function can return another function as its value.
1 | func makeIncrementer -> ((Int) -> Int) { |
A function can take another function as one of its arguments.
1 | func hasAnyMatches(list: [Int], condition: (Int) -> Bool) -> Bool { |
Functions are actually a special case of closures: blocks of code that can be called later. The code in a closure has access to things like variables and functions that were available in the scope where the closure was created, even if the closure is in a different scope when it’s executed—you saw an example of this already with nested functions. You can write a closure without a name by surrounding code with braces ({}
). Use in
to separate the arguments and return type from the body.
1 | var numbers = [20, 19, 7, 12] |
map: Returns an array containing the results of mapping the given closure over the sequence’s elements. |
---|
Declarationfunc map<T>(_ transform: (Int) throws -> T) rethrows -> [T] |
DiscussionIn this example, map is used first to convert the names in the array to lowercase strings and then to count their characters.let cast = ["Vivien", "Marlon", "Kim", "Karl"] let lowercaseNames = cast.map { $0.lowercased() } // 'lowercaseNames' == ["vivien", "marlon", "kim", "karl"] let letterCounts = cast.map { $0.count } // 'letterCounts' == [6, 6, 3, 4] |
Parameterstransform A mapping closure. transform accepts an element of this sequence as its parameter and returns a transformed value of the same or of a different type.- No description. |
ReturnsAn array containing the transformed elements of this sequence. |
You have several options for writing closures more concisely. When a closure’s type is already known, such as the callback for a delegate, you can omit the type of its parameters, its return type, or both. Single statement closures implicitly return the value of their only statement.
1 | let mappedNumbers = numbers.map({ number in 3*number }) |
You can refer to parameters by number instead of by name—this approach is especially useful in very short closures. A closure passed as the last argument to a function can appear immediately after the parentheses. When a closure is the only argument to a function, you can omit the parentheses entirely.
1 | let sortedNumbers = numbers.sorted { $0 > $1 } |
对象与类
Use class
followed by the class’s name to create a class. A property declaration in a class is written the same way as a constant or variable declaration, except that it’s in the context of a class. Likewise, method and function declarations are written the same way.
1 | class Shape { |
Create an instance of a class by putting parentheses after the class name. Use dot syntax to access the properties and methods of the instance.
1 | var shape = Shape() |
Use init:
1 | class NamedShape { |
Override:
1 | class Square: NamedShape { |
1 | class Circle: NamedShape { |
getter and a setter:
1 | class EquilateralTriangle: NamedShape { |
If you don’t need to compute the property but still need to provide code that’s run before and after setting a new value, use willSet
and didSet
. The code you provide is run any time the value changes outside of an initializer. For example, the class below ensures that the side length of its triangle is always the same as the side length of its square.
1 | class TriangleAndSquare { |
Optional value:
1 | let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square") |
枚举和结构体
Use enum
to create an enumeration. Like classes and all other named types, enumerations can have methods associated with them.
1 | enum Rank: Int { |
By default, Swift assigns the raw values starting at zero and incrementing by one each time, but you can change this behavior by explicitly specifying values. In the example above, ace
is explicitly given a raw value of 1
, and the rest of the raw values are assigned in order. You can also use strings or floating-point numbers as the raw type of an enumeration. Use the rawValue
property to access the raw value of an enumeration case.
Use the init?(rawValue:)
initializer to make an instance of an enumeration from a raw value. It returns either the enumeration case matching the raw value or nil
if there’s no matching Rank
.
1 | if let convertedRank = Rank(rawValue: 3) { |
Summary: A half-open interval from a lower bound up to, but not including, an upper bound. |
---|
Declarationstruct Range<Bound> where Bound : Comparable |
DiscussionYou create a Range instance by using the half-open range operator (..< ).let underFive = 0.0..<5.0 You can use a Range instance to quickly check if a value is contained in a particular range of values. For example:underFive.contains(3.14) // true underFive.contains(6.28) // false underFive.contains(5.0) // false``Range instances can represent an empty interval, unlike ClosedRange .let empty = 0.0..<0.0 empty.contains(0.0) // false empty.isEmpty // true Using a Range as a Collection of Consecutive ValuesWhen a range uses integers as its lower and upper bounds, or any other type that conforms to the Strideable protocol with an integer stride, you can use that range in a for -in loop or with any sequence or collection method. The elements of the range are the consecutive values from its lower bound up to, but not including, its upper bound.for n in 3..<5 { print(n) } // Prints "3" // Prints "4" Because floating-point types such as Float and Double are their own Stride types, they cannot be used as the bounds of a countable range. If you need to iterate over consecutive floating-point values, see the stride(from:to:by:) function. |
Most app UIs are very visual experiences, so most accessibility work focuses on VoiceOver — a screen reader that lets people with low to no vision use Apple devices without needing to see their screens. VoiceOver reads out information to users about your app’s UI elements. It’s up to you to make sure this information helps users interact efficiently with your app.
协议和扩展
使用 protocol
声明一个协议:
1 | protocol ExampleProtocol { |
类、枚举和结构都可以采用协议:
1 | class SimpleClass: ExampleProtocol { |
本文作者 : preccrep
原文链接 : https://preccrep.github.io/2021/07/05/Swift%E5%BC%80%E5%8F%91%E5%AD%A6%E4%B9%A0/
版权声明 : 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!