函数
  • 函数相当于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. MSSQL update 多表关联更新

    update tMeter set 字段= t.源自段 from ( select * from 源表信息 ) t where 关联条件 实际demo: UPDATE dbo.WX_TWODIMENC ...

  2. 进程间通信IPC之--共享内存

    每个进程各自有不同的用户地址空间,任何一个进 程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲 区,进程1把数据从用户空间拷到内核缓冲区,进程2再从内核缓冲 ...

  3. Nginx_地址重写(rewrite)_日志管理(log_format)_压缩输出_Nginx设定限速_Nginx设置反向代理及反向代理缓存

    Nginx地址重写 Nginx rewrite rewrite语法规则1).变量名可以使用 "=" 或 "!=" 运算符~ 区分大小写~* 不区分大小写^~ 禁 ...

  4. win7 Android环境搭配

    Eclipse环境 第一步:下载JDK http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.h ...

  5. HDU - 5685 Problem A(逆元)

    这题我第一次想的就是直接模拟,因为我是这样感觉的,输入n是3次方,长度是5次方,加起来才8次方,里面的操作又不复杂,感觉应该能过,然而不如我所料,TLE了,玛德,这是第一次的代码. #include ...

  6. cf380D Sereja and Cinema 组合数学

              time limit per test 1 second memory limit per test 256 megabytes input standard input outp ...

  7. cf 605B B. Lazy Student 构造 好题

    题意: 一个n个节点的图,有m条边,已知这个图的一个mst 现在如果我们知道这个图的m条边,和知道mst的n-1条边是哪些,问能不能构造出一个满足条件的图 思路:排序+构造 数组deg[i]表示节点i ...

  8. ADO.NET(完整修改和查询、实体类,数据访问类)

    一.完整修改和查询 在编写c#语句时需考虑到用户体验,例如在编写修改语句时,需要考虑到输入的内容在数据库中是否能够找到. 中间变量运用. 1.先查 2.执行操作 完整修改语句: bool has = ...

  9. 查看iis错误日志时提示找不到 freb.xsl的解决方法

    http://stackoverflow.com/questions/786638/how-can-i-get-gzip-compression-in-iis7-working/787251 Look ...

  10. mysql事务与mysql储存引擎

    事务概念及存储引擎 1.0 为何要事务? 先来看一个场景,银行转账汇款: 李彦宏和周鸿祎天天打架,现在让李彦宏给周鸿祎转款1000 元 设计如下表 account表 编号(id)用户名(user)金额 ...