枚举类型
import UIKit
// 1.枚举类型定义
enum MenthodType : String{
case get = "get"
case post = "post"
case put = "put"
case delete = "delete"
}
// 2.创建枚举具体的值
let type1 : MenthodType = .get
let type2 = MenthodType.get
let type3 = MenthodType(rawValue: "put")
let str = type3?.rawValue
// 3.给枚举类型进行赋值
enum Direction : Int{
case east = 1
case west = 2
case north = 3
case south = 4
}
let d1 : Direction = .east
let d2 = Direction(rawValue: 1)
// 4.枚举类型定义二:
enum Type : Int{
case get = 0, post, put, delete
}
let t1 : Type = .get
let t2 = Type(rawValue: 1)
结构体
- 结构体(struct)是由一系列具有相同或不同类型的数据构成的数据集合
- 结构体指的是一种数据结构
- 结构体是值类型,在方法中传递时是值传递
import UIKit
// 1.定义结构体
struct Location {
// 属性
var x : Double
var y : Double
// 方法
func test() {
print("结构体中的test函数")
}
// 改变成员属性,如果在结构体函数中修改了成员属性,那么该函数前必须加上mutating
mutating func moveH(_ distance : Double) {
self.x += distance
}
// 给结构体扩充构造函数
// 1> 默认情况下,系统为每一个结构体提供一个默认的构造函数,并且该构造函数要求给每一个成员属性赋值
// 2> 构造函数都是以init开头,并且构造函数不需要返回值
// 3> 在构造函数结束时,必须保证所有的成员属性有被初始化
init(x : Double, y : Double) {
self.x = x
self.y = y
}
init(xyStr : String) {
let array = xyStr.components(separatedBy: ",")
let item1 = array[0]
let item2 = array[1]
// ?? 判断前面的可选类型是否有值
// 有值-解包,没有指-使用后面的值
self.x = Double(item1) ?? 0
self.y = Double(item2) ?? 0
}
}
// 2.创建结构体对应的值
var center = Location(x: 20, y: 30)
// 3.系统结构体的创建方式
let rect = CGRect(x: 0, y: 0, width: 100, height: 100)
let size = CGSize(width: 20, height: 30)
let point = CGPoint(x: 0, y: 0)
let range = NSRange(location: 0, length: 3)
// 4.给结构体扩充方法
center.test()
center.moveH(20)
// 5.给结构体扩充构造函数
Location(x: 20, y: 30)
类的使用
类的定义
- 定义的类,可以没有父类,那么该类是rootclass
- 通常情况下,定义类时,继承自NSObject(非OC的NSObject)
import UIKit
// 1.如何定义类
/*
OC类的定义
@interface Person : NSObject
@end
@impelment
@end
*/
class Person {
// 开发个人规范:
// 1> 如果属性是值类型,则初始化为空值
// 2> 如果属性是对象类型,则初始化为nil值
var name : String = ""
var age : Int = 0
var view : UIView?
}
// 2.创建类的对象
let p = Person()
let view = UIView()
p.name = "aaa"
p.age = 18
p.view = view
类的属性
import UIKit
// 1.创建类
class Student {
// 类的属性定义
// 存储属性: 用于存储实例的常量&变量
var name : String = ""
var age : Int = 0
var mathScore : Double = 0.0
var chineseScore : Double = 0.0
// 计算属性: 通过某种方式计算得来结果的属性
var aveageScore : Double {
return (chineseScore + mathScore) * 0.5
}
// 类属性
static var courseCount : Int = 0
// 给类扩充函数
// 在OC中写的很多没有参数的方法,在Swift中可以写成计算属性
/*
func getAverageScore() -> Double {
return (chineseScore + mathScore) * 0.5
}
*/
}
// 2.创建类的对象
let stu = Student()
// 3.访问类属性
Student.courseCount = 2
监听属性的改变
import UIKit
class Person {
var name : String = "" {
// 属性监听器
// 1.监听属性即将发生改变
willSet {
print("属性即将发生改变\(name)")
print(newValue)
}
// 2.监听属性已经发生改变
didSet(oldName) {
print("属性已经发生改变\(name)")
print(oldName)
}
}
}
let p = Person()
p.name = "aaa"
p.name = "bbb"
类的构造函数
import UIKit
/*
使用KVC的条件
1> 必须继承NSObject
2> 必须在构造函数中,先调用super.init()
3> 调用setValuesForKeys
4> 如果字典中n某一个key没有对应的属性,则需要重写setValue forUndefinedKey方法
*/
class Person : NSObject{
var name : String = ""
var age : Int = 0
init(dict : [String : Any]) {
/*
if let name = dict["name"] as? String {
self.name = name
}
if let age = dict["age"] as? Int {
self.age = age
}
*/
super.init()
setValuesForKeys(dict)
}
override func setValue(_ value: Any?, forUndefinedKey key: String) {
}
}
let p = Person(dict: ["name" : "aaa", "age" : 18])
类的析构函数
import UIKit
class Person {
var name : String = ""
var age : Int = 0
// 重写析构函数,监听对象的销毁
deinit {
print("Person --- deinit")
}
}
var p : Person? = Person()
p = nil
自动引用计数
工作机制
- Swift和OC一样,采用自动引用计数来管理内容
- 当有一个强引用指向某个对象时,该对象的引用计数就回自动+1
- 当该强引用消失时,引用计数会自动-1
- 当引用计数为0时,该对象会被销毁
循环引用
import UIKit
/*
OC中表示n弱引用
__weak __unsafe_unretained(野指针错误)
Swift中表示弱引用
weak unowned(野指针错误)
*/
// 1.创建类
class Person {
var name : String = ""
var book : Book?
deinit {
print("Person --- deinit")
}
}
class Book {
var price : Double = 0.0
weak var owner : Person?
deinit {
print("Book --- deinit")
}
}
// 2.创建对象
var person : Person? = Person()
person!.name = "abc"
var book : Book? = Book()
book!.price = 60.0
person!.book = book
book!.owner = person
person = nil
book = nil
可选链
import UIKit
// 1.创建类
class Person {
var name : String = ""
var dog : Dog?
}
class Dog {
var weight : Double = 0.0
var toy : Toy?
}
class Toy {
var price : Double = 0.0
func flying() {
print("flying...")
}
}
// 2.创建类的对象
let p = Person()
p.name = "abc"
let d = Dog()
d.weight = 60.0
let t = Toy()
t.price = 100
p.dog = d
d.toy = t
// 3.可选链的使用
/* 不推荐,非常危险
let dog = p.dog
let toy = dog?.toy
let price = toy?.price
*/
/* 太麻烦
if let dog = p.dog {
if let toy = dog.toy {
let price = toy.price
}
}
*/
// ?. 就是可选链,系统会自动判断可选类型是否有值,如果有值,则解包;如果没有值,则赋值为nil
// 注意:可选链获取的值,一定是可选类型
let price = p.dog?.toy?.price
// 如果可选链中有一个可选类型是没有值,那么这个语句不执行
p.dog?.toy?.price = 50
// 可选链调用方法
p.dog?.toy?.flying()
协议
import UIKit
// 1.协议的定义
protocol SportProtocol {
// 默认情况下协议中的方法都是必须实现的方法
func playBaskball()
func playFootball()
}
// 2.定义类,并且遵守协议
class Teacher : SportProtocol {
func playBaskball() {
print("打篮球...")
}
func playFootball() {
print("踢足球...")
}
}
class Student : NSObject, SportProtocol {
func playBaskball() {
print("打篮球...")
}
func playFootball() {
print("踢足球...")
}
}
// 3.协议在代理设计模型中的使用
// 定义协议时,协议后面最好加上 class
// delegate的属性最好用weak,防止产生循环引用
protocol BuyTicketDelegate : class{
func buyTicket()
}
class Person {
// 定义代理属性
weak var delegate : BuyTicketDelegate?
func goToBeijing() {
delegate?.buyTicket()
}
}
// 4.如何让协议中的方法是可选方法
// optional属于OC特性,如果协议中有可选的方法,那么必须在protocol前面加上@objc,也是需要在optional前面加上@objc
@objc protocol TestProticol {
@objc optional func test()
}
class Dog : TestProticol {
}