美文网首页
swift基础知识

swift基础知识

作者: 美得冒泡的姗迪 | 来源:发表于2017-08-15 17:20 被阅读0次

    一.常量和变量

    [代码]
    let maximumNumberOfLoginAtAttempts = 10    #用let声明常量
    var currentLoginAttempt = 0  #用var声明变量
    
    [类型注释]
     声明常量或者变量的时候提供类型注释,明确存储值的类型。常量或者变量名后依次添加 冒号,空格,类型名称来实现。
     var welcomeMessage: String
     welcomeMessage = "Hello"
    
     其实,可以不适用类型注释,因为在给常量或者变量提供初始值的时候,swift可以推测出他的类型。
    
    [打印]
      println(welcomeMessage)   #打印变量
      #字符串插值 用“ \(变量名) ” 来占位,swift会用变量的值来替换这个占位符
      println("The current value of welcomeMessage is \(welcomeMessage)")
    

    二.注释和分号

     [注释]
      //单行注释
      /*多行 注释*/
    
     [分号]
        语句结束后不需要;去标志结束
        但是如果多个语句写在一行,可以使用分号去分割
    

    三.整数和浮点数

    [整数]
      swift提供 8   16   32   64位有符号和无符号的整数
      Eg.
      UInt8  8位无符号整数
      Int32   32位有符号整数
     
      let minValue = UInt8.min
      let maxValue = UInt8.max
    
      在swift中,UInt ,  Int类型 与 当前系统的字长相等,
      32位系统,Int === Int32
      64位系统,Int === Int64
    
     [浮点数]
        Double  64位浮点数
        Float      32位浮点数
    

    四.类型安全和类型推断

      类型安全:编译的时候会进行类型检查,标记不匹配的类型。
      类型推断:根据初值推断类型
     [数字的字面量]
        不带前缀的十进制数
        0b前缀的二进制数
        0o前缀的八进制数
        0x前缀的十六进制数
     [指数]
        1.25e2    -->   1.25 * (10^2)     #10进制基数是以10为底
        1.25e-2   -->   1.25 * (10^-2)
        0xFp2     -->    15 * (2^2)         #16进制基数是以2为底
     [数值类型的转化]
       整数间的转化demo:
       let twoThousand: UInt16  = 2_000   #_不会改变字面值,辅助提高可读性
       let one: UInt8 = 1
       let twoThousandAndOne = twoThousand + UInt16(one)   #加号两边都是UInt16可以相加
    
       浮点数的转化demo
       let three = 3
       let pointNum = 3.1415
       let pi = Double(three) + pointNum
       let intPI = Int(pi)
    
       上面这种SomeType(ofInitialValue) [eg. Double(three) ]
       是一种调用swift类型构造器的默认方法,我们为他传入初值,比如 UInt16 的构造器可以用来接收UInt8类型的值,
       所以可以将UInt8类型的值转化成UInt16,此处必须传UInt16支持的类型,不是随便什么类型都可以的。当然可以通过扩展让构造器支持自定义类型。
    
      [类型别名]
        typealias AudioSample = UInt16
        var maxUInt16Num = AudioSample.max    #UInt16.max
    

    五.布尔值

     [声明和初始化]  
      let oragesAreOrange = true     #不需要制指定具体的Bool类型,编    译器会帮助我们推断的
      let oragesAreOrange = false
    
      [判断语句与Bool]
      错误写法:编译器不允许非bool值替换Bool,这个跟java等其他语言不同
      let i  = 1
      if i {
      }
      正确写法:
      if i==1 {}
    

    六.元组Tuple

    多个值组合成一个复合值,元组中的值可以是任何类型,并且可以是相互不同的类型。
    场景:比如一个处理访问网页响应的函数,需要返回(Int,String)元组来描述成功失败的结果。
    
    let http404Error = (404,"Not Found")  #类型是 (Int , String)
     #下标访问
     println("The status code is \(http404Error.0)")    #The status code is  404
     println("The status msg is \(http404Error.1)")    #The status msg is  Not Found
    
    let  http200Status = (statusCode:200,description:"OK")
     #元素名称访问
     println("The status code is \(http200Status.statusCode)")    #The status code is  200
     println("The status msg is \(http200Status.description)")    #The status msg is OK
    
    let (statusCode,statusMsg) = http404Error
     println("The status code is \(statusCode)")    #The status code is  404
     println("The status msg is \(statusMsg)")    #The status msg is  Not Found
    
    let (justTheStatueCode, _) = http404Error    # 用( _ ) 来忽略不关心的部分
    println("The status code is \(justTheStatueCode)")    #The status code is  404
    

    七.Optional类型

     Optional 类型是swift独有的 ,表示一个基础类型可能有值也可能没有值,当他没有值的时候就是nil。
    
    [Optional定义]
      定义一个Optional的值很容易,只需要在类型后面加上问号(?)就行了:
      var str : String?
    
     [显式拆包]
      Optional类型的值不能被直接使用,当需要用时要显式拆包,以表明我知道这个Optional是一定有值的,拆包用!:
      var str: String? = "Hello World!"
      str!     //Hello World!
    
      ps,Optional类型其实是一个枚举
    
    [隐式拆包]
      除了显式拆包,Optional还提供了隐式拆包,通过在声明时的数据类型后面加一个感叹号(!)来实现:
      var str: String! = "Hello World!"
      str //Hello World!
    
    [可选绑定Optional Binding]
      如下两个demo来讲述一下为甚么要Optiona Binding:
    
      看下面这个demo,当count != nil条件成真后接着在上下文中使用count,会被要求进行拆包 String(count!) ,
      var count: Int?
      count = 100
      if count != nil {
            "count is " + String(count!)    //count is 100
      } else {
            "nil"
      }
    
      为了避免在条件判断语句后执行一次或更多次的拆包,Swift引进了Optional Binding,我们就可以这样做:
      var count: Int?
      count = 100
      if let validCount = count {
            "count is " + String(validCount)    //count is 100
      } else {
            "nil"
      }
    
    [Optional Chaining]
      暂时还没办法秒懂,mark一下,回头看
      http://blog.csdn.net/zhangao0086/article/details/38640209
    

    八.断言

    用于运行时校验对应条件是否等于true的判断。
    let age = -3
    assert(age>=0,"A person age can not less than zero")
    只有断言的条件 age>=0的时候 才会继续执行,否则 age是负数 断言是false 那么就会触发断言 程序终止。
    

    九.运算符

    赋值  let b = 10
    算数  +  -  *  /
    取余  %
         这个符号要特殊说明一下,因为他与别的语言的取模不一样,他表示( a%b)  a中包括多少个b 并返回剩余的值,公式是
          a = (b * some multiplier) + remainder
          9 = (4 * 2) + 1   [9 % 4 = 1]
          -9=(4 * -2) + -1  [-9 % 4 = -1]    #可见 跟正负号没甚么关系
          8 = (2.5 * 3) + 0.5   #浮点数也一样的
    自增  ++
    自减  --
         var a = 0
         let  b = ++a     # b = 1 ; a = 1
         let  c = a++     # c = 1 ; a = 2
     一元减 -       理解成负号
     一元加 +       对操作数没甚么变化
     复合赋值运算     +=
     比较运算符       相等(a==b)    不相等(a!=b)    大于(a>b)   小于(a<b)  
                    大于等于(a>=b) 小于等于(a<=b)   完全等(===) 不完全等(!==)
     三元条件        question ? answer1 : answer2
     范围运算符       闭合范围运算符  
                    for index in 1...5 {}     #[1,5]
                    半闭合范围运算符
                    for index in 1..5 {}      #[1,5)
                 
     逻辑运算符       逻辑非  !a
                    逻辑与  a && 
                    逻辑或  a || b
    

    十.字符串和字符

    [初始化空字符串]
       var emptyString = ""
       var anotherEmptyString = String()
       if emptyString.isEmpty {    #判断字符串为空
            emptyString += "给字符串加点内容"
       }
      
       string是拷贝类型,即 赋值,参数传递等 string值是生成一个副本的,不是原始的版本。与Cocoa的NSString不同。
    
    [字符]
        let yenSign: Character = "¥"    #需要类型注释 和 字面量
    
        for character in "一个字符串" { 
              println(character)
         }
    
        #countElements统计字符数,全局函数
        let  unusualMsg = "slfjasfjslafjasfj"
        println("\(countElements(unusualMsg))")
        
    [字符串的比较]
        字面值相等   if   str1 == str2 {  ......   }
        前缀相等     if str1.hasPrefix("Act 1")  { ........ }
        后缀相等     if str1.hasSuffix("Act 1")  { ........ }
        字符串大写  let strUpper = str.uppercaseString
        字符串小写  let strLower = str.lowercaseString
        
     [Unicode]
     关于Unicode 和 三种兼容unicode的字符串 自行查找资料进一步学习~
     三种兼容字符串是:UTF-8 编码单元集合    for c in str.utf8  { ... }
                    UTF-16编码单元集合    for c in str.utf16  { ... }
                    21位Unicode标量值的结合  for c in str.unicodeScalars  { ... }
    

    十一.集合

    集合有两类:
      数组:相同类型的有序列表
      字典:相同类型的无序列表
    
    [数组定义]
    var shoppingList: String[] = ["Eggs","Milk"]
    var shoppingList: Array<String> = ["Eggs","Milk"]
    var shoppingList = ["Eggs","Milk"]    #类型推断的存在,可以不用定义类型
    var someInts = Int[] ()               #空数组
    var someInts = []                     #空数组
    #构造器,创建有若干默认值的数组
    var threeDoubles = Double[] (count:3 ,repeatedValue: 0.0)
    var anotherThreeDoubles = Array(count:3 ,repeatedValue: 2.5)
    var sixDoubles = threeDoubles + anotherThreeDoubles
    
    [数组操作]
    shoppingList.count      #元素个数
    shoppingList.isEmpty    #是否为空
    shoppingList.append("flower") #追加元素
    shoppingList += "Baking Powder"  #添加元素
    shoppingList +=["str1","str2"]  #添加多个
    var  firstItem = shoppingList[0]  #获取第一个元素
    shoppingList[0] = "Egg2016"  #修改
    shoppingList[4...6] = ["huhu","fafa"]   #修改下标4到6的三个元素为 huhu  , fafa 
    shoppingList.insert("tomato",atIndex: 0)   #在指定位置插入
    let mapleSyrup = shoppingList.removeAtIndex(0)   #删除index位置的元素
    let apples = shoppingList.removeLast()    #删除最后一个元素,他会避免对count属性的查询,推荐使用这个 而不是 removeAtIndex(count-1)
    
    [数组的遍历]
    for  item  in  shoppingList { ... }
    
     #enumerate为每个元素返回一个元组
     for (index,value) in enumerate(shoppingList) {
           println("item \(index+1) : \(value) ")
     }
    

     [字典的定义]
     var airports: Dictionary<String,String> = ["a":"b","c":"d"]
     var airports = ["a":"b","c":"d"]   
     var airports = Dictionary<Int,String>()    #空字典
     airports = [:]  # 空字典字面量[:],前提是字典已经指定了类型
    
     [字典的操作]
     airports["e"] = "f"    #追加,如果key不存在
     airports["e"] = "g" #修改,如果key存在
    
     #updateValue更新某个key对应的值,返回字典值类型的可选
     if let oldValue = airports.updateValue("new value", forKey:"a") {
            println("\(oldValue)")
      }
    
     #删除键值对
     airports["APL"] = nil        #通过设置值为nil来删除键值对
     if let removedValue = airports.removeValueForKey("a"){
          println(" \(removedValue) ")
     }else {
          println("does not contain value for key a")
     }
    
    [字典的遍历]
     for (airportCode,airportName) in airports {
     }
    
     for airportCode in airports.keys { .... }
    
     for airportName in airports.values { .... }
    
     let  airportCodes = Array(airports.keys)
     let  airportValues = Array(airports.values)
    

    十二.流程控制

    [for  index  in   集合]
            for  index  in   1...5      { ... }    
            for  _  in  1...n           { ... }     #下划线来占位,前提是 你需要用到集合中的元素值
            for  arrItem  in  oneArray { ... } 
            for  (code,msg) in  oneDic  { ... }
            for  character in "Hello"   { ... }
    
     =================================
     [for 循环]
      for  var index = 0;index < 3; ++index {  ....  }
    
     =================================
     [while 循环]
      while a < b {
            a++
      }
    
      do{
            a++
      } while  a<b
     =================================
     [if 语句]
      if condition  {
        ...
      }else if condition {
        ...
      }else {
        ...
     }
     =================================
     [switch 语句]
     swift不需要break去结束一个case执行,当然你也可以写,一个case命中执行后就结束了,不会跳转到下一个case。注意,每个case必须要有至少一条执行语句,不能是空的 会编译报错。
    
     let someCharacter: Character = "e"
     switch someCharacter {
       case "a","b","c":
            println("\(someCharacter)  is a  vowel")
       case "d","e","f":
            println("\(someCharacter)  is a  constant")
       default:
             println("default")
    }
    
    关于case支持的格式:
    范围匹配   case 1...3: 
    元组匹配   let somePoint = (1,1)
              switch somePoint {
                case (0,0):
                      println("(0,0) is at the origin")
                case (_,0):
                      println("用_来匹配任何可能的值")
                case (-2...2,-2...2):
                      println("用范围来匹配值")
                default:
                      println("默认命中")
               }
    
    值绑定   switch somePoint {
                case (let x,0):
                      println("\(x) 被绑定了横坐标命中的值")
                case let(x,y):
                      println("获取绑定的值 ( \(x),\(y) ) ")
                default:
                      println("默认命中")
               }
    
     where分句检测额外条件
             switch somePoint {
                case let(x,y) where x==y:
                      println("绑定的值 ( \(x),\(y) ) on the line x == y ")
                default:
                      println("默认命中")
               }
     =================================
     [控制转移语句]
      continue    停止现在的工作继续下次迭代
      break       终止整个流程
      fallthrough switch执行一个case后会结束此次switch,用fall through会执行下一个case
                  switch m {
                       case  "a":
                             XXXXXXX
                             fall through
                       case "b":
                             XXXXXXXX
                       default:
                            XXXXXXXX
                  }
      标签语句
              gameLoop: ******
              continue gameLoop
    

    十三.函数

    [定义]
      #  ->指定函数的返回值
      func sayHello (personName: String) -> String {
            let greeting = "Hello," + personName + "!"
      }
    
     [参数]
      #多参,返回多个返回值
      func count(str: String,str2: String) -> (vowels: Int,consonants: Int,others: Int){
            return (vowels, consonants, others)
      }
    
      #外参,外部参数名可以在函数调用的时候对于参数有更加直观的认识。即该参数名对外部可见。
      import Foundation  
      func sayHello(username name:String)->String{  
            let result = "Hello," + name  
            return result    
      }  
      var nickname:String = "Jack"  
      println(sayHello(username: nickname))   #调用
    
      #同时可以使某个参数名同时是内部参数名和外部参数名:使用#号。
      func sayHello(#name:String)->String{   
          let result = "Hello," + name  
          return result  
      }  
      var nickname:String = "Jack"  
      println(sayHello(name: nickname)) 
    
      #默认行参值,swift会给你定义的默认行参提供一个自动外部名,比如joiner 会有一个外部名 joiner,跟加#类似
      fun join(str1: String,str2: String,joiner: String = "") -> String {
            return str1 + joiner + str2
      }
      join("hello","world")
    
      #
    

    十四.闭包

    十五.枚举

    [定义]
      enum CompassPoint {
            case North
            case South
            case East
            case West
      } 
      
      var directionToHead = CompassPoint.West   #directionToHead就是CompassPoint类型的变量
      directionToHead = .East   #directionToHead的类型是已知的了,所以你可以忽略它的类型来给他赋值了
    
     [使用Switch语句来匹配枚举值]
       directionToHead = .South
       switch directionToHead {
          case .North:
                println("Lots of planets have a north")
          case .South:
                println("Watch out for penguins")
          case .East:
                println("Where the sun rises")
          case .West:
                println("Where the skies are blue")
        }
    
     [关联值]
      enum Barcode {
            case UPCA(Int, Int, Int)
            case QRCode(String)
      } 
      定义了一个叫做Barcode的枚举类型,它可以有一个UPCA成员,这个成员关联了一个包含三个整型数值的元组,同时这个枚举类型还有一个QRCode成员,关联了一个字符串。
    
      var productBarcode = Barcode.UPCA(8, 85909_51226, 3)    #可以用任意其中一个类型来生成一个新的
      productBarcode = .QRCode("ABCDEFGHIJKLMNOP")   #还可以被赋值为另一个类型,一旦定义了变量类型,再次赋值的时候不需要带类型Barcode
    
      switch productBarcode 
      {
        case .UPCA(let numberSystem, let identifier, let check):     #let可以提前 let .UPCA(numberSystem, identifier, check)
               println("UPC-A with value of \(numberSystem), \(identifier), \(check).") 
        case .QRCode(let productCode):    #let .QRCode(productCode)
               println("QR code with value of \(productCode).") 
      } 
    
    [原始值]
      enum ASCIIControlCharacter: Character {
          case Tab = "\t"
          case LineFeed = "\n"
          case CarriageReturn = "\r"
      } 
    
      enum Planet: Int {
              case Mercury = 1, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune
      } 
      let earthsOrder = Planet.Earth.toRaw()    #toRaw()方法来获取他的原始值,eathsOrder is 3 
    
      let possiblePlanet = Planet.fromRaw(7)    #fromRaw()方法来尝试通过一个原始值来寻找他所对应的枚举成员
      # possiblePlanet is of type Planet? and equals Planet.Uranus”
      # possiblePlanet是一个Planet?类型,可能会是nil,因此需要判断:
      let positionToFind = 9
      if let somePlanet = Planet.fromRaw(positionToFind) {  #可选绑定
           switch somePlanet {
                case .Earth:
                        println("ostly harmless")
               default:
                        println("Not a safe place for humans")
           }
       } else {
            println("There isn't a planet at position \(positionToFind)")   #Planet.fromRaw(positionToFind) 如果是 nil ,那么就会走到这
       }
    

    十六.类和结构体

    反馈一个问题:
     binary operator  ===  can not be applied
    [swift语言详解]http://c.biancheng.net/cpp/html/2427.html 在数组的===比较这一块是错误的,恒等用在引用类型上,而数组是值类型,可以看下这个demo:
    
    Paste_Image.png
    [定义]
      struct Resolution {   #Resolution的结构体,用来描述一个显示器的像素分辨率
          var width = 0
          var heigth = 0
      }
      class VideoMode {     #VideoMode的类,用来描述一个视频显示器的特定模式
           var resolution = Resolution()
           var interlaced = false
           var frameRate = 0.0
           var name: String?
      } 
    
      let someResolution = Resolution()
      let vga = resolution(width:640, heigth: 480)
      let someVideoMode = VideoMode() 
    
      someVideoMode.resolution.width = 12880
      print(someResolution.width)
    
    [属性]
     存储属性:
      struct FixedLengthRange {
          var firstValue: Int
          let length: Int
      }
      var rangeOfThreeItems = FixedLengthRange(firstValue: 0, length: 3)
    
     延迟存储属性:
     延迟存储属性是指当第一次被调用的时候才会计算其初始值的属性。在属性声明前使用@lazy来标示一个延迟存储属性。
     必须将延迟存储属性声明成变量(使用var关键字),因为属性的值在实例构造完成之前可能无法得到。
    
    
    class DataImporter {
        /*
        DataImporter 是一个将外部文件中的数据导入的类。
        这个类的初始化会消耗不少时间。
        */
        var fileName = "data.txt"
        // 这是提供数据导入功能
     }
    class DataManager {
        @lazy var importer = DataImporter()
        var data = String[]()
        // 这是提供数据管理功能
    }
    let manager = DataManager()
    manager.data += "Some data"
    manager.data += "Some more data"
    // DataImporter 实例的 importer 属性还没有被创建 
    
    DataManager的一个功能是从文件导入数据,该功能由DataImporter类提供,DataImporter需要消耗不少时间完成初始化:因为它的实例在初始化时可能要打开文件,还要读取文件内容到内存。DataManager也可能不从文件中导入数据。所以当DataManager的实例被创建时,没必要创建一个DataImporter的实例,更明智的是当用到DataImporter的时候才去创建它。由于使用了@lazy,importer属性只有在第一次被访问的时候才被创建。比如访问它的属性fileName时:
      println(manager.importer.fileName)
      // DataImporter 实例的 importer 属性现在被创建了
      // 输出 "data.txt” 
    
    计算属性:
    类、结构体和枚举可以定义计算属性,计算属性不直接存储值,而是提供一个 getter 来获取值,一个可选的 setter 来间接设置其他属性或变量的值。
    struct Point {
        var x = 0.0, y = 0.0
    }
    
    struct Size {
        var width = 0.0, height = 0.0
    }
    
    struct Rect {
        var origin = Point()
        var size = Size()
        var center: Point {
        get {
            let centerX = origin.x + (size.width / 2)
            let centerY = origin.y + (size.height / 2)
            return Point(x: centerX, y: centerY)
        }
        set(newCenter) {   #(newCenter) 可以省略不写,用默认的newValue
            origin.x = newCenter.x - (size.width / 2)    #origin.x = newValue.x - (size.width / 2)
            origin.y = newCenter.y - (size.height / 2)
        }
      }
    }
    var square = Rect(origin: Point(x: 0.0, y: 0.0),size: Size(width: 10.0, height: 10.0))
    let initialSquareCenter = square.center
    square.center = Point(x: 15.0, y: 15.0)
    println("square.origin is now at (\(square.origin.x), \(square.origin.y))")
    // 输出 "square.origin is now at (10.0, 10.0)”
    
    属性监视器:
    暂时不知道哪里用到,先不说了
    
    类型属性:
    略

    相关文章

      网友评论

          本文标题:swift基础知识

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