Swift初体验

Swift语言是苹果在2014发布的,而且苹果力推开发者使用其来开发APP。所有在此提供一套Swift2.0中文手册供大家使用

:!Swift 2.0 中文手册.pdf

swift 中布局十分严格 切记要注意   左右一定要对称

使用注意:

  • 1.语句末尾不用使用 ;
  • 2.在 Swift 中使用 print() 替代 OC 中的 NSLog
  • 3.在swift中访问属性和调用方法都是通过.来进行的
  • 4.在 Swift 中要实例化一个对象可以使用 类名() 的格式,与 OC 中的 alloc/init 等价
  • 5.OC 中的 [[类名 alloc] initWithXXX],  [类名 类名WithXXX]在 Swift 中通常可以使用 类名(XXX: )找到对应的函数
  • 6.OC 中的 [UIColor redColor] 类方法,在 Swift 中通常可以使用 类名.XXX() 找到对应的函数

1.变量和常量

2.类型推导和类型装换

自动推导

  • swift 对数据类型要求异常严格
  • swift能够根据右边的代码,推导出变量的准确类型
  • 如果要指定变量,可以在变量名后使用 : 类型
  • Int类型分为好几种,Int8, Int16, Int32, Int64,因为类型严格,Int8和Int16不能进行运算,所以建议以后开发中都使用Int

3.字符串 String

  • 是一个结构体,性能高于NSString
  • String 支持直接遍历
  • String 目前具有了绝大多数 NSString 的功能
  • String和NSString转换方便

     

  • OC定义字符串

    /*:
      OC的字符串:
          NSString *str = @"hello";
          格式化字符串: [NSString stringWithFormat:@"%.02f", 3.14159]
      swift中定义字符串:
          var 变量名 = "hello"
    */
  • 字符串中的常用方法

4.Optional可选

 

5.if条件分支

6.循环

7.switch

8.数组

9.元组

10.字典

11.枚举

12函数

  • 函数的定义

    func 函数名(形参名1: 形参类型1, 形参名2: 形参类型2, ...) `->` 返回值 {
      // 代码实现
    }
    /*函数如果没有返回值:
          1. 省略
          2. -> Void
          3. -> ()
    
      外部参数名,作用能够方便调用人员更好地理解函数的语义
      带外部参数名的参数列表格式:
          (外部参数名1 形式参数名1: 参数类型1, 外部参数名2 形式参数名2: 参数类型2, ...)*/
    
  • 函数定义和调用

    //: 定义函数
    func sum(a: Int, b: Int) -> Int {
      return a + b
    }
    //: 调用函数, b表示外部参数名
    sum(10, b: 20)
    //: 没有返回值
    func sayHello() -> () {
      print("hello")
    }
    sayHello()
    
  • 外部参数名

    • 在形参名前再增加一个外部参数名,能够方便调用人员更好地理解函数的语义
    • swift2.0默认帮我们生成除第一个参数外的所有外部参数名
//: 为什么有外部参数名呢?
func addStudent(name: String, age: Int, number: Int) {
    print("name = (name), age = (age), number = (number)")
}

//: 如果没有外部参数名,我们很难判断每个参数的作用
//addStudent("liudehua", 54, 53)

//: 有外部参数名,每个参数的作用一目了然,swift2.0默认帮我们生成除第一个参数外的所有外部参数名
addStudent("liudehua", age: 54, number: 53)

//: 指定外部参数名
func addStudent2(stu_name name: String, stu_age age: Int, stu_number number: Int) {
    print("name = (name), age = (age), number = (number)")
}

addStudent2(stu_name: "liudehua", stu_age: 54, stu_number: 53)
  • 函数返回元组类型
    /*:
    在c语言中要返回多个值:
      1.传参数时传入指针,在函数内部修改该指针指向的值
      2.返回一个结构体
      3.返回数组
    */
    //: 在swift中可以通过返回元组来方便的返回多个值
    func getStudent() -> (String, Int, Int) {
      return ("liudehua", 54, 53)
    }
    //: student是一个(String, Int, Int)的元组
    let student = getStudent()
    //: 可以通过.0 .1 来访问
    student.0
    student.1
    //: 函数通过元组返回多个值,并且为元组中的元素取名成,方便调用
    func getStudent2() -> (name: String, age: Int, num: Int) {
      return ("liudehua", 54, 53)
    }
    let student2 = getStudent2()
    student2.name
    student2.age

闭包

       闭包类似于 OC 中的 Block,是一段预先定义好的代码,在需要时执行

定义

  • 闭包表达式格式:

      { (形参名称1: 形参类型1, 形参名称2: 形参类型2, ...) -> 返回值 `in`
              //要执行的代码
      }
    
    • in 用于区分闭包定义和代码实现

    定义闭包

    // 定义闭包
    var closure = { (text: String) -> Void in
    }  

    调用闭包

    // 调用闭包
    closure("学习闭包")

