函数
  • 函数相当于OC中的方法
  • 格式:
    • func 函数名(参数列表) -> 返回值类型 {
          代码块
          return 返回值
      }
    • func 函数名(参数列表){  // 返回值为Void 可以省略
          代码块
          return 返回值
      }
 
  • 常见函数类型

    • // 1.没有参数,没用返回值
      func run() -> Void {
          print("I am running")
      }

      // 如果没用返回值,Void可以写成()
      func run1() -> () {
          print("I am running")
      }
      // 如果没有返回值,后面的内容可以都不写
      func run2() {
          print("I am running")
      }

      // 调用函数
      run2()

      // 2.有参数,没用返回值
      func callPhone(phoneNum : String) {
          print("打电话给\(phoneNum)")
      }
      callPhone("10086")

      // 3.没用参数,有返回值
      func greetings() -> String {
          return "吃饭了吗?"
      }
      var str1 = greetings()
      print(str1)

      // 4.有参数,有返回值
      func sum(num1 : Int, num2 : Int) -> Int {
          return num1 + num2
      }
      var result = sum(20, num2: 30)
      print(result)

  • 函数使用注意

    • 在函数内部可以看到的参数,就是内部参数
    • 在函数外面可以看到的参数,就是外部参数
    • 默认情况下,从第二个参数开始,参数名称既是内部参数也是外部参数
    • 如果第一个参数也想要有外部参数,可以设置标签:在变量名前加标签即可
    • 如果不想要外部参数,可以在参数名称前加_
      • // 默认情况下,从第二个参数开始,参数名称既是内部参数也是外部参数
        func calculate(num1 : Int, num2 : Int, num3 : Int) -> Int {
            return num1 * num2 * num3
        }
        var result1 = calculate(20, num2: 4, num3: 5)

        // 如果第一个参数也想要有外部参数,在变量名前加标签即可,如果不想要,在参数名前加 _
        func calculate1(myNum1 num1 : Int, _ num2 : Int, num3 : Int) -> Int {
            return num1 * num2 * num3
        }
        var result2 = calculate1(myNum1: 20, 4, num3: 5)

        // 方法的重载:方法名称相同,但是参数不同,可以称之为方法的重载
        func calculate(num1: Int, _ num2 :Int) -> Int {
            return num1 * num2
        }
        var result3 = calculate(20, 20)

 
    • 默认参数:某些情况,如果没有传入具体参数,可以使用默认参数

      • func makecoffee(type :String = "卡布奇诺") -> String {
            return "制作一杯\(type)咖啡。"
        }
        print(makecoffee("拿铁"))
        print(makecoffee())
        制作一杯拿铁咖啡。
        制作一杯卡布奇诺咖啡。
 
    • 可变参数:函数的参数个数可以不确定,但必须是相同类型,在参数类型名后面加入(…)来指示这是可变参数

      • func sum(numbers:Double...) -> Double {
            var total: Double = 0
            for number in numbers {
                total += number
            }
            return total
        }

        sum(100.0, 20, 30)
        sum(30, 80)

 
    • 引用类型(指针传递): 默认情况函数的参数是值传递,如果想改变外面的变量,则需要传递变量的地址,swift 提供 inout关键字就可以实现。注意:必须是变量

      • // 函数一:值传递
        func swap(var a : Int, var b : Int) {
            let temp = a;
            a = b;
            b = temp  
            print("a:\(a), b:\(b)")
        }

        var a = 10
        var b = 20
        swap(a, b: b)
        print("a:\(a), b:\(b)")
        a:20, b:10
        a:10, b:20

        // 函数二:指针的传递
        func swap2(inout m : Int, inout n : Int) {
            let temp = m
            m = n
            n = temp
            print("m:\(m), n:\(b)")
        }
        var m = 10
        var n = 20
        swap2(&m, n: &n)
        print("m:\(m), n:\(n)")
        m:20, n:20
        m:20, n:10

 
    • 嵌套函数:swift中可以嵌套函数,但是不推荐使用

      • let value = 55
        func test() {
            func demo() {
                print("value \(value)")
            }
            print("test")
            demo()
        }

        //demo() // 错误
        test()
        test
        value 55

 
