1、数值类型
swift基本数据类型
Int、UInt、Float、Double、Bool、String、Character、Optional、Dictionay、Set、Array、Any、AnyObject
swift的基本数据类型都是struct类型。赋值给另一个变量的时候会复制一份相同的内容给另外一个变量。
title | content |
---|---|
值类型(value type) | 1、枚举(enum):Optional 2、结构体 (truct):Bool、Int、Float、Double、Character、String、Array、Dictioanry、Set |
引用类型(reference type) | 类(class) |
1、String字符串
// 初始化
var str = "Swift"
var str = String("Swift")
// 字符串连接
var str2 = "OC"
var str3 = str+str2
// 字符串比较
if str == str2 {
print( "\(str) 与 \(str2) 是相等的" )
} else {
print( "\(str) 与 \(str2) 不相等" )
}
2、Character为字符修饰的类型为单个字母
// Character只能取单个字母,不能为空否则会crash
for ch in "Swift" { // 遍历字符
print(ch)
}
3、Optional为可选类型,一般可以用?代替
let rows: Optional<Int>
let rows: Int? // 表明rows可能是Int,也可能是nil,使用的时候使用!取值
// ?和!的区别
// ?是一种判断后再拆包的语法糖,当你不确定有值的时候就可以用 “?”
// !是一种强制拆包的语法糖,当你确定有值的时候可以用 “!”
4、Dictionary字典类似于OC的NSDictionary
// 创建
var dic = Dictionary<Int, String>()
var dic = [Int:String]()
var dic:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
// 取值
var oneVar = dic // 默认取第一个
var twoVar = dic[2]
let keys = dic.keys // 取出来为数组
let values = dic.values
for (key, value) in dic.enumerated() {
print("字典 key \(key) - 字典 (key, value) 对 \(value)")
}
for item in dic {
print("\(item.key) --> \(item.value)")
}
// 修改
var newOneVar = dic.updateValue("new One", forKey: 1)
dic[1] = "new One"
// 移除
var removedValue = dic.removeValue(forKey: 2)
dic[2] = nil
let index = dic.index(dic.startIndex, offsetBy: 1)
dic.remove(at: index) // 通过下标移除
dic.removeAll() // 移除所有
// 其他属性
print("dic 含有 \(dic.count) 个键值对") // 计算个数
print("dic = \(dic.isEmpty)") // 判空
5、Set集合类似于OC的NSSet
// 创建
var s = Set<String>()
var s: Set<String> = ["One", "Two", "Three"]
// 取值
for num in s.sorted() {
print("\(num)")
}
// 添加
s.insert("Four")
// 删除
if let removeFour = s.remove("Four") {
print("\(removeFour)? I'm over it.")
} else {
print("removeFour error")
}
// 其他
if s.contains("Four") {
print("s contain Four")
} else {
print("s not contain Four")
}
if s.isEmpty {
print("s集合为空.")
} else {
print("s集合不为空.")
}
// union、intersection、subtracting、symmetricDifference
// isSubset(of:)、isSuperset(of:)、isStrictSubset(of:)、isStrictSuperset(of:)、isDisjoint(with:)
6、Array数组类似于OC的NSArray
// 创建
var arr = Array<String>()
var arr = [String](repeating: "Zero', count: 1)
var arr:[String] = ["One", "Two", "Three"]
// 取值
var oneVar = arr[0]
var twoVar = arr.index(after: 0)
var oneVar = arr.index(before: 1)
// 修改
arr[0] = "newOne"
// 添加
arr.append("Four")
arr += ["Five"] // 合并数组
// 删除
arr.remove(at: 4)
arr.removeAll()
// 其他
print("arr.isEmpty = \(arr.isEmpty)")
7、Any可以表示任意类型,甚至包括函数类型,类似于OC的id
AnyObject可以表示任意类型的实例,使用class定义的对象
2、关键字
声明的关键字
class、deinit、init、enum、extension、func、import、let、var、operator、protocol、static、struct、typealias、open、public、internal、fileprivate、private、subscript、
语句中的关键字noescape
fallthrough、defer、break、case、default、do、else、for、guard、if、in、repeat、return、switch、where、while
表达式和类型的关键字
try、as、catch、throw、throws、rethrows、false、is、nil、super、Self、self、true
特定上下文中被保留的关键字
associatedtype、some、convenience、dynamic、optional、protocol、final、infix、prefix、postfix、lazy、indirect、mutating、none、nonmutating、override、precedencegroup、required、get、set、unowned、weak、inline、@discardableResult
1、deinit和init,convenience(便利构造器)
init指定构造器(init?、init!可失败构造器)
convenience便利构造器必须调用init方法、也可以在extension中调用init方法
deinit析构函数
class People {
var name: String
init(name: String) { // 指定构造器
self.name = name
}
init?(name: String) { // 可失败构造器
self.name = name
if name.isEmpty { return nil }
}
deinit {
// 执行析构过程
}
}
extension People {
convenience init(smallName: String) {// 便利构造器
self.init(name: smallName)
}
}
2、enum枚举
// 枚举相关值基本用法
enum Student {
case Name(String)
case Score(Int,Int,Int)
}
var name = Student.Name("Swift")
var score = Student.Score(98,97,95)
switch score {
case .Name(let studName):
print("学生的名字是: \(studName)。")
case .Mark(let score1, let score2, let score3):
print("学生的成绩是: \(score1),\(score2),\(score3)。")
}
3、extension和oc的category功能大同小异,区别是swift的扩展方法可以被外部类调用,也支持被继承。
4、let和var的区别,let为常量,var为变量。
5、operator 自定义运输符
// prefix 前置运输符号
// infix 中间运输符号
// postfix 后置运输符号
prefix operator ^
prefix func ^ (var vector: Double) -> Double {
return pow(2, vector)
}
print(^5)
//
postfix operator ^
postfix func ^ (var vector: Int) -> Int {
return vector * vector
}
print(5^)
// precedencegroup 优先级
infix operator ^^:Precedence
precedencegroup Precedence {
associativity: left // 结合性 none
higherThan: AdditionPrecedence // 比加法高
lowerThan: MultiplicationPrecedence // 比乘法低
assignment: true // 代表在可选链操作中拥有跟赋值运算符一样的优先级
}
func ^^(left: Double, right: Double) -> Double {
return pow(left, right)
}
print(2 ^^ 10 - 2 ^^ 3)
6、open、public、internal、fileprivate、private访问控制
open 可以被其他module中继承重写
public 只能在其他module中调用,不能重写
internal 只能在内部module中调用重写
fileprivate 能在相同的文件中调用
private 只能在类的内部使用
7、subscript下标脚本
// 动态成员查找
@dynamicMemberLookup // 标记使用的subscript有自定义值
struct Person {
subscript(dynamicMember member: String) -> String {
let properties = ["nickname": "Zhuo", "city": "Hangzhou"]
return properties[member, default: "undefined"]
}
}
//执行以下代码
let p = Person()
print(p.city)
print(p.nickname)
print(p.name)
// 扩展
// dynamicCallable 函数变量可以作为函数调用
@dynamicCallable
struct RandomNumberGenerator {
func dynamicallyCall(withArguments args: [Int]) -> Double {
let numberOfZeroes = Double(args.first ?? 0)
let maximum = pow(10, numberOfZeroes)
return Double.random(in: 0...maximum)
}
}
// 调用方式
let random = RandomNumberGenerator()
let num = random(2)
// random(2)等同于random.dynamicallyCall(withArguments: [2])
print(num)
8、fallthrough 在swich语句中继续往后执行跑一个case
let Describe = 1
var description = "The number \(Describe) is"
switch Describe {
case 1,3,7:
description += " a prime number, and also"
fallthrough
case 5:
description += " an integer"
default :
description += " finished"
}
print(description)
9、defer 在{}作用域的最后一行执行defer
defer {
print("finally")
}
do {
throw NSError()
print("impossible")
} catch {
print("handle error")
}
10、for 循环使用
// forEach的使用
let arr: [String] = ["One","Two","Three"]
arr.forEach { (item) in
print("\(item)")
}
// for循环100次
for _ in 0...100 {
print("good");
}
11、guard和if相反,guard是条件不满足的情况下执行
// if 的作用域只在当前的if条件语句内
func login(_ info: [String: String]) {
var username
if let tmp = info["username"] {
username = tmp
print("请输入用户名")
return
}
print("用户名:\(username)")
}
// guard的作用域在当前guard所在大括号内,且guard执行完成之后必须退出当前作用域
func login(_ info: [String: String]) {
guard let username = info["username"] else {
print("请输入用户名")
return
}
print("用户名:\(username)")
}
12、repeat 先判断条件语句后循环
repeat{
print( "index 的值为 \(index)")
index = index + 1
}while (index < 20)
13、where 条件语句
//协议
protocol aProtocol{}
extension aProtocol where Self:UIView{
//只给遵守aProtocol协议的UIView添加了拓展
func getString() -> String{
return "string"
}
}
//使用for in遍历
for value in array where value > 2 {
print(value) //输出3 4 5 6
}
14、as类型转换
let money = 20 as CGFloat // 转换为CGFloat类型
15、is 若一个类属于另一个类的子类,则会返回true,否则返回false。
class Person {}
class Student:Person {}
let s = Student()
if s is Person {
print("Student")
}
16、try、catch、throw、throws、rethrows
throw 抛出一个错误允许你明确某些意外的事情发生了并且正常的执行流不能继续下去。
throws 函数内部通过throw抛出自定义Error,可能会抛出Error的函数必须加上throws声明
rethrows 函数本身不会抛出错误,但调用闭包参数抛出错误,那么它会将错误向上抛。
enum SomeError : Error {
case illegalArg(String)
case outOfBounds(Int, Int)
case outOfMemory
}
func divide(_ num1: Int, _ num2: Int) throws -> Int {
if num2 == 0 {
throw SomeError.illegalArg("0不能作为除数")
}
return num1 / num2
}
func exec(_ fn: (Int, Int) throws -> Int, _ num1: Int, _ num2: Int) rethrows {
print(try fn(num1, num2))
}
try exec(divide, 20, 0)
17、Self和self
1、self和oc的用法一样
2、Self 1)、可以用于协议中限制相关类型。2)、可以用于类中充当方法的返回值。3)可以访问静态方法或变量
3、.self类型的本身值。Class.self返回当前类的元类信息。
protocol Copyable {
func copy() -> Self
func clamp(intervalToClamp: Self) -> Self
}
class A: Copyable {
var num = 1
required init() {}
func copy() -> Self {
let result = self
result.num = num
return result
}
func clamp(intervalToClamp: A) -> Self {
let result = self
result.num = num
return result
}
class func calssFunc() -> Self {
let type = self
print(type)
let result = type.init()
return result
}
}
class B: A {
func clamp(intervalToClamp: B) -> Self {
let result = self
result.num = num
return result
}
}
let type = A.self // A.self代表元类
type.calssFunc()
let typeB = B.self
typeB.calssFunc()
let objectA = A()
objectA.num = 100
let newObjectA = objectA.copy()
objectA.num = 1
let objectB = B()
objectB.num = 100
let newB = objectB.copy()
18、associatedtype 关联类型,为协议中的某个类型提供占位符。some指明返回的协议为不透明类型,明确为某一种类型。
protocol NetworkRequest {
associatedtype T
func didReceiveData(_ data: T)
}
class ViewModel: NetworkRequest {
typealias T = String
func didReceiveData(_ data: T) {
}
}
class PresetModel: NetworkRequest {
func didReceiveData(_ data: T) {
}
}
// 函数的返回需要some指明,只能返回某一种类型
func requestType() -> some NetworkRequest {
return ViewModel()
}
19、convenience 便利构造器
class MainClass {
var name: String
init(name: String) {
self.name = name
}
convenience init() {
self.init(name: "[匿名]")
}
// 类里面使用懒加载
lazy var planNameLabel: UILabel = {
let label = UILabel()
label.text = "yo yo yo kongfu!"
return label
}()
}
let main = MainClass(name: "Runoob")
print("MainClass 名字为: \(main.name)")
let main2 = MainClass()
print("没有对应名字: \(main2.name)")
20、dynamic,swift调用的方法具有oc的动态性能,optional标记oc协议为可选值
@objc protocol CounterDataSource {
@objc optional var fixedIncrement: Int { get }
@objc optional func incrementForCount() -> Int
dynamic func decrementForCount() -> Int
}
21、final,类方法属性等不希望被重写或者继承时,在前面添加的标记
22、lazy 懒加载
// 懒加载打印序列
let numbers = 1...5
let doubleNumbers = numbers.lazy.map { (i: Int) -> Int in
print("numbers\(i)")
return i * 2
}
for i in doubleNumbers {
print("doubleNumbers\(i)")
}
// 懒加载UILabel
var planNameLabel: UILabel = {
let label = UILabel()
label.text = "lazy OK!"
return label
}()
23、indirect 递归枚举,枚举值中包含自己的枚举
indirect enum ArithExpr {
case number(Int)
case sum(ArithExpr, ArithExpr)
case difference(ArithExpr, ArithExpr)
}
let five = ArithExpr.number(5)
let four = ArithExpr.number(4)
let two = ArithExpr.number(2)
let sum = ArithExpr.sum(five, four)
let difference = ArithExpr.difference(sum, two)
24、mutating 结构体和枚举类型值默认情况下是不能被修改,如果要修改加上关键字mutating
protocol Togglable {
mutating func toggle()
}
struct Test: Togglable {
var time: Int = 0
mutating func toggle() {
self.time = 33333
}
}
var test = Test()
test.time = 2
print(test.time)
test.toggle()
print(test.time)
25、unowned、weak,无主引用和弱引用的区别,弱引用必须为可选类型,当引用的对象不存在时,自动设置为nil;无主引用不能为可选类型,如果引用了一个已经被销毁的对象会抛出错误。
let | var | Optional | Non-Optional | |
---|---|---|---|---|
strong | ✔ | ✔ | ✔ | ✔ |
weak | ✔ | ✔ | ✔ | ✗ |
unowned | ✔ | ✔ | ✗ | ✔ |
class User {
var name: String
private(set) var phones: [Phone] = []
// 使用的运营商
var subscriptions: [CarrierSubscription] = []
init(name: String) {
self.name = name
print("初始化 \(name)")
}
func addPhone(phone: Phone) {
phones.append(phone)
// 手机的持有者
phone.owner = self
}
deinit {
print("销毁 \(name)")
}
}
class Phone {
let model: String
weak var owner: User?
var carrierSubscription: CarrierSubscription?
init(model: String) {
self.model = model
print("手机模型 \(model)")
}
func provision(carrierSubscription: CarrierSubscription) {
self.carrierSubscription = carrierSubscription
}
func decommission() {
self.carrierSubscription = nil
}
deinit {
print("销毁手机模型 \(model)")
}
}
class CarrierSubscription {
let name: String
let countryCode: String
let number: String
let user: User
init(name: String, countryCode: String, number: String, user: User) {
// 运营商名
self.name = name
// 区号
self.countryCode = countryCode
// 电话号码
self.number = number
// 对应用户
self.user = user
// 将 CarrierSubscription 添加到User的subscriptions属性中
user.subscriptions.append(self)
print("CarrierSubscription \(name) 初始化")
}
deinit {
print("CarrierSubscription \(name) 销毁")
}
}
do {
unowned let user = User(name: "John")
let iphone = Phone(model: "iphone6s")
user.addPhone(phone: iphone)
let subscription = CarrierSubscription(
name: "TelBel",
countryCode: "0032",
number: "31415926",
user: user)
iphone.provision(carrierSubscription: subscription)
}
26、inline内联函数,函数声明前加@inline
// 永远不会被内联(即使开启了编译器优化)
@inline(never) func test() {
print("test")
}
// 开启了编译器优化后,即使代码很长,也会被内联(递归函数、动态派发的函数除外)
@inline(__always) func test() {
print("test")
}
27、@discardableResult标记返回值可以不被使用(语法糖)
protocol Togglable {
mutating func toggle()
}
struct Test: Togglable {
var time: Int = 0
@discardableResult mutating func toggle() {
self.time = 33333
return self.time // 有返回值
}
}
var test = Test()
test.toggle() // 可以不使用返回值,无警告