闭包使用场景(回调)

  • 模拟耗时操作

      // 闭包的使用场景: 回调
      // 在子线程执行完任务后通知调用者
      func loadData(finished: (result: String) -> Void) {
          dispatch_async(dispatch_get_global_queue(0, 0)) { () -> Void in
              print("拼命加载数据: (NSThread.currentThread())")
    
              dispatch_async(dispatch_get_main_queue(), { () -> Void in
                  print(": (NSThread.currentThread())")
                  // 通知调用者
                  finished(result: "获取到20条数据")
              })
          }
      }
    
  • 调用

    loadData { (result) -> Void in
      print("网络请求完成: (result)")
    }

类的定义

  • OC中的类

    OC中一个类包涵.h和.m两个文件
      .h:
          @interface 类名: 父类名
          @end
    
      .m:
          @implement 类名
          @end
    
      实例化类:
          类名 *变量名 = [[类名 alloc] init];
    
  • swift 定义类格式

    • ()里面是空,表示调用类的默认构造函数 = [[类名 alloc] init];
    • swift中访问属性通过点语法来访问, 方法也是通过点语法来调用
    • 继承和OC一样,通过 : 来继承, swift也只有单继承

      class 类名: 父类名 {
            //: 一些属性
            //: 一些方法
        }
      
        实例化一个类:
        var 变量名 = 类名()
      
      注意:
        1swift的继承和oc一样是通过:, swift也只有单继承
        2.访问类的属性和调用类的方法都是通过.来进行的
        3.覆盖父类方法, 需要加关键字 override
      
  • 定义Person类:

    //: 定义一个类, 没有继承任何类的类,称之为 基类,超类
    class Person: NSObject {
      // 名称属性
      var name = "liudehua"
      // 年龄
      var age = 54
      // 身高
      var height = 1.78
      // 体重
      var weight = 70.0
      // 方法
      func sleep() {
          print("累了,睡觉")
      }
      func eat() {
          print("饿了,吃饭")
      }
    }
    
  • 实例化Person

    // 实例化类Person
    var p = Person()
    // 访问属性
    print(p.name)
    // 修改属性
    p.name = "zhangsan"
    print("名称修改后:(p.name)")
    // 调用方法
    p.sleep()
    
  • 定义Student继承Person

    //: 继承 和OC 一样通过 : 来实现继承
    class Student: Person {
      // 班级属性
      var grade = "ios05期"
    
      // 定义学习方法
      func study() {
          print("开开心心学习,高薪就业")
      }
    
      // 覆盖父类方法, 需要加关键字 override
      override func sleep() {
          print("学习累了,睡觉")
      }
    }
    
  • 实例化Student 

    // 实例化Student
    let s = Student()
    print(s.grade)
    // 调用Student的sleep
    s.sleep()

类的属性

  • oc中的属性:
    • @property(noatomic, copy) NSString *name;
      • 1.在.h声明 getter 和 setter 方法
      • 2.在.m实现 getter 和 setter 方法
      • 3.在.m生成 _成员变量
  • 存数型属性: 存储数据
    • 属性监视器: 当存储型属性发生改变的时候,通知我们属性发生了改变
      • willSet: 在属性将要发生改变时调用
      • didSet: 在属性已经发生改变时调用
  • 计算型属性: 不存储任何数据,通过get方法来返回一个计算好的数据通过set方法来设置一个存储型属性的值,当只提供get方法时,称之为只读计算属性.必须要有get方法

    • 计算型属性 相当于 OC 中的 @property 生成的 getter 和 setter 方法,只不过 setter 方法没有给 _成员变量 赋值

        @interface Person ()
      
        @property (nonatomic, assign) CGFloat heightCM;
      
        @end
      
        @implementation Person
      
        // getter
        - (CGFloat)heightCM {
            return ;
        }
      
        // setter
        - (void)setHeightCM:(CGFloat)heightCM {
            // 没有 _heightCM = heightCM
        }
      
  • 类属性: 不管创建多少个实例,都共享这个属性

    • 定义:在类属性前面加class关键字,类属性只能是计算型属性
    • 访问方法: 类名.属性名

存储型属性、计算型属性

