swift之属性与单例模式

14 篇文章 0 订阅

一、属性

1.1-swift中的属性

/*
存储属性
	类似于成员属性的概念
	存储在实例的内存中
	结构体、类可以定义存储属性
	枚举不可定义存储属性
计算属性
	本质就是方法(函数)
不占用实例的内存
*/
struct Test {
    var value:Double
    var calculate:Double{
        set {
            value = newValue+1
        }
        get{
            value-1 //单一计算忽略return
        }
    }
}
var test = Test(value:10)
print(test.value)
print(test.calculate)
test.calculate=20
print(test.value)
print(test.calculate)
10.0
9.0
21.0
20.0

1.2-存储属性

/*
存储属性:
	在创建类或者结构体的实例时,必须为所有的存储属性设置一个合适的初始值
	可以在构造函数(初始化器)里为存储属性谁在一个初始值
	可以分配一个默认的属性值做为属性定义的一部分
*/
struct Test {
    var value:Double = 1
}
var test = Test()
print(test.value)
1.0

1.3-计算属性

/*
计算属性:
	set传入的新值默认叫做newValue,也可以自定义
	只读计算属性:只有get没有set(有set不能没有get)
	定义计算属性只能用var不能用let(let代表常量:值是一成不变的)
	计算属性的值是可以发生变化的(即使是只读计算属性)
*/
struct Test {
    var value:Double
    var calculate:Double{
        set (testNew){
            value = testNew+1
        }
        get{
            value-1
        }
    }
}
var test = Test(value:10)
print(test.value)
print(test.calculate)
10.0
9.0

//只读计算属性
struct Test {
    var value:Double
    var calculate:Double{
        get{
            value-1
        }
    }
}

1.4-枚举rawValue原理

//枚举原始值rawValue本质是只读计算属性
enum Test:Int {
    case up=1,down=2,left,right
    var rawValue:Int{
        switch self {
        case .up:
            return 11
        case .down:
            return 22
        case .left:
            return 33
        case .right:
            return 44
        }
    }
}
print(Test.right.rawValue)
44

1.5-延迟存储属性

/*
延迟存储属性:
	使用lazy可以定义一个延迟存储属性,在第一次调用到属性的时候才会进行初始化
	lazy属性必须是var(let必须在实例的初始化方法完成之前就拥有值)
	如果多条线程同时第一次访问lazy属性时,无法保证属性只被初始化一次
	当结构体包含一个延迟存储属性时,只有var才能访问延迟存储属性
	因为延迟存储属性初始化时需要改变结构体的内存
*/
class Car{
    init(){
        print("car init.")
    }
    func run(){
        print("car is running.")
    }
}
class Person{
    lazy var car = Car()
    init() {
        print("person init.")
    }
    func go(){
        car.run()
    }
}
let p = Person()
print("-----")
p.go()
person init.
-----
car init.
car is running.
//如果没有lazy则输出:
car init.
person init.
-----
car is running.


//经典例子,调用资源的时候需要用到才调用
class PhotoView{
	lazy var image:Image={
		let url="http://www.test.com/1.jpg"
		let data = Data(url:url)
		return Image(data:data)
	}
}

1.6-属性观察器

/*
可以为非lazy的var存储属性设置属性观察器,
willSet在set即将赋值之前调用,didSet在赋值之后调用
set/get和willSet/didSet不能同时使用
在构造函数(初始化器)中设置属性值不会触发willSet和didSet
willSet新值newValue,didSet旧值oldValue
在属性定义时设置初始值也不会触发
*/

1.7-全局变量局部变量

/*
属性观察器、计算属性的功能,同样可以应用在全局变量、局部变量中
*/

1.8-inout详解

inout(输入参数、指针传递、引用传递)

struct Test {
    var a:Int
    
    var b:Int{
        set {
            a = newValue/2
            print("set b value ",newValue)
        }
        get {
            print("get b")
            return a * 2
        }
    }
    func show(){
        print("a value:\(a),b value:\(b)")
    }
    
}

func test(_ num:inout Int) -> Void{
    num = 20
}

var t=Test(a:30)
test(&t.a)
t.show()
    0x100000b1f <+111>: leaq   -0x30(%rbp), %rsi  //将Test.a的地址池引用传递给test函数
    0x100000b23 <+115>: movl   $0x20, %edx
test(&t.b)
t.show()
	0x100001563 <+83>:  callq  0x100001620               ; test.Test.b.getter : Swift.Int at main.swift:63
    0x100001570 <+96>:  callq  0x100001bf0               ; test.test(inout Swift.Int) -> () at main.swift:74
    0x100001580 <+112>: callq  0x100001770               ; test.Test.b.setter : Swift.Int at main.swift:59
//如果是计算属性,会先调用test()之前先调用Test.b.get()方法放到临时的局部变量,并传到test(),将值修改后放回局部变量里,再根据新值调用Test.b.set()方法。

/*
总结:
	1、如果实参有物理内存地址,且没有设置属性观察器,直接将实参的内存地址传入函数(实参进行引用传递)
	2、如果实参是计算属性或者设置了属性观察器,采取copy in copy out的做法,调用该函数时,先复制实参的值,产生副本get,将副本的内存地址传入函数进行引用传递,在函数内部可以修改副本的值,函数返回后再将副本的值覆盖实参的值set。
本质是引用传递(地址传递)
*/

1.9-类型属性

/*
属性可以分为:
	实例属性:只能通过实例去访问
		存储实例属性,存储在实例的内存中,每个实例都有一份
		计算实例属性
	类型属性:只能通过类型去访问
		存储类型属性,整个程序运行过程中,就只有一份(类似全局变量)
		计算类型属性
		
可以通过static定义类型属性
如果是类,也可以用关键字class
*/
class Test{
	static var count:Int = 0
	init(){
		Test.count += 1
	}
}
let t1 = Test()
let t2 = Test()
let t3 = Test()
print(Test.count)
3

/*
不同于存储实例属性,必须给存储类型属性设置初始值,因为类型没有像实例那样init初始化器来初始化存储属性

存储类型属性默认就是lazy,会在第一次使用的时候才初始化
就算被多个线程同时访问,保证只初始化一次
存储类型属性可以是let

枚举类型也可以定义类型属性(存储类型属性、计算类型属性)
*/

二、单例模式

public class FileManager{
	public static let shared = FileManager()
	private init(){}
}

public class FileManager{
	public static let shared = {
		//...
		//...
		return FileManager()
	}()
	private init(){}
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值