Swift 基础
Demo:https://github.com/asd521411/Swift–Basic-Knowledge.git
import UIKit
//Swift将OC中的大部分类都变成了结构体,比如Sring,比如Array,比如Dictionary。
//按住command点击随便一个Int或者Double或者String都会发现前面有一个struct,结构体。使用起来变得更加简单。
//Swift中不再存在OC中的NSMutableArray、NSMutableString,NSMutableDictionary
//在Swift中,只通过参数名前面是let还是var,let就是不可变,var就是可变
//常量字符串
var letStr1 = “字符串常量”
let letStr2:String = “另一种定义”
let letStr3 = String(“字符串”)
//拼接
print(letStr1 + letStr2 + letStr3)
letStr1.append(letStr2)
print(letStr1)
print(letStr1.count)
//可以便利字符串里面的字符
let letStr4:String = “奔跑的蜗牛”
for cha in letStr4 {
print(cha)
}
let letCharacter:[Character] = [“c”, “h”, “a”, “r”]
let letInt:Int = 20
//数组
let letArr1 = Int
let letArr2 = [“zhao”, “qian”, “sun”, “li”]
let letArr3:Array = [0,1,2,3,4]
let letArr4 = Array(repeating: 0, count: 5)
var varArr1:[String] = [“ke”, “bian”, “shu”, “zu”]
//字典
let letDic1 = Int:String
let letDic2 = Dictionary<String,String>()
let letDic3:Dictionary = [“ket1”:“value1”, “key2”:“value2”]
var varDic1:[Int:String] = [1:“value1”, 2:“value2”]
for (key, value) in varDic1{
print(key,value)
}
//循环0…3->[0,3]; 0…❤️->[0,3)
for i in 0…3 {
print(i)
}
//repeat-while 同do while
var temp = 0
repeat {
temp += 1
print(“try it again”)
}
while temp<3
let grade = 80
if grade > 90 {
print(“A”)
} else if grade > 80 {
print(“B”)
}
//与OC中不同的是,不需要给case分支添加break
let time = 12
switch time {
case 0…6:
print(“sleep”)
case 7:
print(“get up”)
case 8,12,18 :
print(“eat”)
case let x where x>=18 && x<=24 :
print(“play”)
default:
print(“busy”)
}
//continue语句和fallthrough语句
//swift中continue用来告诉用于一个循环体停止本次的循环,并立即进入下一个循环
let datas = [1,2,3,4,5,6,7,8,9]
var odd = 0
for even in datas {
if even%2==0 {
continue
}
odd += 1
}
print(odd)
//fallthrough语句
//在OC中,必须要在case的末尾加入break,才能阻止自动跳入下一个case分之中。
//在swift中,switch语句不会从一个case跳转到下一个case分支,而是只要匹配一个case分支,就会完成整条switch语句。
//fallthrough语句的作用是在switch语句中,执行完一个case分支之后,跳转到下一个case分支中。
let time1 = 6
var mass = “zifu”
switch time1 {
case 2,3,6,12:
mass += “(time1) o`cl0ck”
fallthrough
default:
print(mass+".")
}
//函数===========================
//函数格式如下:
//func 函数名(参数变量: 类型, 参数变量: 类型) -> 返回类型 {
//
//}
//设置可变的参数数量
//定义函数时,如果不能确定传入参数的数量,可通过变量类型后面加入…定义变量参数。
//一个函数最多能有一个变量参数,且必须是函数表中的最后一个。
//一个函数如果有一个或多个参数,变量参数一定放在最后。
func mean (numbers:Double…) -> Double {
if numbers.count==0 {
return 0.0
} else {
var temp :Double = 0
for number in numbers {
temp += number
}
return temp/Double(numbers.count)
}
}
//函数作为参数
//1、
func getBigger(num1:Int, num2:Int) -> Int{
return num1 > num2 ? num1 : num2
}
func getSum(num1:Int, num2:Int) -> Int {
return num1 + num2
}
func funcAsPara(takeFunc:(Int, Int) -> Int, para1:Int, para2:Int) -> Bool{
let result = takeFunc(para1, para2)
return result > 0 ? true: false
}
let letFuncAsPara1 = funcAsPara(takeFunc: getBigger, para1: 5, para2: 2)
let letFuncAsPara2 = funcAsPara(takeFunc: getSum(num1:num2:), para1: 3, para2: 2)
print(letFuncAsPara1, letFuncAsPara2)
//2、
func method1(para1:String, para2:String) -> String{
return para1 + para2
}
print(method1(para1:“采蘑菇”, para2:“小姑娘”))
func funcAsPara1(takeFuncPara:(_ a:String, _ b:String) -> String, para:String) -> String{
let methodStr = takeFuncPara(“book”, “pro”) + para
return methodStr
}
let letFuncAsPara = funcAsPara1(takeFuncPara: method1(para1:para2:), para: “air”)
print(letFuncAsPara)
func funcPara(takePara:(String, String)->String, para1:String, para2:String){
print(“输出:(para1 + para2)”)
}
let letFuncPara = funcPara(takePara:method1, para1:“我是”, para2:“一个兵”)
print(letFuncPara)
//函数嵌套
func chooseNumber(big:Bool,number1:Int,number2:Int) -> Int{
// func getSmaller() {
// print((number1>number2) ? number2 : number1)
// }
func getSmaller(num1:Int, num2:Int) -> Int{
return num1 < num2 ? num1 : num2
}
// func getBigger() {
// print((number1>number2) ? number1 : number2)
// }
func getBigger(num1:Int, num2:Int) -> Int{
return num1 > num2 ? num1 : num2
}
return big ? getBigger(num1: number1, num2: number2) : getSmaller(num1: number1, num2: number2)
}
//print(chooseNumber(big: false, number1: 5, number2: 2))
print(chooseNumber(big: true, number1: 20, number2: 30))
//函数的输入输出参数
//如果想要一个函数可以修改参数的值,并且这些修改在函数结束之后仍然存在,那就可以将参数定义为输入输出参数,这可以通过在参数类型的前面加入inout关键字来实现。
//同时,传入函数的参数,只能是变量,不能是常量,当传入的参数作为输入输出参数时,需要在前面加上&符号,表示这个参数值是可以被修改的。
func funcInout (num1: inout Int, num2: inout Int){
let temp = num1
num1 = num2
num2 = temp
print(num1, num2)
}
var inoutNum1 = 10
var inoutNum2 = 20
print(funcInout(num1: &inoutNum1, num2: &inoutNum2))
//常用的内置函数
//abs绝对值函数
abs(-1)
//min最小值函数
min(3,4,1)
//max最大值函数
max(2,5,3,1)
//filter函数
//filter函数用于查找在数组元素中,满足指定条件的元素,例如查数组中1~10能被3整除的数字。
let numbers = [1,2,3,4,5,6,7,8,9,10]
for i in numbers.filter({$0%3==0}) {
print(i)
}
//$0表示忽略了参数名,而使用默认参数为$0
//map函数
//map函数通常用于将数组中的每个元素,通过指定的方法进行转换。例如将数组中的每个整数都成3
let mapNumbers = [1,2,3,4,5,6,7,8,9,10]
for i in mapNumbers.map({$0*3}) {
print(i)
}
//reduce函数
//reduce函数可以把数组元素组合计算为一个值,比如将数组中每个数字进行加法计算,获得元素之和
let reNums = [1,2,3,4,5,6,7,8,9,10]
let sum = reNums.reduce(0, {$0+$1})
print(sum)
//第一个参数为初始值,这里设置初始值为0了,就是将 0,1…到10依次相加。
//也可以这样写
let sum2 = numbers.reduce(0, +)
print(sum2)
//枚举 枚举可以支持字典、字符、整数和浮点类型。作为枚举成员的数据类型
//enum 枚举名称 {
// 此处放置枚举的成员
//}
//enum UserLevel {
// case 总经理
// case 区域经理
// case 主管
// case 业务员
//}
//或
//enum UserLevel {
// case 总经理,区域经理,主管,业务员
//}
//给枚举添加方法
enum Gender : UInt8 {
case Male,Female,UnKnow
func description() {
switch self {
case.Male:
print(“Hi,Man~”)
case.Female:
print(“Hi,lady~”)
case.UnKnow:
print(“Hi~”)
}
}
}
let gender = Gender.Female
gender.description()
//结构体
//在Swfit开发环境中,结构体是构建代码所用的一种通用且灵活的结构体。
//Swfit中,把一些基本数据类型,string,array,dictionary等全部变成了结构体,更方便我们使用。
//可以为结构体定义变量或常量的属性,甚至可以像枚举一样,给结构体添加方法。
//struct 结构体名称 {
// // 此处为结构体内容
//}
struct Animal {
let zooName:String = “Beijing Zoo”
var name:String
}
//需要注意的是:类是引用类型,而结构体和枚举都是值类型。值类型是一种当它被指定为常量或变量,或被传递给函数时会拷贝的类型。这意味着你所创建的任意结构体和枚举实力,作为属性所包含的任何类型,在代码传递中总是被拷贝的。
//如例:
let firstAnimal = Animal(name:“Tiger”)
var secondAnimal = firstAnimal
secondAnimal.name = “Elephant”
print(firstAnimal) // 输出结果:Tiger
print(secondAnimal) // 输出结果: Elephant
//上例中,创建了一个Animal结构体的实体,并初始化name属性为Tiger。
//然后将firstAnimal实例赋予secondAnimal变量。当firstAnimal被赋予给secondAnimal变量时,firstAnima的值就被拷贝了一份。并将拷贝的实例赋予给secondAnimal,这样就产生了两个不同的实例。所以当secondAnimal的name属性修改时,firstAnimal的name不会变化。
struct AnimalStru {
let zoomName = “名字”
let name:String
func say() -> Void {
print(“动物名 (name)”)
}
}
let animal1 = AnimalStru(name: “????”)
print(animal1.name)
//结构体下标
struct TimeTable {
let multiplier : Int
subscript (index: Int) -> Int {
return multiplier * index
}
}
let timeTable = TimeTable(multiplier: 3)
print(timeTable[2])
//Swift类是构造代码的一种通用而灵活的构造体。类与结构体相似但不同,类和结构体都有属性,都可以定义方法,但类是引用类型,结构体是值类型。
//class 类名 {
// 属性列表
// 方法列表
//}
class Person {
var name : String
var age : Int = 0
var sex : String
init() {//Swift要求定义类时,类的属性一定要初始化
self.name = “zzzz”
self.age = 0
self.sex = “male”
}
init(name:String, age:Int, sex:String) {
self.name = name
self.age = age
self.sex = sex
print(“走这里”)
}
func action(name:String, age:Int, sex:String) {
self.name = name
self.age = age
self.sex = sex
print(“name=(name)”, “age=(age)”, “sex=(age)”)
}
}
let letPerson = Person(name: “qian”, age: 20, sex: “male”)
letPerson.name = “qian”
letPerson.age = 10
letPerson.sex = “male”
letPerson.action(name: “shen”, age: 12, sex: “male”)
//类属性的 set 和 get 方法
class Time {
var hour:Int = 1
var minute:Int {
get {
return hour * 60
}
set(newMinute){
self.hour = newMinute / 60
}
}
}
let timea = Time()
print(timea.hour)
print(timea.minute)
//willSet和didSet
//willSet 和 didSet 属于给类属性添加观察者。
//willSet在设置属性值之前被调用。
//didSet在设置属性值之后被调用。
//在实现willSet时,新的属性值将被作为常量参数来传递,可以给这个参数一个名字,如果没有,这个参数就被命名为newValue。
class Role {
var skill : Int = 1
var level : Int = 1 {
willSet {
print(“角色即将升级(newValue)”)
}
didSet {
if oldValue >= level{
print(“升级失败”)
}else {
print(“角色已经升级,等级到达 (level)”)
}
}
}
}
let letRole = Role()
letRole.level = 2
letRole.level = 3
//a -> 我们为level添加了willSet和didSet方法。
//b -> 在willSet方法中,调用此方法时,输出提示语,其中newValue是默认参数名。
//c -> 在didSet方法中,调用此方法,判断level是否有增长,输出条件语句。oldValue是旧值的默认参数名。
//静态方法 如果操作不需要具体实例,我们就可以定义近静态方法,反之,如果某些操作是需要具体实例的,那就需要定义实例化方法。
class MathTool {
class func sum(number1:Int ,number2:Int) -> Int {
return number1 + number2
}
class func multiply(num1:Int ,num2:Int) -> Int {
return num1 * num2
}
}
//调用的时候可以直接用类名调用,不需要实例化。如果某些地方不需要实例化,建议使用静态方法。
print(MathTool.sum(number1: 10, number2: 1))
print(MathTool.multiply(num1: 2, num2: 4))
//类的析构 Swift和Object-C都是通过ARC来管理内存的,不需要我们对实例化的对象进行释放操作,但有些环境中,可能需要我们自己去清理一些额外的资源,比如创建了一个自定义的类,这个类打开了一个文件,并写入若干数据,就需要我们再类实例被释放之前关闭该文件。
class FileManager {
func openFile() {
print(“open file from the resorce”)
}
func writeFile() {
print(“Write the data into the file”)
}
deinit {
print(“delete the fileManager”)
}
}
var fileManager:FileManager? = FileManager()
fileManager?.openFile()
fileManager?.writeFile()
fileManager = nil//在最后,添加了一个deinit,这个方法就是析构函数,当实例的引用计数为0时,系统自动调用这个方法,在输出结果中可以看出
//继承
class AnimalBase {
func run() {
print(“I can run”)
}
}
class Elephant:AnimalBase {
var name:String
override init() {
self.name = “elephant”
}
override func run() {
print("I'm a \(name), I can run.")
}
}
//请注意在init 和 run前面都有关键字 override
//如果不希望父类的属性、下标或方法被重写,可以在父类中的属性或方法前加final关键字,比如 final var、final func 等。
//当子类中尝试重写 final方法或属性时,编译器将会编译错误。
//延时加载属性lazy
class Point {
var pointValue:String = “1000”
}
class UserInfo {
var username:String = “Coco”
lazy var point:Point = Point()
}
let user = UserInfo()
print(user.point.pointValue)
//类的引用特性
//Swift中,元组、枚举、结构体属于值类型,而类属于引用类型。
//值类型的特征是在赋值、初始化和传递参数过程中的数据。并为这个数据创建一个崭新独立的实例。
//引用类型与值类型不用,引用类型的实例在被赋予到一个变量或常量或作为参数传递到另一个函数时,其操作的并不是类实例的拷贝,而是已存在的实例本身。就是说,假如值类型和引用类型都是一个常量的话,值类型传递的是对这个常量进行拷贝得到的另一个常量,而引用类型传递的就是这个常量本身。
//is、as、Any、Anyobject、?、!
//1、is、as 类型检查
//在swift中, 类型检查是一种检查实例类型的方式,同时也是让实例作为它的父类或子类的一种方式。
//Swift通过 is、as来实现类型检查
class World {
var name:String
init(name:String) {
self.name = name
}
}
class Per:World {
var food:String
init(name:String, food:String) {
self.food = food
super.init(name:name)
}
}
class Dog:World {
var tail:String
init(name:String, tail:String) {
self.tail = tail
super.init(name: name)
}
}
let arr:[World] = [Dog.init(name: “Benben”, tail: “Li”),
Per.init(name: “Li”, food: “apple”),
Dog.init(name: “Dandan”, tail: “Han”),
Per.init(name: “Han”, food: “orange”),
Per.init(name: “Liu”, food: “banana”)]
var dogNum:Int = 0
var personNum:Int = 0
for item in arr {
if item is Dog {
dogNum += 1
} else {
personNum += 1
}
}
print(dogNum)
print(personNum)
//as
for item in arr {
if item is Dog{
let dog = item as! Dog
print(“Dog:(dog.name), master:(dog.tail)”)
} else {
let person = item as! Per
print(“Person:(person.name), food:(person.food)”)
}
}
//Any和Anyobject
//有点类似OC中的id,Swift为不确定的类型,提供了两种特殊别名,any和anyobject,
//Anyobject可以表示class类型的实例。
//Any可以表示任何类型的实例。
var objects = Any
objects.append(3)
objects.append(3.141592653)
objects.append(“圆周率”)
for item in objects {
switch item {
case let someInt as Int:
print(“This is Int class (someInt)”)
case let someDouble as Double:
print(“This is Double class (someDouble)”)
default:
print(“This is String class (item)”)
}
}
//?和!
//在Swift中,我们用var来定义变量,但Swfit中并不会自动给变量赋初始值。 所以如果使用未赋值的变量就会报错。
//所以他们搞了一个?,告诉你,我也不知道这个变量是不是有值,或者是什么类型的值。
//当你确定了这个变量确实有值要怎么办?他们又搞了一个!,让你告诉系统,我确定这个变量有值,出了事情我负责,然后,如果这个值是空的,他们就给你报错,然后项目搞崩。气不气,气不气。
//我是这样理解的,然后我们来看一个Optional类型,它是一个枚举类型,这个类型只有两个元素,None和Some。就是说,nil对应Optional.None。
var password : String?
print(password?.count)
//a -> 第一行中,我们定义了一个password,右侧添加了?, 表示password变量属于Optional类型,他的值可能是String类型,也可能是nil请注意此时的password不是String类型,而是Optional类型,对于一个Optional类型的变量,如果未被初始化,他的默认值是nil。
//b -> 在第二行代码中,在password后面也加了一个?,表示对password进行拆包,尝试获取Optional包中的String内容。
//c -> 但因为password没有被赋值,所以最为Optional类型的password默认值为nil。此时会跳过characters.count语句,直接输出password的值,nil。
//当你使用!时,就表示你告诉编译器,你确定 password一定不是nil,但是password的值就是nil,所以系统会报错。
//当我们给password进行赋值之后,
var password1 : String?
password1 = “123456”
print(password1!.count)
//协议和扩展
//扩展可以完成以下任务:
//添加计算型属性和计算静态属性。
//定义实例方法和类方法。
//提供新的构造器。
//定义下标。
//定义和使用新的嵌套类型。
//使一个已有类型符合某个接口。
extension Int {
var double : Int {
return self * 2
}
var half : Double {
return Double(self)/2.0
}
func bigger(num : Int) -> Int {
if self <= num {
return num
} else {
return self
}
}
}
let num:Int = 1
print(num.double)
print(num.half)
print(num.bigger(num: 2))
//协议
protocol Walking {
func walk()
}
protocol Running:Walking {
var velocity:Double{get set}
func run()
}
//这是一个继承与Walking的协议Runing,并添加了属性velocity和方法run。协议能继承一个或多个其他协议,多个协议之间用,分隔开
protocol Eating {
func eat()
}
//上面的例子中,多加了一个Eating协议,然后我们定义一个类,去实现这些协议。
class People:Running,Eating {
var velocity: Double = 2.0
func walk() {
print(“I`m walking”)
}
func run() {
print("I`m runing")
}
func eat() {
print("I`m eating")
}
}
//上面的类中,遵循了2个协议 Runing、Eating,而Runing继承自Walking,所以也要实现Walking的方法。如果协议没有实现的话,系统会报错。People中,实现了协议中的属性velocity,实现的时候会发现是有自动提示的,然后实现了三个协议中的方法
//属性观察器
class LightBlub{
static let maxCurrent = 30
var current = 0 {
didSet(oldCurrent) {
if current == LightBlub.maxCurrent {
print(“the current value get to the maxnum”)
}else if current > LightBlub.maxCurrent {
print(“过高”)
current = oldCurrent
}
print(“the current value is (current)”)
}
}
}
let blub = LightBlub()
blub.current = 20
blub.current = 30
blub.current = 40
上一篇: Resin的几个常用配置
下一篇: 几个常用的js技巧