类的构造函数

  • 构造函数:

    • 构造函数类似于OC中的初始化方法:init方法
    • 默认情况下创建一个类时,必然会调用一个构造函数,如果没有编写任何构造函数,编译器也会提供一个默认的构造函数。
    • 如果是继承自NSObject,可以对父类的构造函数进行重写
 
  • 构造函数的基本使用
  • 1、类的属性必须有值,如果不是在定义时初始化值,可以在构造函数中赋值
      • class Student1: NSObject {
            var name : String
            var age : Int
           
            // 重写了NSObject(父类)的构造方法
            override init() {
                name = ""
                age = 0
            }
        }

        // 创建一个Student1对象
        let student1 = Student1()

         
 
  • 2、初始化时给属性赋值

    • 我们经常在创建对象是就给属性赋值,可以自定义构造函数
    • 注意:自定义了构造函数会覆盖init()方法,也就不再有默认的构造函数
      • class Student2: NSObject {
            var name : String
            var age : Int
            // 自定义构造函数,会覆盖init()函数
            init(name : String, age : Int) {
                self.name = name
                self.age = age
            }
        }
        // 创建一个Student2对象
        let student2 = Student2(name: "why", age: 18)
 
  • 3、字典转模型(初始化时传入字典)

    • 创建对象时,更多的是将字典转成模型
    • 注意:从字典中取出的是NSObject,任意类型,可以通过 as! 转成需要的类型再赋值(不可以直接赋值)
      • class Student3: NSObject {
            var name : String
            var age : Int
            // 自定义构造函数,会覆盖init()函数
            init(dict : [String : NSObject]) {
                name = dict["name"] as! String
                age = dict["age"] as! Int
            }
        }

        // 创建一个student3对象
        let dict = ["name" : "Siri", "age" : 18]
        let student3 = Student3(dict: dict)
        student3.name  // "Siri"

 
  • 4、字典转模型(利用KVC转化)

    • 利用KVC字典转模型会更加方便
    • 注意:KVC并不能保证会给所有的属性赋值,因此属性必须要有默认值
      • 基本数据类型默认值设置为0
      • 对象或者结构体类型定义为可选类型即可(可选类型没有赋值前为nil)
      • class Student4: NSObject {
            // 结构体或者类的类型,必须是可选类型.因为不能保证一定会赋值
            var name : String?
            // 基本数据类型不能是可选类型,否则KVC无法转化
            var age : Int = 0
            var address : String?
            // 自定义构造函数,会覆盖init()函数
            init(dict : [String : NSObject]) {
                // 必须先初始化对象
                super.init()
                // 调用对象的KVC方法字典转模型
                setValuesForKeysWithDictionary(dict)
            }
        }
        // 创建一个student4对象
        let dict4 = ["name" : "why", "age" : 18]
        let student4 = Student4(dict: dict)
         
                              
 
类的定义
  • 类的定义,可以没有父类,那么该类是rootClass

    • class 类名 : SuperClass {
          // 定义属性和方法
      }
 
