- 类和结构体示列
struct Resolution {
var waith:Double
var height:Double
/* volume 创建只读属性 可以去掉 get 关键字和花括号 */
var volume: Double {
return waith*height
}
}
class VideoMode {
/* lazy:延迟存储属性 只有在第一次被访问的时候才被创建*/
lazy var resolution = Resolution(waith: 0.0, height: 0.0)
var interlaced = false
var frameRate: Int = 10
/* static 无论创建了多少个该类型的实例,这些属性都只有唯一一份*/
static var name: String?
/* sizeMax 是计算属性*/
var sizeMax: Int {
get{
return frameRate*2
}
set(newSizeMax){
frameRate = newSizeMax/2
}
}
}
let someResolution = Resolution(waith: 0.0, height: 0.0)
let someVideoMode = VideoMode()
- 属性观察器
-
willSet
在新的值被设置之前调用
观察器会将新的属性值作为常量参数传入,在willSet
的实现代码中可以为这个参数指定一个名称,如果不指定则参数仍然可用,这时使用默认名称newValue
表示。 -
didSet
在新的值被设置之后立即调用
观察器会将旧的属性值作为参数传入,可以为该参数命名或者使用默认参数名oldValue
。如果在didSet
方法中再次对该属性赋值,那么新值会覆盖旧的值。
class StepCounter {
var totalSteps: Int = 0 {
willSet(newTotalSteps) {
print("About to set totalSteps to \(newTotalSteps)")
}
didSet {
if totalSteps > oldValue {
print("Added \(totalSteps - oldValue) steps")
}
}
}
}
let stepCounter = StepCounter()
stepCounter.totalSteps = 200
// About to set totalSteps to 200
// Added 200 steps
stepCounter.totalSteps = 360
// About to set totalSteps to 360
// Added 160 steps
- 在实例方法中修改值类型 - mutating
- 结构体和枚举是值类型。默认情况下,值类型的属性不能在它的实例方法中被修改。
struct UPoint {
var x = 0.0, y = 0.0
mutating func moveByX(x deltaX: Double, y deltaY: Double) {
x += deltaX
y += deltaY
// self = UPoint(x: x + deltaX, y: y + deltaY) 结果同上
}
}
var someUPoint = UPoint(x: 1.0, y: 1.0)
someUPoint.moveByX(x: 2.0, y: 3.0)
print("The point is now at (\(someUPoint.x), \(someUPoint.y))")
// 打印 "The point is now at (3.0, 4.0)"
- 实例方法(-号方法)和类型方法 (+号方法)
- 实例方法
class Counter {
var count = 0
func increment() {
count += 1
}
}
let counter = Counter()
counter.increment()
- 类型方法
class Square {
// 类型属性,用class关键字
class var PI: Double{
return 3.14
}
/* 1. 在类中,需要注意的是,存储属性不能使用class进行修饰,用static就可以了
2. 协议和结构体的类型也用static修饰 */
static var phone: String?
}
print(Square.PI)
- 下标语法 - subscript
struct TimesTable {
let multiplier: Int
subscript(index: Int) -> Int {
return multiplier * index
}
}
let threeTimesTable = TimesTable(multiplier: 3)
print("six times three is \(threeTimesTable[6])") // 打印 "six times three is 18"
- 继承
class Vehicle {
var currentSpeed = 0.0
// final 防止重写修饰
final var name:String?
func makeNoise() {
}
var description: String {
return "traveling at \(currentSpeed) miles per hour"
}
}
class SomeClass: Vehicle {
var gear = 1
// 重写父类方法 override修饰
override func makeNoise() {
// 访问父类方法实现
super.makeNoise()
}
// 重写属性
override var description: String {
return super.description + " in gear \(gear)"
}
// 重写属性观察器
override var currentSpeed: Double {
didSet {
gear = Int(currentSpeed / 10.0) + 1
}
}
}
- 构造方法
class AgeClass{
}
class Food {
var name: String
/* unowned 无主引用不会牢牢保持住引用的实例 当AgeClass销毁时Food也会自行销毁*/
unowned let age: AgeClass
/* 可选属性不需要在构造函数里赋值 */
var response: String?
/* weak 弱引用不会对其引用的实例保持强引用 */
weak var ageData: AgeClass?
/* required修饰的构造器 表明所有该类的子类都必须实现该构造器,且子类也要加required修饰而不需要添加override修饰符 */
required init(name: String, age:AgeClass) {
self.name = name
self.age = age;
}
/* 便利构造器 */
convenience init() {
self.init(name: "[Unnamed]",age:AgeClass())
}
/* 当一个类的实例被释放之前,析构器会被立即调用 */
deinit {
// 执行析构过程
}
}
- 可选链
class Person {
var residence: Residence?
var name: String?
}
class Residence {
var numberOfRooms = 1
}
let john = Person()
/* name可选,强制展开*/
let personName = john.name!
/* residence有可能为nul Swift就会在residence不为nil的情况下访问numberOfRooms */
let roomCount = john.residence?.numberOfRooms
- 异常处理
func processFile(filename: String) throws {
if exists(filename) {
let file = open(filename)
/* defer语句在即将离开当前代码块时执行一系列语句 */
defer {
close(file)
}
while let line = try file.readline() {
// 处理文件。
}
// close(file) 会在这里被调用,即作用域的最后。
}
}
/* 如果processFile返回有值则fliePath有值,不然为nul fliePath为可选类型*/
let fliePath = try? processFile(filename: "path")
- 类型转换 -as -is
class MediaItem {
// 父类
}
class Movie: MediaItem {
// 子类一
}
class Song: MediaItem {
// 子类二
}
let library = [
Movie(),
Song(),
]
// 检查类型
for item in library {
if item is Movie {
// movieCount += 1
} else if item is Song {
//songCount += 1
}
}
// 向下转型
/*
当你不确定向下转型可以成功时,用类型转换的条件形式(as?)
只有你可以确定向下转型一定会成功时,才使用强制形式(as!)
*/
for item in library {
if let movie = item as? Movie {
} else if let song = item as? Song {
}
}
- 扩展
- 可以为一个类型添加新的功能,但是不能重写已有的功能。
- 添加计算型属性和计算型类型属性
- 定义实例方法和类型方法
- 提供新的构造器
- 定义下标
- 定义和使用新的嵌套类型
- 使一个已有类型符合某个协议
class SomeType{
}
extension SomeType {
// 为 SomeType 添加的新功能写到这里
var km: Double { return 100 * 1_000.0 }
}
- 协议语法
protocol SomeProtocol {
// 这里是协议的定义部分
var mustBeSettable: Int { get set }
static func someTypeMethod()
}
// 遵循协议时,应该将父类名放在协议名之前,多个协议以逗号分隔
class SomeClass: SomeProtocol {
// 实现协议
var mustBeSettable: Int = 1
static func someTypeMethod() {
}
}
- 协议的继承
protocol InheritingProtocol: SomeProtocol {
}
- 类类型专属协议
- 添加
class
关键字来限制协议只能被类类型遵循
protocol SomeClassOnlyProtocol: class {
}
- 协议扩展
extension InheritingProtocol {
// 添加扩展的协议
}
- 访问级别
-
Open 和 Public 级别可以让实体被同一模块源文件中的所有实体访问,在模块外也可以通过导入该模块来访问源文件里的所有实体。通常情况下,你会使用 Open 或 Public 级别来指定框架的外部接口。Open 和 Public 的区别在后面会提到。
-
Internal 级别让实体被同一模块源文件中的任何实体访问,但是不能被模块外的实体访问。通常情况下,如果某个接口只在应用程序或框架内部使用,就可以将其设置为 Internal 级别。
-
File-private 限制实体只能在其定义的文件内部访问。如果功能的部分细节只需要在文件内使用时,可以使用 File-private 来将其隐藏。
-
Private 限制实体只能在其定义的作用域,以及同一文件内的 extension 访问。如果功能的部分细节只需要在当前作用域内使用时,可以使用 Private 来将其隐藏。
-
Open 为最高访问级别(限制最少),Private 为最低访问级别(限制最多)。
-
Open 只能作用于类和类的成员,它和 Public 的区别如下:
-
Public 或者其它更严访问级别的类,只能在其定义的模块内部被继承。
-
Public 或者其它更严访问级别的类成员,只能在其定义的模块内部的子类中重写。
-
Open 的类,可以在其定义的模块中被继承,也可以在引用它的模块中被继承。
-
Open 的类成员,可以在其定义的模块中子类中重写,也可以在引用它的模块中的子类重写。
- 自定义运算符
运算符位置:
- 前置运算符 prefix
- 中间运算符 infix
- 后置运算符 postfix
postfix operator |??
postfix func |?? (left: String?) -> String! {
return left != nil ? left : "空"
}
var test1: String?
var test2 = "test2"
print(test1|??) // 打印 空
print(test2|??) // 打印 test2
/* 以上代码定义了一个新的运算符 |?? 判断左侧所给出的变量是否为nil,如果不为nil就返回该变量,如果为nil就返回 "空" */
swift学习电梯:
swift-基础类型
swift-函数
swift-类和结构体
网友评论