美文网首页
Swift数据类型至少要知道这些

Swift数据类型至少要知道这些

作者: _我和你一样 | 来源:发表于2019-03-01 18:12 被阅读0次

    可选型optional

    1. 可选型本质上是一个枚举类型enum
    enum Optional<T> {// The <T> is a generic like as in Array<T>
        case none
        case some(T)
    }
    

    以下两种写法是等价的

    let x:String? = nil
    ... is ...
    let y = Optional<String>.none
    
    let x:String? = "Hello"
    ... is ...
    let x = Optional<String>.some("Hello")
    
    // unwrap
    let y = x!
    ...is...
    switch x {
        case .some(let value):y = value
        case .none:// raise an excepiton
    }
    
    let x:String? = ...
    if let y = {
        // do someting with y 
    }
    ... is ...
    switch x {
        case .some(let y):// do something with y
        case .none:break
    }
    
    1. 可选型是可以链式传递的
    var display:UILabel?
    if let temp1 = display {
        if let temp2 = temp1.text {
            let  x = temp2.hashValue
            //...
        }
    }
    // 等价于 链式解包如果中间有一个为nil,返回的值为nil
    if let x = display?.text.hashValue // x is an Int
    let x = display?.text.hashValu // x is an Int?
    //因此在链式解包时使用?而不是!
    
    1. 可选默认值操作符??

      如果可选型解包值为nil,则赋予默认值

    let s: String? = ...
    if s != nil {
        display.text = s
    }else {
        display.text = ""
    }
    // 等价于
    display.text = s??""
    

    元组 tuple

    tuple is a grouping of values

    You can use it anywhere you can use a type.

    let x: (String,Int,Double) = ("Hello",5,0.85)// the tyoe of x is a tuple
    let (word,number,value) = x// this names the tuple emlements when accessing the tuple 当元组被访问时,命名元组内的元素
    print(word)// hello
    print(number)// 5
    print(value)// 0.85
    // 当元组被声明的时候也可以为元组元素命名 建议使用这种,tuple 可以通过点语法访问元组内的元素
    let y:(x:String,i:Int,v:Double) = ("Hello",5,0.85)
    print(y.x)
    print(y.i)
    print(y.v)
    // 可以使用下划线忽略元组中元素
    let (word,_,value) = x
    

    Range

    A range in swift is just tow end Points.

    A range can represent things like a selection in some text or a portion of an Array

    Range is generic(e.g. Range<T>), but T is restricted(e.g. comparable).

    类似于这种

    struct Range<T> {
        var startIndex:T
        var endIndex:T
    }
    

    CountableRange 包含的值可以迭代或者用下标访问

    创建Range有一种特殊的语法

    ..< 不包含上限。

    ...包含上限

    CountableRange 可以用for in 遍历

    // C-like : for (i = 0;i<20;i++)
    for i in 0..<20 {
        
    }
    // 浮点数不是countable的 对于 for(i=0.5;i<=15.25;i+=3) 是无法直接使用forin的,但是有一个通用的方法可以从浮点数创建一个CountableRange
    for i in stride(from:0.5,through:12.25,by:0.3){
        
    }
    

    数据结构 struct,enum,class

    相似点:

    语法声明相似

    class ViewController: ... {
        
    }
    
    struct Calculation {
        
    }
    
    enum Opration {
        
    }
    

    都可以拥有属性和方法

    func doit(agrx agri:Type)->ReturnValue{
        
    }
    var storedProperty =<initial value>(not enum)
    
    var computedProperty:Type {
        get{}
        set{}
    }
    

    初始化(not enum)

    init(arg1x arg1i:Type,arg2x arg2i:Type ...){
        
    }
    

    不同点:

    1. 只有class可以继承

    2. struct 和 enum是值(value)类型,而class是引用类型(inference)

    值类型(如struct,enum)特点如下:

    Copied when passed as an argument to a founction

    Copied when assigned to a different variable

    Immutable if assigned to a variable with let (function parameters are let)

    You must note any func that can mutate a struct/enum with the keyword mutating

    引用类型(如class)特点如下:

    Stored in the heap and reference counted(automatically)

    Constant Pointers to a class (let) still can mutate by calling methods and changing properties

    When passed as an argument, does note make a copy (just passing a pointer to same instance)

    参数名称

    对于所有的方法而言所有的参数都有一个内部名称和外部名称,

    内部名称是在方法内使用的局部变量

    外部名称是调用者调用方法时使用的名称

    如果不想让调用者使用外部名称,可以使用下划线忽略外部名称,

    如果只提供了一个参数名,这个参数名即是外部名称又是外部名称

    类型和方法都可以拥有方法和属性

    类型的方法和属性都需要使用static关键词修饰

    比如Double这个struct类型有一系列变量和方法在这个类型上

    比如访问 Double.pi 访问的不是实例的属性而是类型的属性

    属性观察

    可以通过willSet和didSet来观察属性值的更改。

    如果修改了一个结构体,也会包含这种变化

    var someStoredProperty:Int = 42 {
        willSet{newValue is the new value}
        didSet{oleValue is the old value}
    }
    // 继承的属性也可以观察 重新父类的属性和方法都需要使用关键词override
    override var inheritedProperty:String{
        willSet{newValue is the new value}
        didSet{oleValue is the old value}
    }
    // 架构体的变化也可以捕获
    var opertaions:Dictionary<String,Operation>=[...]{
        willSet{will be executed if an opreation is added/removed}
        didSet {will be executed if an opreation is added/removed}
    }
    

    懒加载

    使用lazy关键词修饰,这种变量只有在访问的时候才会初始化,可以通过执行闭包或者调用方法来创建一个对象

    lazy var brain = CalulatorBrain()
    lazy var someProperty:Type = {
        // construct the value of someProperty 
        return <the constructed value>
    }()
    lazy var myProperty = self.initialiedMyProperty()
    

    初始化

    1. 什么时候需要init方法

    init方法不是非常常见,因为

    • 属性可以使用=赋予默认值
    • 属性也可以使用可选型,这种情况下初始值为nil
    • 属性也可以使用懒加载

    因此,当上述方面不能满足时,需要初始化方法。

    1. 有些初始化方法不用自己写就可以使用
    • 基类的init()方法
    • 如果结构体没有初始化方法,会有默认的初始化方法包含所有的参数
    1. 在init方法中需要做什么

      当初始化完成之后,所有属性都应当有值(可选型可以为nil)

      在class中有两种初始化方法 convenience and designated

      1. a designated init must (and can only) call a designated init that is in its immediate supercalss
      2. you must initialize all properties introduced by your calss before calling a supercalss' init
      3. You must call a supercalss' init before you assign a value to an inherited property
      4. a convenience init must ( and can only) call an init in its own class
      5. a convenience init must call that init before it can set any property values
    2. 可以失败的初始化

    如果init声明为init?,它将返回一个可选型,初始化失败时为nil

    比如

    let image = UIImage(named:"foo")// image is an Optional
    

    类型转换

    可以使用as?来进行类型转换,尤其在有使用到Any类型,以及父类像子类转换时很常见

    断言

    可以使用assert在调试时帮助调试,

    assert(()->Bool,"message") 这个函数的参数时自动闭包,所以不需要{}

    条件为假时,给出后面的信息。

    当编辑为release版本时,断言会完全被忽略。

    相关文章

      网友评论

          本文标题:Swift数据类型至少要知道这些

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