class Person {
  //: 存储型属性
  var name = "liudehua"
//
  //: 存储型属性,单位是m
  var height = 1.74
//
  //: 计算型属性
  var heightCM: Double {
      get {
          return height * 100
      }

      set {
          height = newValue / 100
      }
  }
//
  //: 存储型属性
  var age = 54
//
  //: 存储型属性
  var weight: Float = 70 {
    //: 在属性将要发生改变时调用 willSet { print("weight willSet") }     //在属性已经发生改变时调用 didSet { print("weight didSet") } } // //: 定义一个sleep方法 func sleep() { print("person 累了, sleep...") } // //: 定义一个eat方法 func eat() { print("person 饿了, eat...") } } // 实例化Person var person = Person() person.height person.heightCM = 178 person.height person.weight = 72 var person2 = Person() //: person的weight属性和person2的weight没有关系,相互独立的. person2.weight = 60 print(person2.weight)

类属性

//: 定义圆
class Circle {
  //: 只要是圆就有圆周率,圆周率的值固定不变,不管创建多少个实例,都共享这个圆周率属性
  //: 类型属性: 只读计算型属性
  class var pi: Double {
      return 3.141592653
  }
//
  var radius = 20.0
//
  //: 周长,只读计算型属性
  var perimeter: Double {
      return 2 * Circle.pi * radius
  }
}
//
//Circle.pi = 1
//
var pingpong = Circle()
pingpong.perimeter
//
pingpong.radius = 40
pingpong.perimeter

构造函数

自定义 Car 对象

class Person {
    var name: String
}
  • 以上代码会报:“存储性属性没有初始化值”,原因是在swift中类实例化后,所有的存储型属性必须有值

  • 解决方法1:定义属性时赋值

    class Person {
      // 直接赋值
      var name: String = "liudehua"
    }
    // 实例化
    var p1 = Person()
    p1.name
    // 实例化
    var p2 = Person()
    p2.name
    //: 实例化出来对象 name属性都一样,显然不合理.
    
  • 解决方法2:将对象属性类型设置为 Optional
    class Person {
      var name: String?
    }
    var p = Person()
    p.name = "liudehua"
    print(p.name)
    //: 用可选的,打印出来都带Optional
    
  • 输出结果:Optional("liudehua")
  • 有没有什么办法,在类的实例化过程中,给存储型属性设置指定的值?,实例化后直接拿来用.或者在类实例化时指定存储型属性的值

利用 init 函数为属性初始化

  • 在swift中对象是通过构造函数来实例化的.构造函数的作用:在对象实例化过程中给所有的存储型属性设置初始值,并且执行必要的准备和初始化任务.
class Person: NSObject {
   var name: String

    var age: Int

    //: 重写父类构造函数
    override init() {
        print("init")
        name = "liudehua"
        age = 22
    }
}

重载构造函数

  • swift 中支持函数重载,同样的函数名,不一样的参数类型
//: 重载构造函数
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }

子类构造函数

  • 自定义子类时,需要在构造函数中,首先为本类定义的属性设置初始值
  • 再调用父类的构造函数,初始化父类中定义的属性
  • 如果子类没有去实现构造函数,会继承父类的构造函数
  • 如果子类实现了构造函数,不会继承父类的构造函数
class Stuent: Person {
    var grade: String

    // 子类构造函数需要调用父类构造函数
    // 需要先初始化子类属性,在调用父类构造函数
    init(name: String, age: Int, grade: String) {
        self.grade = grade
        super.init(name: name, age: age)
    }
}

convenience 构造函数

便利构造函数: 它是辅助性的构造函数.方便创建对象

  • 默认情况下,所有的构造函数都是指定构造函数 Designated
  • convenience 关键字修饰的构造方法就是便利构造函数
  • 便捷构造函数可以返回 nil
  • 需要调用本类的一个指定构造函数
    /// 方便创建ios05期学生
    convenience init?(stuName: String, stuAge: Int) {

        // 判断age是否合法
        if stuAge < 0 || stuAge > 130 {
            print("年龄不合法")
            return nil
        }

        self.init(name: stuName, age: stuAge, grade: "ios05期")
    }

构造函数小结

  • 1.不需要func关键字.名称是固定的,都叫 init
  • 2.当类没有实现构造函数时,系统会添加一个默认的构造函数.
  • 3.如果实现了构造函数,系统就不会添加默认构造函数
  • 4.如果子类没有实现构造函数.会继承父类的构造函数
  • 5.子类构造函数需要调用父类构造函数
  • 6.需要先初始化子类属性,在调用父类构造函数
  • 7.子类一旦实现了构造函数.就不会继承父类的构造函数

懒加载

在 iOS 开发中,懒加载是无处不在的

  • 方法1

    lazy var p = Person()
    
  • 方法2

    // 方法2, 需要指定p的类型
    lazy var p: Person = {
      let person = Person()
      return person
    }()
    
  • 测试调用

    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
      p.name = "lisi"
      print("p.name: (p.name)")
    }
    
  • Person 类

    class Person: NSObject {
      var name: String?
    
      override init() {
          print("初始化")
      }
    }
 
原文地址:https://www.cnblogs.com/YRFios/p/4984645.html