代码下载
前言
最近找工作,很多单位都需要掌握Swift这门语言,发现Swift将是大势所趋啊!自己之前也断断续续学习过一阵子,但是学以致用啊,项目开发都是用Objective-C不用就容易忘,这段时间得闲就整理出这篇文章,可以说是自己的学习回顾吧,希望对大家有用!这都是些基本的东西,没有做过多的描述。后面我会更新一些Swift较深入探讨的文章。
数据类型
1.基本数据类型有:整型:Int,浮点型:Float,双精度浮点型:Double,字符型:Character,字符串型:String
定义常量:var x: Float = 42.0
定义变量:let y: Int = 12
注意:Swift可以推断出数据的类型,所以在变量常量声明的时候可以省略数据类型。
var x = 12
let y = 42.0
2.字符串的声明:
let name : String = "綦帅鹏"
let age : Int = 10
print("My name is " + name + "," + String(age) + " years old!")
print("My name is \(name),\(age) years old!")
注意:
- Swift中字符串可以通过”+”来拼接。
- 在Swift字符串中可以通过”(名称)”来获取常量、变量的值。
3.元组:元组是一系列不同类型数据的有序集合,可以包含不同的数据类型,通过”.下标”来获取对应的数据。
//元组
let student = ("綦帅鹏",27,"打球")
print("学生:\(student.0),\(student.1)岁,喜欢\(student.2)!")
4.数组:数组是一系列相同类型的数据的有序集合,数组中的数据类型必须相同。
//数组,数组中数据的类型必须相同
var studentsName = ["张三","李四","王五"]
//添加数据
studentsName.append("赵六")
print(studentsName)
//添加多个数据,也可以理解为数组合并
studentsName += ["綦帅鹏","綦朝晖"]
print(studentsName)
//添加数据到指定位置
studentsName.insert("廖腾逸",at: 0)
print(studentsName)
//修改数据
studentsName[1] = "廖雨琦"
print(studentsName)
//移除数据
studentsName.remove(at: 2)
print(studentsName)
//移除最后一个数据
studentsName.removeLast()
print(studentsName)
print(studentsName)
//移除所有数据
studentsName.removeAll()
print(studentsName)
5.字典:字典是一系列相同类型的数据的无序集合,数据是由键值对存在的,并且键不能为nil。
//字典:不能将key指定为nil
var product = ["name":"iPhone5","size":"4寸"]
print(product)
//取值
print(product["name"]!)
//添加数据
product["address"] = "香港"
print(product)
//修改数据
product["size"] = "4英寸"
print(product)
//删除数据
product["address"] = nil
print(product)
//字典数组搭配
print([[1, 2, 3],["1","2","3"]])
print([["name": "张三","address": "湖南"],["name": "李四","address": "北京"]])
//空数组
var arr: Array<Int> = []
arr.append(1)
print(arr)
var otherArr = [Int]()
otherArr += [2]
print(otherArr)
//空字典
var dic = Dictionary<String,String>()
dic["name"] = "张三"
print(dic)
6.数组与字典的遍历
//数组遍历
for item in [1,2,3] {
print(item)
}
for (index,item) in [1,3].enumerated() {
print("\(index): \(item)")
} //遍历字典
for (key,value) in ["name": "张三","address": "湖南"] {
print("\(key):\(value)")
}
流程控制
1.for循环
let arr = [1,3,4,5,6,7,8,9,10]
for num in arr {
print(num)
}
for item in 1...10 {
print(item)
}
for item in 1..<10 {
print(item)
}
for item in [1,10].reversed() {
print(item)
}
2.if…else…选择
let lightColor = "red"
if lightColor == "red"
{
print("Stop!")
}
else
{
print("Go!")
}
3.while循环和switch…case…选择
let limit = 75
var speed = 0
while speed < 100 {
speed += 1
switch speed {
case 0..<20:
print("太慢啦!")
case 20..<40:
print("快点行吗!")
case 40..<60:
print("速度起来啦!")
case 60...limit:
print("别超速呀,我的哥!")
default:
print("超速啦,我的哥!")
}
if speed > limit {
break
}
}
注意:在Swift中可以不需要使用break关键字
函数
1.函数的定义:func 函数名(参数1名: 参数类型,参数2名: 参数类型) -> 返回值类型
func add(num: Int,otherNum: Int) -> Int {
return num + otherNum
}
print(add(num: 10,otherNum: 20))
2.参数个数变化的函数定义:在函数的最后一个参数中用…来添加多个参数
//可变参数,只能在函数的最后一个参数中用...来添加多个参数
func addAllNums(nums: Float...) -> Float {
var result : Float = 0.0
for item in nums {
result += item;
}
return result
}
print(addAllNums(nums: 10,20,30,40,50,60,70,80,90,100))
3.带默认参数的函数
//默认参数
func circleArea(r: Double = 10) -> Double{
return M_PI*r*r
}
print(circleArea())
print(circleArea(r: 100))
//找出最大数
func findMax(nums: Double...) -> Double {
var result : Double = -Double.infinity//负无穷大
for item in nums {
if item > result {
result = item
}
}
return result
}
print(findMax(nums: 12,3333,32413,324,34124,3432))
//找出最小数
func findMin(nums: Double...) -> Double {
var result : Double = Double.infinity
for item in nums {
if item < result {
result = item
}
}
return result
}
print(findMin(nums: 12,3432))
//函数返回函数
func findNum(type: String) -> (Double...) -> (Double) {
if type == "max" || type == "Max" {
return findMax
}
return findMin
}
print(findNum(type: "Max")(1,32,34,23) + findNum(type: "Min")(2,323,233,1,323))
//函数嵌套
func randomNum(type:String) -> Int {
func randomPositive() -> Int {
return Int(arc4random())
}
func randomNegative() -> Int {
return -(Int)(arc4random())
}
if type == "randomPositive" {
return randomPositive()
}
return randomNegative()
}
print(randomNum(type: "randomPositive"))
print(randomNum(type: "randomNegative"))
注意:函数中的参数inout关键字会改变函数体外的变量值,同时在调用该函数的时候,此参数需传地址而不是值。
//变量参数,inout关键字会改变函数体外的变量值
func ascendingSort(num1: inout Int,num2: inout Int,num3: inout Int) -> [Int]
{
var temp : Int
if num1 > num2 {
temp = num1;
num1 = num2;
num2 = temp;
}
if num2 > num3 {
temp = num2;
num2 = num3;
num3 = temp;
}
return [num1,num2,num3]
}
var num1 = 3
var num2 = 2
var num3 = 4
print(ascendingSort(num1: &num1,num2: &num2,num3: &num3))
print([num1,num3])
闭包
1.说明:闭包与函数类似,就是一个代码块分装了其所处环境的所有状态。在闭包之前声明的所有变量常量都会被闭包所捕获,从本质上说闭包保留定义它时的程序状态。函数是有名称的闭包,闭包是无名称的函数。
2.定义一个计算单利的闭包
var simpleClosure = {(amount: Double,interestRate: inout Double,years: Int) -> Double in
interestRate = interestRate/100
var interest = Double(years) * interestRate * amount
return interest + amount
}
//闭包做函数的参数
func loanCalculator(amount: Double,years: Int,calculator: (Double,inout Double,Int) -> Double) -> Double
{
return calculator(amount,&interestRate,years)
}
var rate : Double = 3.875
print(loanCalculator(amount: 10000,interestRate: &rate,years: 5,calculator: simpleClosure))
类
Swift中的类基本上就类的变量、常量、函数、继承等内容,十分简单方便。
枚举
枚举的定义方式如下,可以给枚举类型的数据设置值也可以不设置值
/// 颜色类型枚举
enum ColorType {
case RGB
case CMYK
case HSB
}
let type: ColorType = .RGB
print(type)
/// 学科枚举
enum Subject: String {
case Chinese = "语文"
case Math = "数学"
case English = "英语"
}
let subjece: Subject = .Chinese
print(subjece)
结构体
Swift中的结构体和C语言类似,同时Swift的结构体还包括方法,这使得与类十分相似。不过结构体是不能继承的,并且结构体是值类型的数据结构,而类是引用类型的数据结构。
- 值类型:每次赋值都将创建副本,并把副本赋值给新的变量或常量,变量或常量存储的是副本。
- 引用类型:说白了,引用类型就是指针,不管赋值给多少变量或者常量,他们都指向同一个对象,变量和常量存储的都是指向这个对象的引用,而不是副本。
struct Color {
var R: Double = 0.0
var G: Double = 0.0
var B: Double = 0.0
var Alpha: Double = 0.0
func stringValue() -> String {
let limit: Double = 255.0
let rInt: Int = Int(self.R*limit)
let gInt: Int = Int(self.G*limit)
let bInt: Int = Int(self.B*limit)
let alphaInt: Int = Int(self.Alpha*limit)
let result: String = String.init(format: "%02X%02X%02X%02X",rInt,gInt,bInt,alphaInt)
return result
}
}
let red: Color = Color(R: 1.0,G: 0.0,B: 0.0,Alpha: 1)
print(red)
print(red.stringValue())
协议
指定了类和结构需要实现的方法和变量,optional关键字可以定义协议中选择实现的方法和变量,一个结构体或者类可以实现多个协议,值得注意的是协议之间是可以继承的。
//多协议
protocol AreaComputetionProtocol {
func computeArea() -> Double
}
protocol PerimeterComputetionProtocol {
func computePerimeter() -> Double
}
struct RectAngle: AreaComputetionProtocol,PerimeterComputetionProtocol {
var width,height: Double
internal func computeArea() -> Double {
return width*height
}
internal func computePerimeter() -> Double {
return 2*(width + height)
}
}
let rect: RectAngle = RectAngle(width: 3.0,height: 4.0)
print(rect.computeArea())
print(rect.computePerimeter())
//协议继承
protocol TriangeleProtocol: AreaComputetionProtocol,PerimeterComputetionProtocol {
var a: Double {get set}
var b: Double {get set}
var c: Double {get set}
var base: Double {get set}
var height: Double {get set}
}
struct Triangle: TriangeleProtocol {
var a: Double = 0.0
var b: Double = 0.0
var c: Double = 0.0
var base: Double = 0.0
var height: Double = 0.0
func computeArea() -> Double {
return base*height/2.0
}
func computePerimeter() -> Double {
return a + b + c
}
}
let triangle: Triangle = Triangle(a: 3,b: 4,c: 5,base: 3,height: 4)
print(triangle.computeArea())
print(triangle.computePerimeter())
说到协议就不得不说委托,委托是为了让一个类或结构体能够将工作和决策交给另一个类或结构去完成。
//委托:让一个类或结构能够将工作和决策交给另一个类或结构去完成
/// 售货机协议
protocol VendingMathineProtocol {
/// 是否投币
var coinInserted: Bool {get set}
/// 能否售货
func shouldVend() -> Bool
}
/// 自动售货机类,遵守售货机协议
class Vendor: VendingMathineProtocol {
var coinInserted: Bool = false
/// 如果投币则售货否则不售货
///
/// - Returns: 是否售货
func shouldVend() -> Bool {
if coinInserted {
coinInserted = false
return true
}
else
{
return false
}
}
}
/// 可乐机类
class ColaMethine {
// 自动售货机类,遵守售货机协议
var vendor: VendingMathineProtocol
init(vendor: VendingMathineProtocol) {
self.vendor = vendor
}
/// 投币
func insertCoin() {
vendor.coinInserted = true
}
/// 销售可乐按钮事件
func pressColaButton() -> String {
if vendor.shouldVend() {
return "Here's a cola!"
}
else
{
return "You must insert coin!"
}
}
/// 销售啤酒按钮事件
func pressRootBeerButton() -> String {
if vendor.shouldVend() {
return "Here's a Root Beer!"
}
else
{
return "You must insert coin!"
}
}
}
let methine: ColaMethine = ColaMethine.init(vendor: Vendor.init())
print(methine.pressColaButton())
methine.insertCoin()
print(methine.pressColaButton())
methine.insertCoin()
print(methine.pressRootBeerButton())
print(methine.pressColaButton())
扩展
不继承而扩展类的功能,扩展能够以非侵入式的方式,增加类、结构、甚至基本类型的行为和功能,类似于Objective_C的类别,但是强大得多。基本使用如下:
// MARK: - 可乐机的扩展
extension ColaMethine {
/// 健怡可乐按钮事件
func pressDietColaButton() -> String {
if vendor.shouldVend() {
return "Here's a Diet Cola!"
}
else
{
return "You must insert coin!"
}
}
}
methine.insertCoin()
print(methine.pressDietColaButton())
1.扩展基本数据类型:不能在扩展中添加常规存储属性,但可以添加计算属性:值是通过计算获得的属性
let limit: Double = 1024.0
// MARK: - 为Int64扩展属性,获取存储单位的换算结果
extension Int64 {
var K: String {return String.init(format: "%fK",Double(self)/limit)}
var M: String {return String.init(format: "%fM",Double(self)/limit/limit)}
var G: String {return String.init(format: "%fG",Double(self)/limit/limit/limit)}
var T: String {return String.init(format: "%fT",Double(self)/limit/limit/limit/limit)}
}
let bytes: Int64 = 2345346457
print(bytes.K)
print(bytes.M)
print(bytes.G)
print(bytes.T)
2.mutating关键字:如果要修改自身的值而不是返回计算的结果,那么就得使用mutating关键字
// MARK: - 为Double数据类型扩展方法
extension Double {
/// 平方值
mutating func squra() {
self = self*self
}
/// 立方值
mutating func cube() {
self = self*self*self
}
}
var num: Double = 1.5
num.squra()
print(num)
num.cube()
print(num)
Swift内存管理
Swift以ARC方式为引用类型数据管理内存,这种方式是由编译器提供支持的。每一个引用类型的数据都有一个引用计数的的属性,当这个对象被创建的时候它的引用计数就为1,当这个对象在应用程序运行过程中被传递,就可能被多个“所有者”持有并使用。当“所有者”获得所有权时引用计算就相应加1,而在放弃所有权时引用计数就相应减1,直到引用计数为0时(所有的“所有者”都放弃了所有权),对象就会被销毁,它所占用的内存归还给内存池,供其他对象使用。
1.循环引用:循环引用就是指不同对象之间相互持有对方,这样造成了对象永远被“所有者”所占有,而无法释放,从而形成内存泄漏。
- 普通对象之间的循环引用:这种循环引用可以使用weak关键字来打破。
//循环引用
class ClassA {
var b: ClassB!
//销毁时调用
deinit {
print("\(type(of: self)) 销毁了!")
}
}
class ClassB {
var a: ClassA!
//销毁时调用
deinit {
print("\(type(of: self)) 销毁了!")
}
}
var aClass: ClassA! = ClassA()
var bClass: ClassB! = ClassB()
aClass.b = bClass
bClass.a = aClass
//使用"weak"可以解决对象之间相互引用而造成的循环引用
class ClassC {
var d: ClassD!
//销毁时调用
deinit {
print("\(type(of: self)) 销毁了!")
}
}
class ClassD {
weak var c: ClassC!
//销毁时调用
deinit {
print("\(type(of: self)) 销毁了!")
}
}
var cClass: ClassC! = ClassC()
var dClass: ClassD! = ClassD()
cClass.d = dClass
dClass.c = cClass
cClass = nil
dClass = nil
-
@H_478_1403@闭包内的循环引用:闭包是引用类型的数据,类的实例变量强引用了闭包,而如果闭包中再引用了类对象的话,就会造成循环引用。在闭包定义中添加”[unowned self] in”可以解决闭包内的循环引用。@H_155_1404@
class Student {
var name: String = ""
var age: Int = 0
lazy var info: () -> Void = {
print("name:\(self.name),age:\(self.age)")
}
deinit {
print("\(type(of: self)) 销毁了!")
}
}
var student: Student! = Student()
student.name = "张三"
student.age = 10
student.info()
student = nil
class People {
var name: String = ""
var age: Int = 0
lazy var info: () -> Void = { [unowned self] in
print("name:\(self.name),age:\(self.age)")
}
deinit {
print("\(type(of: self)) 销毁了!")
}
}
var people: People! = People()
people.name = "张三"
people.age = 10
people.info()
people = nil
说明:一个对象在销毁的时候会调用deinit,而一个变量赋值为nil时就会放弃对原有对象的持有。
泛型
不指定数据的类型,只是指定一个占位符。编译器负责对数据类型进行检查。使用方式如下:
func valueEqual<T: Equatable>(value1: T,value2: T) -> Bool {
return value1 == value2
}
运算符重载:只需定义一个运算符命名的函数就可以对运算符进行重载。
/// 二维矩阵结构体
struct TwoDimensionalMatrix {
var a11: Double,a12: Double
var a21: Double,a22: Double
}
/// 重载+运算符,实现二维矩阵的相加
func +(matrix: TwoDimensionalMatrix,otherMatrix: TwoDimensionalMatrix) -> TwoDimensionalMatrix {
return TwoDimensionalMatrix.init(a11: matrix.a11 + otherMatrix.a11,a12: matrix.a12 + otherMatrix.a12,a21: matrix.a21 + otherMatrix.a21,a22: matrix.a22 + otherMatrix.a22)
}
/// 重载*运算符,实现二维矩阵的相乘
func *(matrix: TwoDimensionalMatrix,otherMatrix: TwoDimensionalMatrix) -> TwoDimensionalMatrix {
return TwoDimensionalMatrix.init(a11: matrix.a11 * otherMatrix.a11,a12: matrix.a12 * otherMatrix.a12,a21: matrix.a21 * otherMatrix.a21,a22: matrix.a22 * otherMatrix.a22)
}
let matrix: TwoDimensionalMatrix = TwoDimensionalMatrix.init(a11: 1,a12: 2,a21: 3,a22: 4)
let otherMatrix: TwoDimensionalMatrix = TwoDimensionalMatrix.init(a11: 1,a22: 4)
print(matrix + otherMatrix)
print(matrix * otherMatrix)
相等与相同
相等是指值相等,相同是指指向的对象为同一个对象。使用==来判断值的相等,用===来判断是否为同一个对象。
let a: Int = 1
let b: Int = 1
class IntClass {
var value: Int = 0
init(value: Int) {
self.value = value
}
}
let intA: IntClass = IntClass.init(value: 1)
let intB: IntClass = IntClass.init(value: 1)
print(a == b)
print(a != b)
print(intA === intB)
print(intA !== intB)