- 函数相当于OC中的方法
- 格式:
- func 函数名(参数列表) -> 返回值类型 {
代码块
return 返回值
} - func 函数名(参数列表){ // 返回值为Void 可以省略
代码块
return 返回值
}
- func 函数名(参数列表) -> 返回值类型 {
- 常见函数类型
- // 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)
- // 1.没有参数,没用返回值
- 函数使用注意
- 在函数内部可以看到的参数,就是内部参数
- 在函数外面可以看到的参数,就是外部参数
- 默认情况下,从第二个参数开始,参数名称既是内部参数也是外部参数
- 如果第一个参数也想要有外部参数,可以设置标签:在变量名前加标签即可
- 如果不想要外部参数,可以在参数名称前加_
- // 默认情况下,从第二个参数开始,参数名称既是内部参数也是外部参数
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 makecoffee(type :String = "卡布奇诺") -> String {
- 默认参数:某些情况,如果没有传入具体参数,可以使用默认参数
- 可变参数:函数的参数个数可以不确定,但必须是相同类型,在参数类型名后面加入(…)来指示这是可变参数
- 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)
- func sum(numbers:Double...) -> Double {
- 可变参数:函数的参数个数可以不确定,但必须是相同类型,在参数类型名后面加入(…)来指示这是可变参数
- 引用类型(指针传递): 默认情况函数的参数是值传递,如果想改变外面的变量,则需要传递变量的地址,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 提供 inout关键字就可以实现。注意:必须是变量
- 嵌套函数:swift中可以嵌套函数,但是不推荐使用
- let value = 55
func test() {
func demo() {
print("value \(value)")
}
print("test")
demo()
}//demo() // 错误
test()
test
value 55
- let value = 55
- 嵌套函数:swift中可以嵌套函数,但是不推荐使用
- 构造函数:
- 构造函数类似于OC中的初始化方法:init方法
- 默认情况下创建一个类时,必然会调用一个构造函数,如果没有编写任何构造函数,编译器也会提供一个默认的构造函数。
- 如果是继承自NSObject,可以对父类的构造函数进行重写
- 构造函数的基本使用
- 1、类的属性必须有值,如果不是在定义时初始化值,可以在构造函数中赋值
- class Student1: NSObject {
var name : String
var age : Int
// 重写了NSObject(父类)的构造方法
override init() {
name = ""
age = 0
}
}// 创建一个Student1对象
let student1 = Student1()
- class Student1: NSObject {
- 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)
- class Student2: NSObject {
- 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"
- class Student3: NSObject {
- 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 {
// 定义属性和方法
}
- 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)")
- class Person { // 这种定义属性必须写初始值,因为系统不会自动初始化初始值,可选类型除外
- 计算属性
- 并不存储实际的值,而是提供一个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
}
}
- // 注意:计算属性的值是不固定的,只能声明为变量,不能使用let
- 类属性
- 所有的类和实例都共有一份类属性.因此在某一处修改之后,该类属性就会被修改
- 类属性的设置和修改,需要通过类来完成
- // 类型属性:用类来访问的属性,用class关键字修饰的属性,也可以称为“类属性” 。
// 特点:一个类只会有一份,类的多个实例对象都共享这唯一的一份。
// 使用:类型属性不依赖于对象而存在,用类名来访问。
// 注意:class修饰的类型属性只能是计算属性,不能是存储属性。
class Circle {
classvar PI: Double {// 所有用到的PI的值都是一样的,可以写成类属性
return3.14
}
}
print("圆周率 = \(Circle.PI)")
- // 类型属性:用类来访问的属性,用class关键字修饰的属性,也可以称为“类属性” 。
- 属性监视器
-
可以监视属性值的修改过程。需要在属性值被修改的时候做出响应的情况可以用属性监视器。计算属性可以在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
- //注意:willSet和didSet在属性初始化过程中不会被调用,只会当属性的值在初始化之外的地方被设置时被调用。也就是在声明时不会引发willSet和didSet的调用
- 第一次使用时才进行初始化的属性(相当于懒加载),使用关键字 @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// 调用才会打印
- class Dog {