类的属性
  • swift中类的属性有三种

    • 存储属性:存储实例的常量和变量
    • 计算属性:通过某种方式计算出来的属性
    • 类属性:与整个类自身相关的属性
 
  • 存储属性

    • class Person {   // 这种定义属性必须写初始值,因为系统不会自动初始化初始值,可选类型除外
         
          var age:Int = 1   // var 关键字修饰变量
         
          let life = 1      // let 修饰常量,不能修改
         
          var name: String?
         
      }

      var person = Person()

      person.age = 20          // 直接通过点运算符读写

      person.name = "Siri"

      print("person的名字是\(person.name), person的生命是\(person.life), person的年龄是\(person.age)")

 
  • 计算属性

    • 并不存储实际的值,而是提供一个getter和一个可选的setter来间接获取和设置其它属性
    • 存储属性一般只提供getter方法
    • 如果只提供getter,而不提供setter,则该计算属性为只读属性,并且可以省略get{}
      • //  注意:计算属性的值是不固定的,只能声明为变量,不能使用let
        class Square {
            var width: Double = 0   // 边长
            var girth: Double {     // 周长 
                get {  
                    returnwidth * 4 
                    }
                set {               // 默认有一个newValue 的值 
                    width = newValue / 4
                    }
                }
            }
        var square = Square()
        square.width = 10
        print(square.girth)   // 调用 girth 属性的 get,输出结果是40
        square.girth = 200
        print(square.width)   // 调用 girth 属性的 set,并且把200传递给 newValue,输出结果是 50
      • // 注意:一个属性不能既是存储属性有事计算属性
        // 只读计算属性:只有get方法,没有set方法
        class Square3 {  
            var girth: Double {   // 周长 
                get {  
                    return40  
                }
            }
        }

        //也可以简写成:
        class Square4 {
            var girth: Double {   // 周长 
                return40
            }
        }

 
 
  • 类属性

    • 所有的类和实例都共有一份类属性.因此在某一处修改之后,该类属性就会被修改
    • 类属性的设置和修改,需要通过类来完成
      • // 类型属性:用类来访问的属性,用class关键字修饰的属性,也可以称为“类属性” 。
        // 特点:一个类只会有一份,类的多个实例对象都共享这唯一的一份。
        // 使用:类型属性不依赖于对象而存在,用类名来访问。
        // 注意:class修饰的类型属性只能是计算属性,不能是存储属性。
        class Circle {
            classvar PI: Double {// 所有用到的PI的值都是一样的,可以写成类属性
                return3.14  
            }
        }
        print("圆周率 = \(Circle.PI)")
 
 
  • 属性监视器

    • 可以监视属性值的修改过程。需要在属性值被修改的时候做出响应的情况可以用属性监视器。计算属性可以在set方法中监听 ,而存储属性没有set,可以为存储属性添加willSet和didSet两个属性监视器。
      • // 属性监视器
        //可以监视属性值的修改过程。需要在属性值被修改的时候做出响应的情况可以用属性监视器。计算属性可以在set方法中监听,而存储属性没有set,可以为存储属性添加willSet和didSet两个属性监视器。
        class Square5 {
            var width: Double = 0.0 {
                 willSet {// willSet 有 newValue
                     print("willSet---new=\(newValue), current=\(width)")
                 }
                 didSet {// oldSet 有 oldValue 
                     print("didSet---old=\(oldValue), current=\(width)")
                 }
             }
         }
      • var square5 = Square5()
        square5.width = 10.0
        willSet---new=10.0, current=0.0
        didSet---old=0.0, current=10.0
 
      • //注意:willSet和didSet在属性初始化过程中不会被调用,只会当属性的值在初始化之外的地方被设置时被调用。也就是在声明时不会引发willSet和didSet的调用
        //如果在didSet方法中修改了属性的值,就不会再引发didSet的调用,也就不会循环引用。
        class Square6 {
            var width: Double = 0.0 {
                willSet {
                }
                didSet {
                    width = 80
                }
            }
        }

        var square6 = Square6()
        square6.width = 40
        print("width=\(square6.width)")  // 打印:width=80.0

 
 
延迟属性
  • 第一次使用时才进行初始化的属性(相当于懒加载),使用关键字 @lazy 来标识一个延时属性。
  • 好处:让某些资源用到时再去加载,避免不必要的资源浪费。
  • 注意:延迟存储属性必须是变量,不能是常量。
    • class Dog {
          var name: String = "timo"
          init() {
              print("你是一条狗")
          }
      }
      class Person1 {   
          var dog: Dog = Dog() 
      }
      class LazyPerson {
          lazyvar dog: Dog = Dog()
      }
      var person1 = Person1() // 会直接打印  你是一条狗
      var lazyPerson = LazyPerson()     // 不会直接打印lazyPerson.dog// 调用才会打印
 
 
 

