Swift(2)

作者: 永恒守护__刘鹏辉 | 来源:发表于2016-04-17 22:19 被阅读35次

    可选类型(?)

    隐式解析可选类型(!)

    结构体

    协议

    扩展

    闭包

    demo截图.png
    import Foundation
    
    //MARK:--------------------Swift中的"?"和"!"--------------------
    /*
      1. 在swift中可选类型(optionals),用"?"表示,用于处理值缺失的情况,表示"这儿有一个值,且它等于x"或者表示"这儿没有值"
      2. 可选类型是一个包含两种情况的枚举值,None和Some,用来表示可能有值或可能没有值
         2.1. nil就是Optional.None,当声明一个可选变量或者可选属性的时候,没有提供初始值,它的值默认为nil
         2.2. 非nil就是Optional.Some
      3. 任何类型都可以明确地声明为可选类型,当声明一个可选类型时,要确保用括号给"?"操作符一个合适的范围。例如:声明可选整数数组,应该写成"(Int[])?",如果写成"Int[]?",就会报错
    */
    
    // 定义一个可选类型:以下两种声明方式是相等的
    var Optional_1 : Int?// 在数据类型和"?"之间没有空格
    var Optional_2 : Optional<Int>
    var intNumber : Int? = 100
    // 打印出来以后是一个Optional类型的值
    print(intNumber)
    // 如果要取到100,必须对可选类型强制解析
    print(intNumber!)
    
    // 4. "!":用来强制解析,如果可选类型实例包含一个值,可以用"!"来访问这个值
    // 注意:可选类型分为有值和没值,如果可选类型的变量没值时对其强制解包,程序就会崩溃,如下面的程序:
    /*
    var Number : Int?
    print(Number!)
    */
    
    /*
       5. 自动解析(隐式解析)
         5.1 可以在声明可选变量时,使用"!"来替换"?",这样可选变量在使用时就不需要再加一个"!"来取值了,它会自动解析
         5.2 隐式解析可选类型,和可选类型一样,都是有值和没有值(nil)两种结果
         5.3 区别是赋值时,隐式解析可选类型不需要再强制解析
         5.4 注意:隐式解析可选类型的变量没有值时,程序一样会崩溃
    */
    var IntNumberOne : Int! = 10
    print(IntNumberOne)
    
    /*
       6. 可选绑定
          6.1 可选绑定:用来判断可选类型是否包含值,如果包含就把值赋给一个临时常量或者临时变量
          6.2 可选绑定可以用在if和while语句中来对可选类型的值进行判断,并把它赋给一个常量或者变量
          6.3 如果不确定可选类型是否有值,用可选绑定,不需要对可选类型强制解析
    */
    var intNumberTwo:Int?
    if var intNumberThree = intNumberTwo
    {
        print("可选类型有值 = ", intNumberThree)
    }
    else
    {
        print("可选类型无值")
    }
    //MARK:----------------------Swift中的结构体---------------------
    /*
     1. 与C和OC不同的是:
        1.1 结构体不需要包含实现文件和接口文件
        1.2 结构体允许我们创建一个单一文件,且系统会自动生成该结构体用于面向其他代码的外部接口
     2. 结构体总是通过被复制的方式在代码中传递,因此,原本结构体的值是不可修改的
     3. 结构体的应用
        3.1 在代码中,可以使用结构体定义自定义数据类型
        3.2 按照通用的准则,当符合一条或者多条以下条件时,请考虑构建结构体
            3.2.1 结构体的主要目的是用来封装少量相关简单数据
            3.2.2 有理由预计一个结构体实例在赋值或者传递时,封装的数据将会被拷贝而不是引用
            3.2.3 任何结构体中存储的值类型属性,也将会被拷贝,而不是被引用
            3.2.4 结构体不需要去继承另一个已存在类型的属性或者行为
     4. 例如:
        4.1 几何形状的大小,封装一个width属性和height属性,两者均为double类型
        4.2 一定范围的路径,封装一个start属性和length属性,两者均为    Int类型
        4.3 三维坐标系内的一点,x,y,z属性,三者均为double类型
    */
    // 格式:struct + 结构体名字 + {结构体实现}
    
    struct Frame
    {
        // 存储属性 就是类或结构体里定义的变量(或常量)
        var x : Float
        var y : Float
        var width : Float
        var height : Float
        
        // 计算属性 除存储属性外,类、结构体和枚举可以定义计算属性.计算属性不直接存储值,而是提供一个getter和一个可选的setter,来间接获取和设置其他属性或变量的值
        // get方法 :在属性类型后面添加{},使用get关键字声明和实现get方法
        // set方法 :同上
        // set方法不可以单独出现,必须搭配着get方法才可以出现,但是get方法可以单独出现
        var centerX : Float {
            get{
                return x + width / 2
            }
        }
        var centerY : Float {
            get{
                return y + height / 2
            }
        }
        // 结构体属性  只能通过结构体去调用
        static var myStruct = "我是一个结构体属性"
        // 结构体中可以声明和实现成员方法即函数
        func sayHI()
        {
            print("你好,我是一个方法")
        }
        // 结构体的类方法:方法前用static修饰,只能由结构体调用
        static func sayHello()
        {
            print("hello")
            // 结构体类方法中只能调用结构体属性
            print(self.myStruct)
        }
        // 结构体自带有初始化方法,但是也可以重写
        init(x newX : Float, y newY : Float, width newWidth : Float, height newHeight : Float)
        {
            x = newX
            y = newY
            width = newWidth
            height = newHeight
        }
    }
    // 调用结构体属性(因为是结构体属性,所以只能由结构体调用,不能由对象调用)
    print(Frame.myStruct)
    // 调用结构体的类方法
    Frame.sayHello()
    
    // 结构体有自带的构造体方法和初始化方法
    // 以下这两种创建对象的方式没区别
    var frame : Frame = Frame(x: 10, y: 10, width: 100, height: 100)
    var frame1 : Frame = Frame.init(x: 10, y: 10, width: 100, height: 100)
    print(frame.centerX)
    // 调用Frame结构体的成员方法
    frame1.sayHI()
    
    //MARK:-----------------------Swift中的类-----------------------
    // 类是人们构建代码所用的一种通用且灵活的构造体。我们可以使用与结构体完全相同的语法规则来为类定义属性(常量、变量)和添加方法
    /*
     1. swift中,类和结构体有很多共同点
        1.1 定义属性,用于存储值
        1.2 定义方法,用于提供功能
        1.3 定义构造器,用于提供初始化值
        1.4 遵循协议,用来对某个类提供标准功能
        1.5 通过扩展,用来增加默认实现的功能
     2. 与结构体相比,又有其他附加功能
        2.1 继承,允许一类继承另一个类的特征
        2.2 类型转换允许在运行时检查和解释一个类实例的类型
        2.3 引用计数:允许对一个类多次引用
    */
    // 值类型:该类型的每个实例持有数据的副本,并且该副本对于每个实例来说是独一无二的一份,比如结构体(struct)、枚举(enum)、元组(tuple)都是值类型
    /*
    值类型的使用场景:
        当使用"=="运算符比较数据的时候
        想单独复制一份实例数据的时候
        在多线程环境下操作数据的时候
    */
    /*
    // 创建一个StructObject结构体变量
    struct StructObject
    {
        var data : Int = -1
    }
    var a = StructObject()
    // b是a的拷贝
    var b = a
    // 更改a的数据,b的不受影响
    a.data = 42
    print("\(a.data), \(b.data)")
    */
    
    // 引用类型:该类型的实例共享数据唯一的一份副本(在native层面说的话,就是该类型的每个实例都指向内存中的同一个地址),比如类(class)就是引用类型
    
    /*
    // 创建一个ClassObject类
    class ClassObject
    {
        var data : Int = -1
    }
    var a = ClassObject()
    // 将a变量的值赋值给b,其实是一个引用的过程
    var b = a
    // a的数据改变了,但是b也发生了改变
    a.data = 42
    print("\(a.data), \(b.data)")
    */
    
    /*
    使用值类型的情形:
       使用 == 运算符比较实例数据的时候
       单独复制一份实例数据的时候
       在多线程环境下操作数据的时候
    使用引用类型(比如class)的情形:
       使用 == 运算符判断两个对象是否引用同一个对象实例的时候
       当上下文需要创建一个共享的、可变的对象时
    */
    
    // 类的定义格式:class + 类名 + {类的实现}
    class Person
    {
        // 当给一个类写属性的时候,这个属性如果没有初值那就需要是可选类型
        // 存储属性
        var name : String?
        var gender : String?
        var age : Int?
        
        // 计算属性
        var width : Float {
            get{
                return 100
            }
            set{
                // set方法中的newValue表示新的值
                self.width = newValue
            }
        }
        // 此处static修饰的是类属性
        static var hooby : String? = "大播"
        // 此处static修饰的是类方法,这时类方法可以调用static修饰的类属性
        static func sayMy()
        {
            print(hooby!)
        }
        // 没用static修饰的类方法不能调用static修饰的属性
        func sayHI()
        {
            print("你好啊\(self.width)")
            name = "污唐"
        }
        // 声明类方法时,static和class都可以修饰类方法,区别在于class修饰的类方法可以被子类重写。class修饰的类方法可以调用static修饰的属性,但是class自己不能修饰属性
        class func saySaWaDiKa()
        {
            print(hooby!)
        }
        // 类的构造方法  系统没有自带,需要自己写了才能调用
        init(name newName : String, gender newGender : String, age newAge : Int)
        {
            name = newName
            gender = newGender
            age = newAge
        }
    }
    // 创建实例对象的两种方式(这两种方式没区别):
    var person : Person = Person.init(name: "王梁", gender: "女", age: 8)
    var person1 : Person = Person(name: "鸭王", gender: "女", age: 3)
    // 调用实例对象的属性
    print(person.age!)
    // 实例person1调用实例方法sayHI()
    person1.sayHI()
    // 类Person调用static修饰的类方法sayMy()
    Person.sayMy()
    // 类Person调用class修饰的类方法saySaWaDiKa()
    Person.saySaWaDiKa()
    
    class student : Person
    {
        var number : NSString?
        
        // 重写父类的方法 :需要添加override修饰
        override func sayHI()
        {
            print("重写方法")
        }
        // 重写父类的init构造方法
         override init(name newName : String, gender newGender : String, age newAge : Int)
        {
            super.init(name: newName, gender: newGender, age: newAge)
            name = newName
            gender = newGender
            age = newAge
        }
        // 在重新创建一个init方法的时候 还是需要super.init
        init(number newNumber : NSString)
        {
            super.init(name: "张三", gender: "男", age: 1)
            number = newNumber
        }
    }
    var stu1 : student = student.init(name: "小明", gender: "男", age: 9)
    stu1 = student.init(number: "007")
    print(stu1.name!,stu1.number!)
    stu1.sayHI()
    
    //MARK:----------------------Swift中的协议-----------------------
    /*
      协议定义了一个蓝图,规定了用来实现某一特定工作或者功能所必需的方法和属性
      类、结构体或枚举类型都可以遵循协议,并提供具体实现来完成协议定义的方法和功能
      任意能够满足协议要求的类型被称为遵循(conform)这个协议
    */
    
    // 声明协议
    // protocol声明的协议,表示Swift的协议,所有的方法都必须实现
    protocol myDelegate
    {
        // 协议方法
        func test()
        // 使用mutating修饰的函数,可以在结构体里面修改结构体的属性
        // 在协议里面使用mutating修饰的函数,在遵守协议的时候,类里面不能使用mutating修饰。但是在结构体里面,如果要修改属性的话必须用mutating修饰方法
        mutating func change()
    }
    // @objc修饰的协议表示这个协议是OC的协议,可以声明可选实现的函数,在函数名前面用optional修饰,这个函数就是可选实现的了
    @objc protocol newDelegate
    {
        optional func newTest()
        func newChange()
    }
    
    class Teacher : Person, myDelegate, newDelegate {
        // 必须实现的方法
        func test()
        {
            name = "111"
            print("aaa")
        }
        // 必须实现的方法
        @objc func newChange()
        {
            
        }
        // 必须实现的方法
        // 协议里面使用mutating修饰的函数,在类里面就是一个普通的函数
        func change()
        {
            name = "100"
        }
        // 可选实现的方法
        @objc func newTest()
        {
            
        }
    }
    let teacher :Teacher = Teacher(name: "a", gender: "b", age: 111)
    teacher.test()
    
    // @objc修饰的协议 结构体不能遵循
    struct myStruct : myDelegate
    {
        var name : String
        // 一般不能直接修改结构体里面的属性
        func test()
        {
            
        }
        // mutating修饰的方法里可以修改结构体的属性
        mutating func change()
        {
            name = "111"
        }
    }
    
    //MARK:----------------------Swift中的扩展-----------------------
    // extension + 类名(结构体名字) 可以对一个类或结构体扩展方法
    // extension不能扩展属性
    // extension也可以给类或结构体扩展协议方法 这个在开发的时候最有用
    
    extension Person : myDelegate // 给Person类扩展协议
    {
        // 实现协议里的方法
        func test()
        {
            
        }
        // 实现协议里的方法
        func change()
        {
            
        }
        // 给Person类扩展方法
        func eat()
        {
            
        }
    }
    extension Frame : myDelegate // 给Frame结构体扩展协议
    {
        // 实现协议里的方法
        func test()
        {
            
        }
        // 实现协议里的方法
        func change()
        {
            
        }
        // 给Frame结构体扩展新的方法
        func play()
        {
            
        }
    }
    
    //MARK:----------------------Swift中的闭包-----------------------
    /*
       * 闭包是自包含的函数代码块,可以在代码中被传递和使用。Swift中的闭包与C和Objective-C中的代码块(block)以及其他一些编程语言中的匿名函数比较相似。
       * 闭包可以捕获和存储其所在上下文中任意常量和变量的引用。这就是所谓的闭合并包裹着这些常量和变量,俗称闭包。Swift会为您管理在捕获过程中涉及到的所有内存操作。
       * 语法格式:
         {
            (参数) -> 返回值类型 in
            执行语句
         }
       * 注意:闭包的函数体部分由关键字in引入。该关键字表示闭包的参数和返回值类型定义已经完成,闭包函数即将开始。
    */
    
    // 使用闭包求两个Int型数的最大值
    // 声明一个闭包
    var maxValue : ((Int, Int) -> Int)
    
    // 实现闭包的第一种方式
    maxValue = {
        (a : Int, b : Int) -> Int in
        return a > b ? a :b
    }
    /*
       其中:
       * maxValue的类型是(Int, Int) -> Int
       * maxValue的值就是一个闭包:
          {
             (a : Int, b : Int) -> Int in
             return a > b ? a :b
          }
    */
    // 第二种方式实现闭包 省略参数类型和返回值
    maxValue = {
        a, b in
        return a > b ? a : b
    }
    // 第三种方式实现闭包 省略参数类型,省略返回值,省略return关键字
    maxValue = {
        a, b in
        a > b ? a : b
    }
    // 第四种方式 都省略了 使用$表示取第几个参数
    maxValue = {
        $0 > $1 ? $0 : $1
    }
    // 第五种 苹果推荐的格式
    maxValue = {
        (a, b) -> Int in
        return a > b ? a : b
    }
    print(maxValue(3,5))
    

    相关文章

      网友评论

          本文标题:Swift(2)

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