zoukankan      html  css  js  c++  java
  • Swift 基本语法2

    一、?和!

    1、可选类型: ?

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

    ! 代表强制解包

     1 // MARK: - ?和!
     2 // ?代表可选类型,实际上的值是枚举类型 -- None和Some,其实nil值相当于Optional.None,非nil就是Optional.Some
     3 // !代表强制解包
     4 
     5 // 定义一个Int类型的可选类型变量
     6 var num : Int? = 8
     7 // 把这个类型类型的变量赋值给另一个可选类型的变量
     8 var num1 = num
     9 print(num1)
    10 // 打印出来以后是一个Optional类型的值,如果要取到8,必须对可选类型强制解包!
    11 var num2 = num!
    12 print(num2)
    13 
    14 var number : Int?
    15 // 如果对没值(nil)的变量进行强制解包,会造成程序崩溃
    16 //var number1 = number!

     2、可选绑定

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

    1 var number : Int?
    2 // 如果对没值(nil)的变量进行强制解包,会造成程序崩溃
    3 //var number1 = number!
    4 
    5 // 可选绑定
    6 // 如果不确定可选类型变量是否有值时,用可选绑定,不需要对可选类型强制解包
    7 if var number2 = number {
    8     print(number2)
    9 }

     3、隐式解析可选类型

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

     1 // 隐式解析可选类型:有值,没值(nil)
     2 
     3 var intNum : Int! = 3
     4 var intNum1 = intNum
     5 print(intNum)
     6 print(intNum1)
     7 
     8 // 如果隐式解析可选类型的变量没值,程序一样会崩溃
     9 
    10 var intNumber :Int!
    11 //var intNumber1 = intNumber
    12 //print(intNumber1)
    13 
    14 // 可选绑定
    15 if var intNumber2 = intNumber {
    16     print(intNumber2)
    17 }

    二、结构体

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

    声明一个结构体的格式:
    struct 结构体的名字 {
       声明成员变量等

    计算属性与存储属性

    · 存储属性就是类或结构体里定义的变量(或常量)。存储属性可以是变量存储属性(用关键字 var定义),也可以是常量存储属性(用关键字let定义)。
    · 除存储属性外,类、结构体和枚举可以定义计算属性。计算属性不直接存储值,而是提供一个必写的getter和一个可选的setter来间接获取和设置其他属性或变量的值。不可以在计算属性中使用self.否则会造成死循环。

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

    结构体遵守代理协议(经自己验证,协议中声明的方法只能是计算属性,否则不能遵守)

     1 // 7、结构体遵守代理协议
     2 
     3 protocol Named {
     4     var name: String { get }
     5 }
     6 protocol Aged {
     7     var age: Int { get }
     8 }
     9 struct Person: Named, Aged {
    10     var name: String
    11     var age: Int
    12 }

    三、类

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

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

    声明类方法的方式有两种

    使用 static 和 class 都可以修饰类方法,区别在于:class修饰的类方法可以被子类重写;static修饰的类方法不可以被子类重写,防止父类方法被修改

     1 // MARK: - 类(class)
     2 class Person {
     3     // 属性
     4     var name : String?
     5     var age : Int?
     6     
     7     // 初始化方法
     8     init(name : String, age : Int) {
     9         self.name = name
    10         self.age = age
    11     }
    12     
    13     // 声明类属性
    14     static var introduce : String?
    15     
    16     // 声明计算属性(setter,getter, 不能用self. 否则会造成死循环)
    17     var value : Int {
    18         set {
    19             age = newValue  // newValue是外界调用方法时从外界传进来的参数
    20         }
    21         get {
    22             return age!
    23         }
    24     }
    25     
    26     // 声明类方法,在类方法中只能使用类属性,不能使用对象属性
    27     // 1、用static关键字修饰,虽然是一个类方法,但是该方法在子类中不能重写
    28     static func sayHi() {
    29         print(introduce! + "hi")
    30     }
    31     // 2、用class关键字修饰,可以被子类重写
    32     class func sayHello() {
    33         print(introduce! + "hello")
    34     }
    35     
    36     // 声明实例方法
    37     func sayBey() {
    38         print("BeyBey");
    39     }
    40 }
    41 
    42 // 1、创建对象,调用初始化方法
    43 var per : Person = Person(name : "MBBoy", age : 12)
    44 print(per.name! + "(per.age!)")
    45 
    46 // 2、访问类属性
    47 Person.introduce = "我是XXX"
    48 print(Person.introduce!)
    49 
    50 // 3、访问计算属性
    51 per.value = 20;
    52 print(per.value)
    53 
    54 // 4、访问类方法
    55 Person.sayHello()
    56 Person.sayHi()
    57 
    58 // 5、访问实例方法
    59 per.sayBey()
    60 
    61 // 定义一个Person类的子类Student,Swift不支持多继承
    62 class Student : Person {
    63     // 重写父类中的类方法
    64     override class func sayHello() {
    65         print("子类Student中重写的类方法sayHello")
    66     }
    67     
    68     // 重写父类中的实例方法
    69     override func sayBey() {
    70         print("子类Student中重写的实例方法sayBey")
    71     }
    72 }
    73 
    74 // 1、初始化Student类的对象
    75 var student : Student = Student(name: "yyp", age: 11)
    76 Student.sayHi()
    77 
    78 // 2、调用重写的父类中的类方法
    79 Student.sayHello()
    80 
    81 // 3、调用重写的父类中的实例方法
    82 student.sayBey()

     值类型与引用类型

    • 值类型:

        值类型(Value Types):每个实例都保留了一分独有的数据拷贝,一般以结构体 (struct)、枚举(enum) 或者元组(tuple)的形式出现。

    • 引用类型:

        引用类型(Reference Type):每个实例共享同一份数据来源(在native层面说的话,就是该类型的每个实例都指向内存中的同一个地址),一般以类(class)的形式出现。

    • 值类型与引用类型使用情形
      • 使用值类型的情形:
                使用==运算符比较实例数据的时候。
                你想单独复制一份实例数据的时候。
                当在多线程环境下操作数据的时候。
      • 使用引用类型(比如class)的情形:
                当使用===运算符判断两个对象是否引用同一个对象实例的时候。
                当上下文需要创建一个共享的、可变的对象时。
    • 值类型与引用类型的区别:
      值类型和引用类型最基本的分别在复制之后的结果。
      • 当一个值类型被复制的时候,相当于创造了一个完全独立的实例,这个实例保有属于自己的独有数据,数据不会受到其他实例的数据变化影响。
      • 复制一个引用类型的时候,实际上是默默地创造了一个共享的实例分身,两者是共用一套数据。因此修改其中任何一个实例的数据,也会影响到另外那个。
     1 // MARK: - 值类型和引用值类型
     2 // 值类型
     3 struct animal {
     4     var name : String?
     5     var age : Int?
     6     
     7     init(name : String, age : Int) {
     8         self.name = name
     9         self.age = age
    10     }
    11 }
    12 
    13 var dog : animal = animal(name: "阿福", age: 3)
    14 // 将dog变量的值赋给dog1(其实是一个拷贝的过程)
    15 var dog1 = dog
    16 dog.name = "aFu"
    17 print(dog.name)    // 打印结果:aFu
    18 print(dog1.name)   // 打印结果:阿福
    19 
    20 // 引用值类型
    21 class pet {
    22     var name : String?
    23     var age : Int?
    24     
    25     init(name : String, age : Int) {
    26         self.name = name
    27         self.age = age
    28     }
    29 }
    30 
    31 var cat : pet = pet(name: "", age: 2)
    32 // 将cat变量的值赋给cat1(其实是一个引用的过程)
    33 var cat1 = cat
    34 cat.name = ""
    35 print(cat.name)   // 打印结果:萌
    36 print(cat1.name)  // 打印结果:萌

     四、协议(protocol)

    ·  协议定义了一个蓝图,规定了用来实现某一特定工作或者功能所必需的方法和属性
    ·  类,结构体或枚举类型都可以遵循协议,并提供具体实现来完成协议定义的方法和功能
    ·  任意能够满足协议要求的类型被称为遵循(conform)这个协议

    声明一个带有可选函数的协议时,必须用@objc来修饰,可选函数要用optional关键字修饰

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

    必须实现的协议方法,就必须实现,否则会报错

    直接实现可选协议里的方法,会报警告,可以添加 @objc 或者继承NSObjec

     1 // MARK: - 协议(protocol)
     2 // 在Swift中声明协议的时候,协议里有可选方法时,需要使用@objc关键字修饰
     3 
     4 // 结婚协议
     5 @objc protocol MarryProtocol {
     6     func cook()  // 做饭
     7     func wash()  // 洗衣服
     8     optional func hitDouDou()   // 打豆豆,可选方法
     9 }
    10 
    11 // 离婚协议
    12 protocol DivorceProtocol {
    13     func DivideMoney()   // 分财产
    14 }
    15 
    16 // 继承与Person,实现了MarryProtocol协议和DivorceProtocol协议
    17 // 如果该类是另一个类的子类,先写父类,再写遵循的协议
    18 class Man : Person, MarryProtocol, DivorceProtocol {
    19     @objc func cook() {
    20         print("还好去新东方学了几年的厨艺,终于可以大展身手")
    21     }
    22     @objc func wash() {
    23         print("还好买了台洗衣机")
    24     }
    25     
    26     func DivideMoney() {
    27         print("分财产")
    28     }
    29 }
    30 
    31 // 创建一个男人
    32 var man = Man(name: "韦小宝", age: 22)
    33 man.cook()
    34 man.wash()
    35 man.DivideMoney()

    五、扩展(Extension)

    ·  extension + 类名(结构体名字)可以对一个类和结构体扩展方法

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

    ·  扩展只能增加方法,不能增加属性

    // MARK: - 扩展(Extension)
    // 1、扩展协议中的相关方法
    extension Man {
        @objc func hitDouDou() {
            print("打豆豆")
        }
    }
    
    man.hitDouDou()
    
    // 2、扩展类方法以及对象方法 (类似于OC的类目(Category))
    extension Man {
        // 对象方法
        func sing() {
            print("唱歌")
        }
        // 类方法
        class func dance() {
            print("growl")
        }
    }
    
    man.sing()
    Man.dance()

    六、闭包

    · 闭包是自包含的函数代码块,可以在代码中被传递和使用。 Swift 中的闭包与 C 和 Objective-C 中的代码块(block)以及其他一些编程语言中的匿名函数比较相似。
    · 闭包可以捕获和存储其所在上下文中任意常量和变量的引用。 这就是所谓的闭合并包裹着这些常量和变量,俗称闭包。Swift 会为您管理在捕获过程中涉及到的所有内存操作。
    1.语法形式
    {(参数)-> 返回值类型  in
          执行语句
    }
    注意:闭包的函数体部分由关键字 in 引入。 该关键字表示闭包的参数和返回值类型定义已经完成,闭包函数体即将开始。

     1 // MARK: - 闭包
     2 // 求两个数的最大值
     3 /*
     4     在OC中使用Block实现
     5     int (^block)(int a, int, b) = ^int (int a, int b) {
     6         return a > b ? a : b;
     7     }
     8 */
     9 
    10 // 使用闭包
    11 var myBlock : ((a : Int, b : Int) -> Int)
    12 
    13 // 第一种方式
    14 myBlock = {
    15     (a : Int, b : Int) -> Int in
    16     return a > b ? a : b
    17 }
    18 
    19 // 第二种方式
    20 myBlock = {
    21     (a, b) -> Int in
    22     return a > b ? a : b
    23 }
    24 
    25 // 第三种方式
    26 myBlock = {
    27     a, b in
    28     return a > b ? a : b
    29 }
    30 
    31 // 第四种方式
    32 myBlock = {
    33     a, b in
    34     // 不用return关键字
    35     a > b ? a : b
    36 }
    37 
    38 // 第五种方式
    39 myBlock = {
    40     a, b in
    41     return a > b ? a : b
    42 }
    43 
    44 let max = myBlock(a: 3, b: 6)
    45 print(max)
  • 相关阅读:
    WordPress主题开发实例:查询单篇文章
    WordPress基础:get_page_link获取页面地址
    WordPress主题开发:优化标题
    React中的的JSX
    WordPress主题开发:WP_Query常用参数
    WordPress基础:wp_list_pages显示页面信息列表
    WordPress基础:常用分类列表wp_list_categories
    SQL Server 2008 安装教程
    XCODE调试时不显示变量值/指针地址的解决方案
    android iOS 编码问题害死人!
  • 原文地址:https://www.cnblogs.com/fearlessyyp/p/5520811.html
Copyright © 2011-2022 走看看