Swift 学习一函数&函数属性&懒加载的更多相关文章

  1. swift学习第十六天:懒加载和tableView

    懒加载 懒加载的介绍 swift中也有懒加载的方式 (苹果的设计思想:希望所有的对象在使用时才真正加载到内存中) 和OC不同的是swift有专门的关键字来实现懒加载 lazy关键字可以用于定义某一个属 ...

  2. Swift语法基础入门四(构造函数, 懒加载)

    Swift语法基础入门四(构造函数, 懒加载) 存储属性 具备存储功能, 和OC中普通属性一样 // Swfit要求我们在创建对象时必须给所有的属性初始化 // 如果没办法保证在构造方法中初始化属性, ...

  3. Spring5.0源码学习系列之浅谈懒加载机制原理

    前言介绍 附录:Spring源码学习专栏 在上一章的学习中,我们对Bean的创建有了一个粗略的了解,接着本文挑一个比较重要的知识点Bean的懒加载进行学习 1.什么是懒加载? 懒加载(Lazy-ini ...

  4. 【转】ViewPager学习笔记(一)——懒加载

    在项目中ViewPager和Fragment接口框架已经是处处可见,但是在使用中,我们肯定不希望用户在当前页面时就在前后页面的数据,加入数据量很大,而用户又不愿意左右滑动浏览,那么这时候ViewPag ...

  5. js学习之原生js实现懒加载

    <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...

  6. @Basic表示一个简单的属性 懒加载,急加载

    5.@Basic(fetch=FetchType,optional=true) 可选 @Basic表示一个简单的属性到数据库表的字段的映射,对于没有任何标注的getXxxx()方法,默认 即为 @Ba ...

  7. [转]ViewPager学习笔记(一)——懒加载

    在项目中ViewPager和Fragment接口框架已经是处处可见,但是在使用中,我们肯定不希望用户在当前页面时就在前后页面的数据,加入数据量很大,而用户又不愿意左右滑动浏览,那么这时候ViewPag ...

  8. Vue-Router学习第二弹动态路由\懒加载\嵌套路由

    在我们做项目时肯定会有出现动态路由: 举个栗子: 一个品种的商品页面会有同类不同样的商品就要在路由的后面加一个id: Vue的路由id是这样添加的: 两种动态路由 一种是params参数添加: 首先现 ...

  9. jQuery延迟加载(懒加载)插件 – jquery.lazyload.js-Web前端(W3Cways.com) - Web前端学习之路

    Lazy Load 是一个用 JavaScript 编写的 jQuery 插件. 它可以延迟加载长页面中的图片. 在浏览器可视区域外的图片不会被载入, 直到用户将页面滚动到它们所在的位置. 这与图片预 ...

随机推荐

  1. python主要用来做什么

    python这门编程语言在国外极受欢迎,但在国内使用还不是极普遍. 由于python编程效率极高,现在国内的使用者也开始变得越来越多. python主要用来做什么?这个语言到底有哪些作用呢? 下面主是 ...

  2. java定时器和多线程实践记录

    这几天因为需要测试mongodb读写分离的问题,因此写了个定时查询程序,并且用到了多线程,以达到定时启动多个线程查询数据库的效果,下边代码记录备忘: package timmer; import ja ...

  3. 单源最短路径——Floyd算法

    正如我们所知道的,Floyd算法用于求最短路径.Floyd算法可以说是Warshall算法的扩展,三个for循环就可以解决问题,所以它的时间复杂度为O(n^3). Floyd算法的基本思想如下:从任意 ...

  4. PUA

    约会技巧 kino技巧 被拒绝的应对方法 (1)一般约会7个小时后,就能带女生回家 (2)点菜时多点一点,以回家放菜为名 (3)理由要文雅 (4)开酒店的理由 第一时间触碰测试 (1)第一次约会要第一 ...

  5. iphone dev 入门实例6:How To Use UIScrollView to Scroll and Zoom and Page

    http://www.raywenderlich.com/10518/how-to-use-uiscrollview-to-scroll-and-zoom-content Getting Starte ...

  6. codeforces 323A. Black-and-White Cube 构造

    输入n 1 <= n <= 100 有一个n * n * n 的立方体,由n ^ 3 个1 * 1 * 1 的单位立方体构成 要用white 和 black 2种颜色来染这n ^ 3个立方 ...

  7. LPC1768之ISP

    一 使用到的芯片内部资源: 1必须是P2.10 2RESET引脚 3必须是串口0 4使用FLASH magic工具. 二操作方法: 先按下reset不放,然后按下ISP,抬起reset,抬起ISP就能 ...

  8. js让iframe高度自动

    HTML: <iframe id="yb_if" width="940px" src="连接" frameborder=0 allow ...

  9. 无状态服务(stateless service)

    一.定义 无状态服务(stateless service)对单次请求的处理,不依赖其他请求,也就是说,处理一次请求所需的全部信息,要么都包含在这个请求里,要么可以从外部获取到(比如说数据库),服务器本 ...

  10. 深入ThreadLocal之三(ThreadLocal可能引起的内存泄露)

    threadlocal里面使用了一个存在弱引用的map,当释放掉threadlocal的强引用以后,map里面的value却没有被回收.而这块value永远不会被访问到了. 所以存在着内存泄露. 最好 ...