• Swift


    1> 可选类型(?)和强制解包(!)

    在swift中,可选类型(?) 其根源是一个 枚举型,里面有 None 和 Some 两种类型。其实所谓的 nil 就是 Optional.None , 非 nil 就是 Optional.Some.

    可选类型是的数据如果不进行解包的话,它是一个 Optional 类型的数据,如果我们想要使用原来类型的数据,必须进行解包

    2> 可选绑定

    可选类型分为有值和没值,如果可选类型的变量没值时对其强制解包,程序就会崩溃,所以,强制解包是非常危险的
    如果不确定可选类型变量是否有值时,用可选绑定,不需要对可选类型强制解包

    3> 隐式解析可选类型(!)

    隐式解析可选类型和可选类型一样,都是 有值 和 没值(nil) 两种结果,区别是赋值时,隐式解析可选类型不需要强制解包。

     1 //MARK: - ?和 ! 的区别
     2 // ? 代表可选类型,其实质是一个枚举类型,里边有None和some两种类型,其实所谓的nil值相当于Optional.None,如果有值相当于Optional.Some
     3 // !有值,没值(nil)
     4 
     5 // !强制解包
     6 
     7 var num : Int? = 8
     8 // 如果对没值(nil)的变量进行强制解包的情况下会造成崩溃
     9 var num1 = num!
    10 print(num1)
    11 
    12 // 可选绑定,不用强制解包
    13 if var num2 = num {
    14     print(num2)
    15 }
    16 
    17 // !隐式解析可选类型:有值,没值(nil)
    18 
    19 // 如果强制解析没值的变量也会造成崩溃
    20 var intNum : Int! = 9
    21 var intNum1 = intNum
    22 print(intNum1)
    23 
    24 // 可选绑定
    25 if var intNum2 = intNum {
    26     print(intNum2)
    27 }

    2.结构体

    1> 概述

    Swift的结构体对比OC来说,可以添加初始化方法、可以遵守代理协议等
    声明一个结构体的格式:

    struct + 结构体的名字 + {

        声明成员变量等

    2> 声明一个结构体代码

     1 //MARK: - 结构体
     2 // 声明一个结构体
     3 struct Rect {
     4     // 声明结构体变量的属性(存储属性)
     5     var x:Float
     6     var y:Float
     7     var Float
     8     var height:Float
     9     //声明结构体属性,要使用static
    10     static var description:String?
    11     // 声明一个计算属性(是用来专门修改结构体变量属性的setter方法,和getter方法,其自身并没有存储功能)
    12     var centerX:Float {
    13         //set方法
    14         set{
    15             x = newValue
    16         }
    17         //get方法(必须得有)
    18         get{
    19             return x / 2
    20         }
    21     }
    22     var centerY:Float {
    23         //get方法
    24         get{
    25             return y / 2
    26         }
    27     }
    28     
    29     // 结构体中还可以声明方法
    30     // 声明一个结构体变量方法(相当于OC中的实例方法)
    31     func frameInfor(){
    32         print("X:(x),Y:(y),(width),height:(height)")
    33     }
    34     // 声明一个结构体方法(相当于OC中的类方法),static修饰
    35     static func infor(){
    36         print("这是结构体方法")
    37     }
    38     
    39 }
    40 
    41 //根据结构体去定义一个结构体变量
    42 var frame = Rect(x: 10, y: 10,  100, height: 100)
    43 //访问结构体变量中的属性
    44 // 注意:结构体变量的属性类型可以使用let去修饰,只不过访问的时候不能进行修改
    45 frame.x = 20
    46 print(frame.x)
    47 
    48 //如何访问结构体属性
    49 Rect.description = "我是结构体属性"
    50 print(Rect.description!)
    51 
    52 //怎么访问计算属性
    53 frame.centerX = 100  // 这句话相当于在调用centerX的setter方法
    54 let value = frame.centerX  // 这句话相当于在调用centerX的getter方法
    55 print(value)
    56 
    57 // 调用结构体变量方法  ******** 用变量名
    58 frame.frameInfor()
    59 // 调用结构体方法  ******** 用结构体名
    60 Rect.infor()

    3.类

    1> 概述

    类是人们构建代码所用的一种通用且灵活的构造体。我们可以使用与结构体完全相同的语法规则来为类定义属性(常量、变量)和添加方法。

    我们通过关键字class来定义类,并在一对大括号中定义它们的具体内容:

      class ClassName { 

          类的内部细节

      }

    2> 声明一个父类和子类的代码

     1 //MARK: - 类(class)
     2 class Person {
     3     var name : String?
     4     var age : Int?
     5     // 构造初始化方法
     6     init(name:String,age:Int){
     7         self.name = name
     8         self.age = age
     9     }
    10     // 自定义初始化方式
    11     init(name:String) {
    12         self.name = name
    13     }
    14     // 声明类属性
    15     static var introduce:String?
    16     // 声明计算属性
    17     var value:Int {
    18         // set方法
    19         set(a) {
    20             age = a // 在写计算属性的时候一定不能出现self.  否则或造成死循环
    21         }
    22         get {
    23             return age!
    24         }
    25     }
    26     // 声明类方法
    27     // 在类方法前边加上static修饰【虽然是一个类方法,但是该方法在子类中不能进行重写】
    28     static func sayHi() {
    29         print(introduce!)  // 注意:在类方法中只能使用类属性,不能使用对象属性
    30     }
    31     // 在类方法前边加上class修饰【他是一个类方法,可以被子类重写】
    32     class func sayHa() {
    33         print(introduce!)
    34     }
    35     // 声明一个对象(实例)方法
    36     func sayHe() {
    37         print("hello iam shilipai")
    38     }
    39 
    40 
    41 }
    42 
    43 // 创建对象【此时应该注意和OC区分开,实例对象,:后边跟的是类】(注意:要初始化对象一定要写初始化构造的方法)
    44 var person1:Person = Person(name: "MBBoy", age: 38)
    45 // 访问类中的属性 (对象属性)
    46 print(person1.name!)
    47 
    48 // 访问类属性
    49 Person.introduce = "我是XXXXX"
    50 
    51 // 访问计算属性
    52 person1.value = 28
    53 print(person1.value)
    54 
    55 // 访问类方法
    56 Person.sayHi()
    57 Person.sayHa()
    58 // 访问实例方法
    59 person1.sayHe()
    60 
    61 
    62 // 定义一个子类student,继承Person
    63 // 在swift中不支持多继承
    64 
    65 class Student:Person {
    66     // 重写父类的方法
    67     // 重写父类中的类方法
    68     override class func sayHa() {
    69         print("重写类的方法")
    70     }
    71     // 重写父类中的实例方法
    72     override func sayHe() {
    73         print("重写实例的方法")
    74     }
    75 }
    76 
    77 // 初始化student对象
    78 var student = Student(name: "小李", age: 18)
    79 
    80 Student.sayHa()
    81 student.sayHe() 

    4. 值类型和引用值类型的区别

     值类型

    • 该类型的每个实例持有数据的副本,并且该副本对于每个实例来说是独一无二的一份,比如结构体(struct)、枚举(enum)、元组(tuple)都是值类型

    • 值传递只是单纯的将数据拷贝一份,赋值给一个同类型的变量,两个变量互不影响,一个值发生改变,另一个不会发生任何变化

     引用值类型

    • 该类型的实例共享数据唯一的一份副本(在native层面说的话,就是该类型的每个实例都指向内存中的同一个地址),比如类(class)就是引用类型。

    • 值传递是将一个变量的地址赋值给另一个变量,当一个值发生改变,两个值同时改变
     1 struct animal { // 值类型
     2     var name:String?
     3     var age:Int?
     4     
     5     init(name:String, age:Int) {
     6         self.name = name
     7         self.age = age
     8     }
     9 }
    10 
    11 var dog = animal(name: "贝贝", age: 3)
    12 var dog1 = dog // 此时将dog的数据拷给dog1
    13 dog.name = "欢欢"
    14 
    15 print("dog.name:(dog.name!), dog1.name:(dog1.name!)")
    16 
    17 // 引用值类型
    18 class animal {
    19     var name:String?
    20     var age:Int?
    21     
    22     init(name:String, age:Int) {
    23         self.name = name
    24         self.age = age
    25     }
    26 }
    27 
    28 var dog = animal(name: "贝贝", age: 3)
    29 var dog1 = dog // 此时将dog的数据拷给dog1
    30 dog.name = "欢欢"
    31 
    32 print("dog.name:(dog.name!), dog1.name:(dog1.name!)")

    值类型与引用类型使用情形

    • 使用值类型的情形:       

      使用 == 运算符比较实例数据的时候。

      你想单独复制一份实例数据的时候。

      当在多线程环境下操作数据的时候。

    • 使用引用类型(比如class)的情形:

      当使用 === 运算符判断两个对象是否引用同一个对象实例的时候。

      当上下文需要创建一个共享的、可变的对象时。

    5.协议

     1> 概述

    • 协议定义了一个蓝图,规定了用来实现某一特定工作或者功能所必需的方法和属性

    • 类,结构体或枚举类型都可以遵循协议,并提供具体实现来完成协议定义的方法和功能

    • 任意能够满足协议要求的类型被称为遵循(conform)这个协议

     2> 声明协议

    • @objc 修饰的协议,其中的方法可以声明成可选实现(使用optional修饰)
    • 声明一个所有函数都必须实现的协议。

    3> 遵守协议

      类遵守协议,直接写在本类名后面的冒号的后面,使用 "," 号分隔

     1 //MARK: - 协议(protocol)
     2 // 当swift中声明协议的时候,协议里有可选方法的时候需要使用 @objc 关键字修饰
     3 @objc protocol MarryDelegate {
     4     func cook()   // 做饭
     5     func wash()   // 洗衣服
     6     optional func hitDouDou()  // 打豆豆
     7 }
     8 
     9 protocol DivorceDelegate {
    10     func divisedMoney()  // 分割财产
    11 }
    12 
    13 // 如果一个类要遵循协议的时候如果这个类有父类,要在冒号后先写父类,然后写要遵循的所有协议,用逗号隔开
    14 class Man: Person,MarryDelegate,DivorceDelegate {
    15     @objc func cook() {
    16         print("还好去新东方学了")
    17     }
    18     @objc func wash() {
    19         print("搓衣板派上用场了")
    20     }
    21     func divisedMoney() {
    22         print("分财产")
    23     }
    24 }
    25 
    26 // 创建一个男人
    27 let man = Man(name: "陈世美", age: 22)
    28 man.cook()
    29 man.wash()
    30 man.divisedMoney()

    6.扩展(Extension)

     1> 概述

      extension + 类名(结构体名字)可以对一个类和结构体扩展方法,类似于 OC 的Category 类目

      extension 可以多次对一个类进行扩展,也可以给一个类扩展协议方法

     2> 使用Extension给类扩充一个方法

     3> 给类扩展实现协议

     1 //MARK: - 扩展(Extension)
     2 //扩展协议中的相关方法
     3 extension Man {
     4     @objc func hitDouDou() {
     5         print("打豆豆")
     6     }
     7 }
     8 man.hitDouDou()
     9 
    10 // 扩展还可以扩展类的方法(给某个类添加方法,类似于OC中的category类目)以及对象方法
    11 extension Man {
    12     // 扩展一个对象方法
    13     func sing() {
    14         print("苍茫的天涯是我的爱")
    15     }
    16     // 扩展一个类方法
    17     class func sleep() {
    18         print("早点睡")
    19     }
    20 }
    21 man.sing()
    22 Man.sleep()

    7.闭包

     1> 概述  

    • 闭包是自包含的函数代码块,可以在代码中被传递和使用。 Swift 中的闭包与 C 和 Objective-C 中的 代码块(block)以及其他一些编程语言中的 匿名函数 比较相似。

    • 闭包可以捕获和存储其所在上下文中任意常量和变量的引用。 这就是所谓的闭合并包裹着这些常量和变量,俗称闭包。。

     2> 语法形式

      {

       (参数)-> 返回值类型  in 
           执行语句
      }

     3> 闭包的使用(五种方式)

     1 //MARK: - 闭包
     2 // 求两个数的最大值
     3 /*
     4 在OC中使用Block实现
     5 int(^myBlock)(int num1,int num2) = ^int(int num1,int num2) {
     6     return num1 > num2 ? num1 : num2;
     7 }
     8 */
     9 // 使用闭包
    10 // 最内括号是参数和类型,箭头 指向的是返回值类型
    11 var myBlock : ((num1:Int, num2:Int)->Int)
    12 // 第一种使用方式
    13 myBlock = {
    14     (num1:Int,num2:Int)->Int in    // 切记不能忘记in
    15     return num1 > num2 ? num1 :num2
    16 }
    17 
    18 // 第二种方式
    19 myBlock = {
    20     num1,num2 in
    21     return num1 > num2 ? num1 : num2
    22 }
    23 
    24 // 第三种方式
    25 myBlock = {
    26     num1,num2 in
    27     num1 > num2 ? num1 : num2
    28 }
    29 
    30 // 第四种方式
    31 myBlock = {
    32     $0 > $1 ? $0 : $1
    33 }
    34 
    35 // 第五种方式
    36 myBlock = {
    37     (num1,num2)->Int in
    38     return num1 > num2 ? num1 :num2
    39 }
    40 
    41 let max = myBlock(num1: 88, num2: 66)
    42 print(max)

    注意:在class类中声明变量 最好立刻初始化 或 定义为可选变量,不然该类必须重写初始化方法

  • 相关阅读:
    AES加解密
    redis HyperLogLog使用
    vi常用操作
    redis string使用
    用jdk命令定位java应用问题
    用户态、内核态及零拷贝
    缓存穿透与雪崩
    ReentrantLock、Semaphore、AQS
    redis list使用
    不同数据库取并集、交集、差集
  • 原文地址:https://www.cnblogs.com/crazygeek/p/5521533.html
Copyright © 2020-2023  润新知