• Swift-002-4.0基础语法补充


    Swift 基础语法补充:

    一.可选类型

    可选类型是swift的一大特色,在定义变量时,如果指定这个变量是可选的话,就是说这个变量可以有一个指定类型的值或者为nil。

    ? 和 ! 的区别

    “?”表示可选类型(Optionals),“!”表示隐式可选类型,其实还是可选类型。

    可选类型:将已存在的某种类型(结构体、枚举、类)定义为可选类型,表示该“新”类型的值可以为空nil   

    var nickName : String?

    使用self.label!是明确声明此时self.label里一定有值,无论什么情况都调用后面的.text赋值方法。

    而使用self.view?是声明此时并不确定self.view里是否有值,所以只在view有值时调用后面.addSubview方法。

    这样做的目的一是让代码更明确, 二是给编译器提供更多线索,在编译时发现更多潜在错误。

    1.定义一个optional 的常量

    let x:Optional = 10
    print(x)

    点击进去查看,可以发现Option其实是一个枚举类型。这个枚举有两个值,一个是none,表示没有值,而另一个是some,表示某一类值。

    在输出的时候,可以看见控制台上的内容Optional(10),它的作用就是提示这是一个可选值。

    而在实际开发中,一般不用上述方式创建可选值,而是指定一个类型,再在其后添一个问号。

    let x:Optional = 10  //第一种写法
    let x:Int? = 20     //第二种写法
    print(x)

    上述代码问号的意思就是定义一个可选的Int类型,可能没有值,也可能有一个整数

    2.解包

    试试将上面案例x和y相加,这个时候还能输出结果么?

    此时可以看到编译器已经报错。在前面的教程中提到过,不同类型的值是不能直接运算的可选项若它的值为nil则不能参加计算

    因此引入解包的概念,“!”代表强制解包它的意思是从可选值中强行获取对应的非空值

    输出结果:

    3.解包常见错误

     

    //错误示范1
    let y : Int?
    print(y)

    使用let定义的是常量,在初始化时必须要给出值

    //错误示范2:
    let y : Int? = nil
    print(y)

    强制解包是危险操作,如果可选值为nil,强制解包系统会奔溃

    4.let 和 var的可选默认值

    //默认值测试
    let x: Int?
    print(x)
    var y :Int?
    print(y)

    用let做测试时会直接报错,说明let的可选值是没有默认值的,而用var做测试时,报错信息就变成了警告,运行的结果为nil。可以由此推测出var的可选项默认值为nil

    swift中有规定,对象中的任何属性在创建对象时,都必须有明确的初始化值。

    5.可选绑定

    if let/var表示。它将变量赋值给一个临时变量,在这个操作中会做两步操作:首先判断变量是否有值,如果没有值,则直接不执行大括号里面的内容;如果有值,系统会自动将变量进行解包,并且将解包后的结果,赋值给临时变量

    //例如

    通过一个字符串创建NSURL对象

     

    let url: URL? = URL(string: "https://www.baidu.com")

    接着创建NSURLRequest对象.

    强制解包非常危险,当url有中文的时候可能会变成nil。所以要判断url是否为空再对其进行解包

    if let url = url {
        let request = URLRequest(url: url)
    }

    二.If语句和三目运算符

    1>.if语句

    在swift中,if语句是不用带小括号的,但是后面跟的语句必须有花括号,哪怕只有一行代码。

      let a = 10
      //if 条件句是没有小括号的
      if a > 5 {
          print("小仙女")
       }else {
          print("小鲜肉")
       }

    2>.三目运算:

    三目运算符的写法是表达式后跟一个问号,用冒号来隔开条件是否成立的值

    let x = 10
    x > 5 ? print("小仙女") : print("妖精")  //注意swift语法比较严谨,空格也要注意

    如果开发者只想处理条件成立的部分,此时可以在冒号后面用一个小括号来代替条件不成立的部分。

    x > 5 ? print("你写了两次啦"):()

    三目运算的简单模式:处理可选项

     "??"的意思是说,如果表达式有值,就使用那个值,如果没有,就是呀“??”后面的值来代替

    let x:Int? = nil
    let y:Int? = 9
    print((x ?? 0) + (y ?? 0))

    运行之后结果为9

    再说说运算符的优先级

    let name:String? = "安琪拉"
    print((name ?? "") + "火烧屁屁咯")
    print(name ?? "" + "火烧屁屁咯")
    /*
    输出结果:
    安琪拉火烧屁屁咯
    安琪拉
    */

    从运行的结果可以看到,“??”的优先级是最低的。如果没有小括号的约束,它会将后面的语句都当成是一个表达式

    if  let 和 var 连用 (提高安全性,括号里面一定是有值的)

            let oName:String? = "小小"
            let oAge:Int? = 18
            //方法1
            if oName != nil && oAge != nil {
                print(oName! + String(oAge!))
            }
            //方法2 let和var连用
            if var name = oName , let age = oAge {
                name = "哈哈"
                print(name + String(age))
            }else {
                print("x 或 y的值为NIl")
            }

     三、Guard使用

    Guard里面是一定有值的

       let oName:String? = "小小"
       let oAge:Int? = 18
       guard let name = oName , let age = oAge else {
            print("姓名或者年龄是nil")
            return
        }
         print(name + String(age))

     四、Switch使用

    Swift中的Switch可以使用任意类型,而不限制是Int类型

        //Swift中的Switch可以使用任意类型,而不限制是Int类型
        //Swift中的Switch不需要break
        //如果要使多个值等于相同的结果,直接用","逗号隔开
        func demo(num:String) {
            switch num {
            case "10","9":
                print("优秀~")
            case "8":
                break
            default:
                print("及格")
            }
        }

     五、For循环:

    数字和...之间不能加空格

        //For循环
        func demo() {
            //大于0 小于5
            for i in 0..<5 {
                print(i)
            }
            //输出结果:0 1 2 3 4
            print("----------------------")
            //大于0 小于等于5
            //数字和...之间不能加空格
            for i in 0...5 {
                print(i)
            }
            //输出结果:0 1 2 3 4 5
        }

    //逆序

            //逆序
            for i in (0..<10).reversed() {
                print(i)
            }
            //输出结果:9 8 7 6 5 4 3 2 1 0

     六、字符串

     由双引号包裹起来的文本字符集

       func demo() {
            //不可变字符串
            let someString = "someString"
            //可变字符串
            var variableString = "Horse"
            variableString += "and carriage"
            print(someString + variableString)
            //字符串初始化
            var anotherEmptyString = String()
            let emptyString = ""
            //字符串判断是否为空
            if emptyString.isEmpty {
                print("Nothing !")
            }
        }

     遍历字符串和计算文字长度:

            //遍历字符串:
            for character in "Dog!?".characters {
                //print(character)
            }
            //计算文字的长度,每个汉字代表3个字节
            let str = "Hello world 你好"
            print(str.lengthOfBytes(using: String.Encoding.utf8))//计算字节的数量
            print(str.characters.count)//字符的个数

    七、数组

    //Set 无序不重复

    //用于存储多个元素的集合,元素的类型必须一致,同时,Swift支持泛型集合

    //集合的可变性取决于是常量和变量

     ①创建数组

            //Array
            //A:初始化方法
            //Array<Element> : Element 是数组中唯一存在的指定类型 或者 [element]
            var someInt = [Int]()//创建一个空数组 数组的值类型被推断为Int类型
            someInt = [1,2,3]
            print(someInt)//结果:[1, 2, 3]
            var threeDoubles = Array(repeating: 1.2, count: 3)//repeating 后为数组默认值,count 为数组长度
            print(threeDoubles[1]) //结果:1.2    
                  
            //B:通过两个数组相加创建数组
            let threeDoubles = Array(repeating: 0.0, count: 3)
            let anotherDoubles = Array(repeating: 2.9, count: 2)
            let result = threeDoubles + anotherDoubles
            print(result)
            
            //C: 字面量创建数组
            var shoppingList :[String] = ["EGGS","MILK"]
            var shoppingList2 = ["Eggs","Milk"]  

    ②操作数组

     

            //字面量创建数组
            var shoppingList = ["Eggs","Milk"]
            //转义斜杠 + () 格式化打印字符串 //isEmpty判断是否为0
            print("一共有(shoppingList.count)项")
            //给数组添加新元素
            shoppingList.append("Flour")
            //第二种添加方法
            shoppingList += ["cheese", "Butter"]//追加
            //在具体索引值添加元素 insert
            shoppingList.insert("Map", at: 3)
            //替换指定元素
            shoppingList[2...4] = ["替换2","替换3"]
            //删除
            shoppingList.remove(at: 0)
            //删除最后一个
            shoppingList.removeLast()
            print(shoppingList)
            //遍历
            for i in shoppingList {
                print(i)
            }
            //for
            //enumerated
            for (index,value) in shoppingList.enumerated() {
                print(String(index+1)+(value))
            }
            print("--------------------------------------")

     

    八、集合

    ①创建集合

             //Set 无序不重复     
            //集合Set 形式:Set<Element>
            //创建空的集合
            var letters = Set<Character>()
            print("Letters的集合长度为(letters.count)")
            //用数组字面量构造集合
            //var favorite:Set<String> = ["Rock","Hip pop"]
            var favorite:Set = ["Rock","Hip pop"]
            //添加元素
            favorite.insert("Jazz")
            if let removeBack = favorite.remove("Rock") {
                print(removeBack)
            }else {
                print("没有值")
            }
            //删除整个集合 removeAll
            //遍历并排序
            for item in favorite.sorted() {
                //按照首字母输出
                print("item-(item)")
            }

    ②操作集合 真子集,即子集不等于父集

          func demo2() {
            let oddD: Set = [1,3,5,7,9]
            let evenD: Set = [0,2,4,6,8]
            let singleDPrime: Set = [2,3,5,7]
            print(oddD.union(evenD).sorted()) // 合并
            //结果:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
            print(oddD.intersection(evenD).sorted()) //相交
            //结果:[]
            print(oddD.subtracting(singleDPrime).sorted()) //取差值
            //结果:[1, 9]
            print(oddD.symmetricDifference(singleDPrime).sorted())//取两个集合不同
            //结果:[1,2,9]
           }
                   let houseAnimals:Set = ["?","?","?"]
            let farmAnimals:Set = ["?","?","?","?","?","?"]
            let cityAnimals:Set = ["?","?"]
            print(houseAnimals.isSubset(of: farmAnimals))//判断前一个值是否包含在后面的集合 结果:true
            print(farmAnimals.isSuperset(of: houseAnimals))//判断所有的值是否包含  结果:true
            print(farmAnimals.isDisjoint(with: cityAnimals))//是否没有交集       结果:false (有交集)

     九、字典

    创建字典和操作字典:

            //创建字典
            var nameOfIntegers = [Int:String]() //创建一个空的字典
            var someDict:[Int:String] = [1:"one",2:"two",3:"three"]//字面量方式创建
            //获取值
            let someVar = someDict[2]
            print("key=1的值(someVar!)")//输出结果为:two
            //修改值
            var oldVar = someDict.updateValue("one的新值", forKey: 1)
            print("key=1的值(oldVar!)")//oldVar 是旧值
            someDict[2] = "two的新值"
            print(someDict[1]!)
            
            //操作字典
            //移除
            var removeValue = someDict.removeValue(forKey: 2)
            print("key=2的值为(removeValue!)")//输出结果为:key=2的值为two的新值
            
            //someDict[3] = nil
            //print(someDict) //输出结果:[1: "one的新值"]
            
            //遍历字典
            for (key,value) in someDict {
                print("遍历字典key:(key) value:(value)")
            }
            for (key,value) in someDict.enumerated() {
                print("遍历字典key:(key) value:(value)")//带索引
            }
            //字典转数组
            let dictKeys = [Int](someDict.keys)
            let dictValues = [String](someDict.values)

    十.函数与闭包

    //函数与闭包

    //函数相当于Objective-C中的方法,是一段完成特定任务的独立代码片段。可以通过给函数命名来标志某个函数的功能。而这个名字可以用来在需要的时候“调用”该函数完成其任务。格式如下

           

            func 函数名(参数列表)-> 返回值类型 {
                   代码块
                   return 返回值
             }
             func表示关键字,多个参数列表之间用逗号隔开,也可以没有参数。使用->指向返回值类型。如果没有返回值,可以用Void代替,也可以省略
        //1、定义无参无返回的函数
        func phone() ->  Void {
            print("小米")
        }
        //phone()
        
        //2.定义无参,有返回值
        func phoneNum() -> String {
            return "123456"
        }
        //print(phoneNum())
        //3.定义有参无返回值
        func callPhone(phoneNum:String) -> Void {
            print("打电话给(phoneNum)")
        }
        //4.定义有参有返回的函数
        func sum(num1 : Int , num2 : Int) -> Int {
            return num1 + num2
        }
        //5.函数无返回值类型:
        func demo() {
        }
        func demo1() -> () {
        }
        func demo2() -> Void {
        }
        //6._ 下划线的使用
        func firstFunc(_ age1 : Int , _ age2 : Int) -> Int {
            return age1 + age2
        }
        //在swift4之后,调用函数的时候,能直观的看到参数。而在之前调用之时,只能看见第二个参数之后的名称,表达起来并不直观。如何解决这个问题呢?
        //可以采用给参数起别名的方式,在参数前面添加一个别名。
        func getSum(number1 num1: Int,number2 num2 : Int) -> Int{
            return num1 + num2
        }

    函数的默认值

        //函数的默认值
        func defaultFunc( name:String = "小Boss", age:String = "18") -> String {
            return name + age
        }
        //print(defaultFunc())  //输出结果  小Boss18
        //print(defaultFunc(name: "小明", age: "18")) //输出结果  小明18
        //print(defaultFunc(name: "小仙女")) //输出结果  小仙女18

    闭包:自包含的函数代码块

          let f = sum  //f 是把函数的指针记录下来
          print(f(20,40))//结果:60
          func sum(x:Int , y:Int) -> Int {
             return x + y
          }
        
            //1.无参无返回值的闭包
            let b1 = {
                print("干掉他们")
            }
            b1()
            //闭包格式 {形参列表 -> 返回值类型 in 实现代码}
            //2.有参无返回值的闭包
            let b2 = {
                (x:String) -> () in print(x)
            }
            b2("String")
            //3.带参数,带返回值的闭包
            let b3 = {
                (x:Int) -> Int in return x + 3
            }
            print(b3(4))//输出结果:7

    尾随闭包和逃逸闭包

          override func viewDidLoad() {
            super.viewDidLoad()
            //普通调用
            myFunc(strP: "Hello", closureP: {
                (string) in print(string)
            })
            //尾随闭包调用
            myFunc(strP: "Hello") {
                (string) in print(string)
            }
            testEscaping {
                [unowned self] () -> Void in
                self.x = 100
            }
            print("x=(x)")//输出结果为:x=10 没有被修改为100
            callBackArray.first?()//修改了x
            print("x=(x)")//输出结果为:x=100 修改成功
        }
        
        //1.尾随闭包
        func myFunc(strP:String,closureP:(String) -> Void) -> Void {
            closureP(strP)
        }
        
        //2.逃逸闭包  在函数之后才能被调用 (闭包逃出了函数的作用域)
        var x = 10
        var callBackArray:[()->Void] = [] //定义数组,数组的元素都是闭包类型的
        //@escaping 允许逃逸出函数
        //逃逸闭包的方法
        func testEscaping(callBack:@escaping () -> Void) {
            callBackArray.append(callBack)
        }

     

     

     

  • 相关阅读:
    使用 RestTemplateBuilder.build() 代替 new RestTemplate()
    R2DBC加入Reactive基金会
    Spring Data 2020.0.1 发布
    前后端分离,注册和登录。涉及Oauth2 Password-Flow 授权方式
    OAuth2 Google、Github自定义登录页面
    Authorization-Server入门(二)
    Authorization-Server入门(一)
    Google或Github 登录Web应用​
    使用SpringBoot发送Gmail和QQ邮箱
    理解同步/异步和阻塞/非阻塞的区别
  • 原文地址:https://www.cnblogs.com/StevenHuSir/p/Swift_GrammarAll.html
Copyright © 2020-2023  润新知