Swift 浅谈

作者: 迎风起飞的猪 | 来源:发表于2018-05-04 09:52 被阅读14次
    空合并运算符
    var count:Int? = 10
    var value:Int
    
    /// 空合并运算符   第一个操作数必须为optional 如果不为nil责将进行拆包操作
    print(count ?? 0)  和 三目运算符 print(count != nil ? count! : 0) 结果一样
    
    结果为:10
    
    元祖
    /// 定义元祖
    var student:(String,Int,Float) = ("kakaxi",20,185.0)
    /// var stu:(name:String,age:Int,height:Float) = ("kakaxi",20,185.0)
    
    print(student.0)
    /// 将元祖进行分解   分解命名时使用_忽略命名字段
    var (name,_,_) = student
    
    print(name)
    
    结果为:kakaxi
    
    数组
    声明一个十个元素相同的数组
    var array = [String](repeating: "helllo world", count: 10)
    var arrList = [0,1,2,3,4]
    
    遍历数组的不同方式
    for item in arrList {
        print(item)
    }
    0
    1
    2
    3
    4
    
    for item in arrList.enumerated() {
        print(item)
    }
    (offset: 0, element: 0)
    (offset: 1, element: 1)
    (offset: 2, element: 2)
    (offset: 3, element: 3)
    (offset: 4, element: 4)
    
    for index in arrList.indices {
        print(arrList[index], separator:"")
    }
    
    0
    1
    2
    3
    4
    
    字典
    var dicts:Dictionary<Int,String>
    dicts = [1:"1",2:"2"]
    print(dicts)
    
    结果为:[2: "2", 1: "1"]
    
    Set
    集合(Set)
    
    集合(Set)特点:无序、唯一性、集合操作、快速查找。
    集合的数据显示和数组是一样的,所以必须显示的声明Set集合!不然!就是数组!
    // 初始化A、B、C三个集合
    var A:Set<String> = ["A", "B", "C", "D"]
    var B:Set<String> = ["C", "D", "E", "F"]
    var C:Set<String> = ["B", "B", "C"]
    
    // 上面Array、Dictionary动态初始化有四种,这里面只有两种
    var set1 = Set<String>()
    var set2:Set<String> = []
    
    // 集合的数量
    A.count
    // 集合第一个元素,因为集合的无序性,它的第一个元素没有意义
    A.first
    // 集合是否为空
    A.isEmpty
    // 向集合中插入一个元素
    A.insert("C")
    // 删除集合中的元素
    A.remove("C")
    // 判断集合中是否包含某个元素
    A.contains("A")
    // 遍历集合
    for index in A {
        index
    }
    
    运算符
    ///通过~=运算符来检查某个数字是否包含在范围中
    var range = 0...10
    print(range~=8)   true
    
    while和repeat-while 条件循环结构
    当 i 大于等于10的时候跳出循环   
    var i = 0
    while i < 10 {
        print("while",i)
        i += 1
    }
    
    repeat while 循环
    先执行循环体,在进行条件判断  和 OC 中的 do - while功能基本一致
    var j = 0
    repeat{
        print("while",j)
        j+=1
    }while j < 10
    
    流程跳转语句
    swift中提供的流程跳转语句主要有:continue、break、fallthrough、return、throw、guard
    
    continue: 语句用于循环结构中,作用为跳过本次循环,直接开始下次循环
    break:中断语句,也可以用于循环结构中,和continue语句不同,break语句会直接中断包含它的循环结构
    fallthrough:语句是swift中特有的一种流程控制语句,可以再中断语句中继续执行下面的语句
    
    例如:
    var i = 3
    switch i {
    case 1...3:
    print("switch")
        fallthrough
    default:
        print("default")
    }
    结果为:switch   default
    如果不加fallthrough 结果为:switch
    
    return: 用于返回结果值,或者用于提前结束无返回值类型的函数
    
    throw: 语句用于抛出异常,抛出的异常如果不进行捕捉处理,也会使程序中断
    
    guard - else: 是Swift2.0之后新加入的一种语法结构,Swift团队创造它的目的在于是代码结构和逻辑更加清晰
    
    func normalFunc(param:Int){
        if param <= 0 {
            return
        }
        print(param)
    }
    
    func fuardFunc(param:Int){
        guard param > 0 else {
            return
        }
        print(param)
    }
    
    
    声明函数
    有参数有返回值
    func compare(param1:Int,param2:Int)->Int {
        return param1 + param2
    }
    
    var add = compare(param1: 10, param2: 20)
    print(add)   30
    
    func search(searchID:Int)->(success:Bool,data:String){
        let reust = true
        let data = "数据实体"
        return(reust,data)
    }
    
    if search(searchID: 1000).success {
        print(search(searchID: 1000).data)   数据实体
    }
    
    函数的参数可以传也可以不传(设置默认值)
    func myFunc(param1:Int,param2:Int = 10)->Int {
        return param1 + param2
    }
    
    print(myFunc(param1: 8))   18
    print(myFunc(param1: 10, param2: 40))    50
    
    函数可以多参数,也可以多个不确定参数
    在参数后面添加...   
    func funcParams(param:Int...)->Int{
        var sum = 0
        for count in param {
            sum+=count
        }
        return sum
    }
    print(funcParams(param: 10,20,30,40,50))   150
    
    声明一个函数变量
    var addFunc:(Int...)->Int
    addFunc = funcParams
    print(addFunc(100,200))   300
    
    函数重载    相同方法名   参数返回值不同
    func addFunc(param1:Int,param2:Int)->Int{
        return param1 + param2
    }
    func addFunc(param1:Double,param2:Double)->Double{
        return param1 + param2
    }
    func addFunc(param1:String,param2:String)->String{
        return param1 + param2
    }
    
    闭包
    闭包标准结构:
    {(参数列表)-> 返回值 in 闭包体}
    首先闭包最外层由大括号包围,内部由闭包关键字in来进行分割,关键字in前面为闭包结构的参数列表和返回值,其书写规则与函数一致,in关键字后面为闭包体,用于实现具体功能
    
    let closures = {(param:Int)->Int in
        return param * param
    }
    
    自定义运算符
    prefix operator ++
    prefix func ++(param:Int)->Int
    {
        return param + 1
    }
    
    枚举
    enum Season {
        case spring
        case summer
        case autumn
        case winter
    }
    let season = Season.spring
    
    func switchFunc(){
        switch season {
        case .spring:
            print("spring")
        case .summer:
            print("summer")
        case .autumn:
            print("autumn")
        default:
            print("winter")
        }
    }
    
    switchFunc()   spring
    
    结构体
    swift 既可以声明属性也可以定义方法
    
    struct Car {
        var price:Int
        var brand:String
        var petrol:Int
        mutating func Drive(){
            if petrol > 0 {
                print("driving")
            }else{
                print("drived")
            }
        }
    }
    
    var car = Car(price: 100000, brand: "宝马", petrol: 10)
    car.Drive()   //  driving
    
    在创建类时,使用final关键字  其类不可以被继承  
    使用final声明属性时,其属性不可以被子类使用
    
    指定构造方法与遍历构造方法
    对于类来说,构造方法有指定构造方法和便利构造方法之分。 指定构造方法的官方名称为Designated,遍历构造方法为Convenience。
     指定构造方法不需要任何关键字修饰,便利构造方法需要使用Convenience关键字来修饰。
    关于指定构造方法和便利构造方法,Swift语言中有这样的规定:
    1.  子类的指定构造方法中必须调用父类的指定构造方法。
    2.  遍历构造方法中必须调用当前类的其他构造方法。
    3.  遍历构造方法归根结底要调用到某个指定构造方法。
    
    // 创建一个类作为基类
    class BaseClass {
        // 提供一个指定构造方法
        init() {
            print("baseClass Designted")
        }
        
        // 提供一个便利构造方法
        // 便利构造方法必须调用当前类中的其他构造方法,并最终调用到指定构造方法
        convenience init(param:String) {
            print("BaseClass Convenience")
            /// 进行指定构造方法的调用
            self.init()
        }
        
    }
    
    /// 创建一个BaseClass的子类
    class SubClass: BaseClass {
        // 覆写指定构造方法中必须调用父类的指定构造方法
        override init() {
            super.init()
        }
        
        // 提供两个便利构造方法
        convenience init(param:String) {
            // 最终调用到某个指定构造方法
            self.init()
        }
        
        convenience init(param:Int) {
            // 调用一个便利构造方法
            self.init(param: "Swift")
            
        }
    }
    
    var obj = SubClass()
    print(obj)     // baseClass Designted   conditation.SubClass
    
    引用计数
    Swift中语言中的数据传递分为两种,即值类型的数据传递和引用类型的数据传递
    
    对于值类型的数据传递,其采用的是完全复制的原理,因此原数据的销毁与内存的释放并不会影响新数据,
    新数据占用的内存会在它本身作用域结束时释放。
    
    if true {
        var a = 0
        if true {
            var b = 1
            a = b
        }
        // 此时变量b所占内存被释放
    }
    // 此处变量a所占内存被释放
    
    引用数据类型的数据传递就复杂一些,我们知道引用类型的数据传递并不会完全复制原数据,
    而是通过要引用的方式对原数据进行访问,因此无论一个类实例被多少个变量所承载,其真正所访问的内存都是同一个地方。
    if true {
        var a = TestClass()
        if true {
            var b = a
        }
        // 此处变量b已经不存在,但是TestClass实例依然占用内存, 没有释放
    }
    // 此处变量a已经不存在,也没有其他变量引用TestClass实例,该实例将调用deinit方法,其所占内存被释放
    
    循环引用及其解决方法
    循环引用一直是初级开发者编程的噩梦。对类实例进行不当的引用会造成内存泄露,内存泄露积累到一定程度就会给应用程序带来灾难性的后果。
    
    class ClassOne{
        deinit {
            print("ClassOne deinit")
        }
    }
    
    class ClassTwo{
        /// ClassTwo 类中有一个ClassOne类的属性
        var classOne:ClassOne?
        init(classOne:ClassOne?) {
            self.classOne = classOne
        }
        deinit {  /// 析构方法  相当于OC中的dealloc
            print("ClassTwo deinit")
        }
    }
    
    var classOne:ClassOne? = ClassOne()
    var classTwo:ClassTwo? = ClassTwo(classOne: classOne)
    /// 此时ClassTwo类中的classOne属性依然在引用classOne实例,因此classOne实例所占内存没有释放
    classOne = nil
    /// 此时classTwo 被释放,classTwo中的属性也都被释放,不在有谁引用classOne,classOne实例也被释放
    classTwo = nil
    
    结果为:
       ClassTwo deinit
       ClassOne deinit   
    
    **上述代码十分健康,两个类都被释放**
    
    
    class ClassOne{
        var cls:ClassTwo?
        deinit {
            print("ClassOne deinit")
        }
    }
    
    class ClassTwo{
        /// ClassTwo 类中有一个ClassOne类的属性
        var cls:ClassOne?
        init(cls:ClassOne?) {
            self.cls = cls
        }
        deinit {
            print("ClassTwo deinit")
        }
    }
    
    var classOne:ClassOne? = ClassOne()
    var classTwo:ClassTwo? = ClassTwo(cls: classOne)
    classOne?.cls = classTwo
    
    classTwo = nil
    classOne = nil
    
    **上述两个类都没有被释放,代码中已将将classOne和classTwo都置为nil,但其所占据的内存将无法释放,这便是循环引用最常见的场景**
    
    Swift 语言中提供了弱引用关键字(weak)来处理这样的问题;weak 关键字的作用是在使用这个实例的时候并不保有次实例的引用
    (普通的引用类型数据在传递时会使实例的引用计数加1,使用weak关键字修饰的引用类型数据在传递时不会使引用计数加1)
    
    将ClassOne中的属性 使用weak 声明:
      weak var cls:ClassTwo?
    结果为:
         ClassTwo deinit
         ClassOne deinit   
    
    扩展:
    **
    弱引用还有一个特点,其职能修饰Optional类型的属性,被弱引用的实例释放后,这个属性会被自动设置为nil,那么问题来了,如果开发中使用到的属性是非Optional值类型的,又恰巧出现了循环引用的场景,开发者该如何处理呢?其实Swift语言中还提供了一个关键字(unowned 无主引用)来处理非Optional值类型属性的循环引用问题。
    **
    

    相关文章

      网友评论

        本文标题:Swift 浅谈

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