美文网首页
Swift 中的变量、常量、类型

Swift 中的变量、常量、类型

作者: _浅墨_ | 来源:发表于2021-05-01 16:33 被阅读0次

    a good building needs a good foundation

    变量、常量、类型

    变量是存储特定类型值的临时容器:

    var count: Int
    var shouldRemind: Bool
    var text: String
    var list: [ChecklistItem]
    
    • Double,与 Float 相似,但精度更高。比如可以使用 Doubles 来存储经纬度。

    • Character,字符。String 就是字符的集合。

    • UInt,Int 变体。U 代表无符号,表示数据类型只能包含正值。之所以称为无符号,是因为数字前面不能带有负号(-)。 UInt 可以存储 0 到 18 位数之间的数字,但不能存储负数。

    • Int8,UInt8,Int16,UInt16,Int32,UInt32,Int64,UInt64。这些都是 Int 的变体。区别在于它们用于存储的字节数。字节越多,它们可以存储的值越大。实际上,我们经常使用 Int,在 64 位平台上它使用 8 个字节存储数据,并且最多可以容纳大约 19 位数字的正数和负数。

    • CGFloat,它实际上不是 Swift 类型,而是 iOS SDK 定义的类型。这是一个小数点数字,例如 Float 和 Double。由于历史原因,在整个 UIKit 中都将其用于浮点值。 (“ CG”前缀代表Core Graphics框架)

    Swift 对类型校验非常严格,比其它许多语言都严格。如果变量的类型为 Int,则不能赋值给它 Float 类型。

    即使两种类型都代表某种类型的数字,Swift 都不会自动在不同的数字类型之间进行转换。

    eg.

    var i = 10
    var f: Float
    f = i         // error
    f = Float(i)  // OK
    

    创建新变量时,我们不必总是指定类型。如果给变量一个初始值,Swift 将使用类型(type inference)推断来自动确定该变量的类型:

    var i = 10              // Int
    var d = 3.14            // Double
    var b = true            // Bool
    var s = "Hello, world"  // String
    

    如果使用具有与实例变量同名的局部变量,则可能引起混淆。当你调用那个变量时,你得到的可能并不是你想要的那个值,代码一多,你自己可能都分不清哪个是哪个了:

    class MyObject {
      var count = 7      // an instance variable
    
      func myMethod() {
        var count = 42   // local variable “hides” instance variable
        print(count)     // prints 42
      }
    }
    

    一些开发者喜欢在实例变量名称的前面加下划线(_),以避免出现此问题:比如实例变量写成_count 而不是 count。还有一种方法是,当访问实例变量时使用关键字 self:

      func myMethod() {
        var count = 42
        print(self.count)   // prints 7
      }
    
    常量 Constants

    有时,我们将计算或方法调用的结果存储到临时容器中,此后该值将永远不会更改,在这种情况下,我们最好使用常量而不是变量:

    let pi = 3.141592
    let difference = abs(targetValue - currentValue)
    let message = "You scored \(points) points"
    let image = UIImage(named: "SayCheese")
    

    提示:一个大牛的建议是,90%的情况下使用 let 都是正确的解决方案。如果使用 let 发现错误,Swift 编译器会警告我们正在尝试更改常量。这种情况下,我们再将 let 更改为 var。

    值类型(Value types) vs 引用类型(reference types)

    当使用基本类型(例如整数和字符串)时,使用 let 创建的常量一旦被赋予值就无法更改:

    let pi = 3.141592
    pi = 3                // not allowed
    

    但是,对于引用类型(reference types)的对象,只有对象的变量(如下面示例中的 item)是常量。对象本身仍然可以更改:

    let item = ChecklistItem()
    item.text = "Do the laundry"
    item.checked = false
    item.dueDate = yesterday
    
    

    但是 item 变量不可更改:

    let anotherItem = ChecklistItem()
    item = anotherItem   // cannot change the reference
    

    定义为 class 的对象是引用类型,而定义为 struct 或 enum 的对象是值类型。这意味着 iOS SDK 中的大多数对象都是引用类型,但是 Swift 语言中内置的内容(例如 Int,String 和 Array)都是值类型。

    集合 Collections

    数组存储对象列表,它包含的对象是按顺序排序的,我们可以通过索引检索它们。

    // An array of ChecklistItem objects:
    var items: Array<ChecklistItem>
    
    // Or, using shorthand notation:
    var items: [ChecklistItem]
    
    // Making an instance of the array:
    items = [ChecklistItem]()
    
    // Accessing an object from the array:
    let item = items[3]
    

    我们可以将数组写为 Array<Type> or [Type] 。第一个是正式写法,第二个是“语法糖”(syntactic sugar),它更容易阅读。 与其它语言不同,在 Swift 中,不能写为 Type [],类型名称应放在方括号内。

    词典(dictionary)存储键值对。一个对象(通常是字符串)是检索另一个对象的键。

    // A dictionary that stores (String, Int) pairs, for example a
    // list of people’s names and their ages:
    var ages: Dictionary<String, Int>
    
    // Or, using shorthand notation:
    var ages: [String: Int]
    
    // Making an instance of the dictionary:
    ages = [String: Int]()
    
    // Accessing an object from the dictionary:
    var age = dict["Jony Ive"]
    

    从字典中检索对象的方法与从数组中读取的表示法非常相似,它们都使用 [] 括号。为了索引数组,我们始终使用正整数作为 key ,但是对于字典,通常使用字符串。

    也有其它类型的集合,但是数组和字典是最常见的集合。

    泛型 Generics

    数组和字典被称为泛型,这意味着它们与存储在这些集合中的对象的类型无关。

    我们可以拥有一个 Int 对象数组,也可以具有一个 String 对象数组,或者实际上是任何类型的对象数组,甚至还有其他数组的数组。

    因此,必须先指定要存储在数组中的对象的类型,然后才能使用它,所以,我们不能这样写:

    var items: Array  // error: should be Array<TypeName>
    var items: []     // error: should be [TypeName]
    

    在 [] 括号内或 Array 一词之后 <> 的括号内,应始终有一个类型声明。如果您以前开发 Objective-C,请注意 OC 中的 <> 的含义与此处完全不同。

    对于字典,则需要提供两个类型名称:一个标识键的类型,一个标识值的类型。

    Swift 要求所有变量和常量都有一个值。我们可以在声明变量或常量时默认指定一个值,也可以通过在 init 方法内为其分配一个值。

    可选变量 Optionals

    有时,使用无值的变量会很有用,在这种情况下,我们需要将其声明为可选变量:

    var checklistToEdit: Checklist?
    

    我们不能立即使用此变量,而应该首先测试它是否具有值。这称为可选解包(unwrapping the optional):

    if let checklist = checklistToEdit {
      // “checklist” now contains the real object
    } else {
      // the optional was nil
    }
    

    在使用字典中的值之前,您需要先使用 if let 将其解包:

    if let age = dict["Jony Ive"] {
      // use the value of age
    }
    

    如果我们确定字典中肯定包含给定的键,则还可以使用强制解包(force unwrapping)来读取相应的值:

    var age = dict["Jony Ive"]!
    

    ! 告诉 Swift,“此值绝对不会为 nil” 。当然,如果为 nil ,则要 crash 了。

    强制解包(force unwrapping)的一种较安全的替代方法是可选链接( optional chaining)。例如,如果navigationController 属性为nil,以下内容将使 app crash:

    navigationController!.delegate = self
    

    但是这样不会:

    navigationController?.delegate = self
    

    如果 navigationController 为 nil,则将被忽略。相当于如下写法:

    if navigationController != nil {
      navigationController!.delegate = self
    }
    

    也可以使用感叹号代替问号来声明可选内容:

    var dataModel: DataModel!
    

    这样的值可能是不安全的,因为可以将其用作常规变量,而不必先对其进行拆包。

    使用这种方式,有时显得更方便。当我们在声明或 init() 中无法为变量提供初始值时,可以使用这种方式。

    但是,一旦给变量赋了一个值,就不应该再将其设置为 nil。 如果该值可以再次变为 nil,则最好使用带问号的 optional 。

    方法(Methods)和函数(functions)

    函数是独立的功能,与对象无关,需要显示的传递数据。
    方法与对象和类相关,依赖对象而调用,可以直接处理对象上的数据,也就是隐式传递数据。

    相关文章

      网友评论

          本文标题:Swift 中的变量、常量、类型

          本文链接:https://www.haomeiwen.com/subject/cgnarltx.html