基本用法
- 变量
var a = 3
var b: NSInteger? = 3
var c: NSInteger?
var d: NSInteger
d = 0
- 数组字典
var a = [1,2,3]
var b: [Any?] = [4,5,"4"];
var c = [String?]()
var d = ["name":1, "type":2]
var f: [String: Any?] = ["name":1, "type":"5"]
var g = [String : Any?]()
- 流程控制与遍历
var a = [1,2,3,4,5]
var c = ["a":1, "b":2, "c": nil]
for value in a{
if value <= 3{
print(value)
}
}
for (index,value) in a.enumerated(){
if value <= 3{
print(value)
}
}
for value in 1..<5{
if value <= 3{
print(value)
}
}
for (key, value) in c{
print("key:\(key)")
print("value:\(value)")
}
var b = "56"
switch b {
case "1":
print(b)
default:
print(b)
}
- 元组
//元组存储混合复杂类型
var b = ("1",1,1.0,name:5,[1,2,3])
//数组无法存储这种混合复杂类型-报错
var bsz: [Any] = ["1",1,1.0,"name":5,[1,2,3]]
//元组存储复杂类型
var c = ("0",1,"2")
//元组存储复杂类型-指定每个元素的类型
var d: (String, Int, String) = ("0",1,"2")
//数组可以存储复杂类型-但是无法指定每个元素的类型
var csz: [Any] = ["0",1,"2"]
1. 有时候数组存不了复杂混合类型
2. 即使可以存储了,但是不能指定每个元素的确定类型
3. 对于存有混合类型的数据比较适合用元组
- 函数
//带参函数
func numValue(number:[Int]) -> (max:Int, min:Int, sum:Int){
var sumUse = 0
var maxUse = number[0]
var minUse = number[0]
for vale in number{
if vale > maxUse{
maxUse = vale
}else if(vale < minUse){
minUse = vale
}
sumUse += vale
}
return (maxUse, minUse, sumUse)
}
var a = [1,53,5,234,54,]
print(numValue(number: a))
print(numValue(number: a).max)
//不定参数
func sum(numbers:Int...) -> Int{
var sum = 0
for item in numbers {
sum += item
}
return sum
}
print(sum())
print(sum(numbers: 1,4,2,5))
//计算参数平均值
func average(numbers:Int...) -> Double{
var average = 0.0
var sum = 0
for item in numbers {
sum += item
}
average = Double(sum)/Double(numbers.count)
return average
}
var strNumber = String(format: "%.2f", average(numbers: 1,2,4))
print(strNumber)
//函数嵌套 ~ 一个函数逻辑很复杂可以考虑使用
func add() -> Int{
var ret: Int = 0
func add1() -> Int{
return ret + 1
}
ret = add1()
return ret
}
print(add())
//函数作为返回值
func add1Func() -> (Int) -> Int{
func add(number:Int) -> Int{
return number + 1
}
return add
}
var addOne = add1Func()
print(addOne(55))
//函数作为入参
var numbers = [20, 19, 7, 12]
func lessThen10(list:[Int]) -> Int?{
for item in list {
if item < 10{
return item
}
}
return nil
}
func less10ValueAddOne(list:[Int], funcThen10:([Int]) -> Int? ) -> Int?{
var ret: Int? = 0
ret = funcThen10(list)
if ret != nil{
ret = ret! + 1
}
return ret
}
var temp = less10ValueAddOne(list: numbers, funcThen10: lessThen10(list:))
print(temp)
- 闭包
func addOne(list:[Int], maxValeBlk:(Int)->(), minValueBlk:(Int)->()){
var max = list[0]
var min = list[0]
for item in list {
if item > max{
max = item
}else if(item < min){
min = item
}
}
maxValeBlk(max)
minValueBlk(min)
}
var numbers = [1,4,1,432,235,8]
addOne(list: numbers, maxValeBlk: { (max) in
print(max)
}) { (min) in
print(min)
}
//系统内部函数使用闭包
var numbers = [20, 19, 7, 12]
var temp = numbers.map({
(number: Int) -> Int in
let result = 3 * number
return result
})
print(temp)
闭包还可以作为数据回调,就是属性回调传值
- 对象和类
//类和对象的简单使用
class Shape{
var numberOfSides = 0
var name = ""
init(name:String) {
self.name = name;
}
func simpleDescription() -> String {
return "a shape with \(self.numberOfSides) sides"
}
}
class Circle: Shape{
var radios = 0.0
var perimeter: Double{
get {
return 2 * Double.pi * self.radios
}
set {
radios = newValue/(2 * Double.pi)
}
}
init(name:String, radios:Double) {
super.init(name: "circle")
super.name = name
super.numberOfSides = 0
self.radios = radios
}
func area() -> Double {
return Double.pi * self.radios * self.radios
}
override func simpleDescription() -> String {
return "a circle with \(self.numberOfSides) sides"
}
}
var circle = Circle(name: "a circle", radios: 2)
print(circle.area())
print(circle.simpleDescription())
circle.name = "test"
circle.radios = 10
print(String(circle.name) + " " + String(circle.radios))
//属性观察器
import UIKit
class Shape{
var numberOfSides = 0
var name = ""
init(name:String, sides:Int) {
self.name = name
self.numberOfSides = sides
}
func simpleDescription() -> String {
return "a shape with \(self.numberOfSides) sides"
}
}
class Circle: Shape{
var radios = 0.0
var perimeter: Double{
get {
return 2 * Double.pi * self.radios
}
set {
radios = newValue/(2 * Double.pi)
}
}
init(name:String, radios:Double, sides:Int) {
super.init(name: "circle", sides: sides)
super.name = name
self.radios = radios
}
func area() -> Double {
return Double.pi * self.radios * self.radios
}
override func simpleDescription() -> String {
return "a circle with \(self.numberOfSides) sides"
}
}
class CircleAndShape {
var shape: Shape{
willSet {
circle.numberOfSides = newValue.numberOfSides
}
}
var circle: Circle{
willSet {
shape.numberOfSides = newValue.numberOfSides
}
}
init(sides:Int, name: String) {
shape = Shape(name: name, sides: sides);
circle = Circle(name: name, radios: 3, sides: sides)
}
}
var circleAndShape = CircleAndShape(sides: 4, name: "hah")
print("\(circleAndShape.circle.numberOfSides) \(circleAndShape.shape.numberOfSides)")
circleAndShape.shape = Shape(name: "fas",sides: 5)
print("\(circleAndShape.circle.numberOfSides)")
总结:
1. 属性分为存储属性和计算属性
2. 存储属性:
1. 存储属性就是类中简单的变量,结构体等。
2. 存储属性可以是懒加载类型
3. 存储属性可以用属性观察器。
3. 计算属性:
1. 计算属性赋值计算,不负责存储。
2. 计算属性是重写getter方法。
3. 如果只是重写了getter方法,那么就是只读属性。
4. !是确定有值,强制解包。?是不确定是不是nil,要先判断如果是nil,就返回nil。如果不是nil就是解包。
-
枚举和结构体
- 枚举类型
case Mon case Tue case Wen case Thu case Fri func description() { switch self { case .Mon: print("本周工作第一天") case .Fri: print("本周还有一天放假") default: print("还是工作吧") } } } Weekady.Mon.description() Weekady.Fri.description() Weekady.Thu.description()enum Weekady: Int { case One = 1 case Two case Three case For case Fiv func big(first:Int, second:Int){ if first > second { print("first big") }else{ print("second big") } } } Weekady.One.big(first: Weekady.One.rawValue, second: Weekady.For.rawValue)//关联值 enum ServerResponse { case result(String, String) case failure(String) } var succeed = ServerResponse.result("6:00 am", "8:09 pm") var error = ServerResponse.failure("a error") switch succeed { case let .result(sunrise, sunset): print("succeed: sunrise is \(sunrise) sunset is \(sunset)") case let .failure(error): print("error: \(error)") }- 结构体
//结构体 enum Rank: Int { case three = 3 case four, five, six, seven, eight, nine, ten case j, q, k case one = 14 case two = 15 func descripthion() -> String{ return "\(self)" } } enum Suit { case spades, hearts, diamonds, clubs func description() -> String{ return "\(self)" } } struct Card { var rank: Rank var suit: Suit init(rank:Rank, suit:Suit) { self.rank = rank self.suit = suit } func description() { print("The Card : \(suit.description()) \(rank.descripthion())") } } var aCard = Card(rank: Rank.three, suit: Suit.hearts) aCard.description() var bCard = Card(rank: Rank.one, suit: Suit.clubs) bCard.description() if aCard.rank.rawValue > bCard.rank.rawValue { print("aCard is big") }else{ print("bCard is big") }3.总结
总结: 1. 枚举类型如果涉及到了赋初始值,要写上类型,如:Int 2. 枚举类型内部可以定义函数,支持switch case来匹配,这时候case后边用.来匹配类型 3. 枚举类型支持关联值枚举,在枚举外部可以用switch case匹配 case后边用 let .来匹配 4. 结构体很像类,它内部可以定义变量,函数,构造器等,和类的区别就是一个是传值,一个是传引用 -
协议和扩展
//协议
protocol exampleProtocol {
var aVale: String {get}
mutating func despriction()
}
struct Circle: exampleProtocol {
var aVale: String = "test"
mutating func despriction() {
print("Circle")
}
}
import UIKit
protocol number {
mutating func onlyTwo() -> String
}
extension Double: number {
func onlyTwo() -> String{
var str = String(format:"%.2f",self)
return str
}
}
print(5.12345.onlyTwo())
总结:
1. swift的类扩展就是OC的分类,只能新增方法,不能新增属性。使用场景,往往是提供工具类。
2. swift的类扩展要实现新增属性,还是得重写get,set方法用关联对象的方式。
- 错误处理
import UIKit
//错误处理
enum Job: Error{
case noJob
case noMoney
}
func goToJob(name:String) throws -> String{
if name == "job" {
throw Job.noJob
}else if name == "money"{
throw Job.noMoney
}
return name
}
do {
let name = try goToJob(name: "money")
print(name)
} catch Job.noMoney{
print("noMoneyError")
}catch {
print(error)
}
let name = try? goToJob(name: "job1")
print(name)
//defer:延时执行,函数执行结束后要执行的代码块
var flag = false
func retFlag() -> Bool{
defer {
flag = true
}
flag = false
return flag
}
print(retFlag())
print(flag)
- 泛型
//泛型来重复任意元素
func repeatElements<T>(_ ele:T,_ repeatCount:Int) -> [T]{
var temp = [T]()
for _ in 1...repeatCount{
temp.append(ele)
}
return temp
}
var temp = repeatElements("2", 4)
print(temp)
var temp1 = repeatElements(4, 4)
print(temp1)
var temp2 = repeatElements(3.14, 4)
print(temp2)
//泛型查找任意类型相同的元素
func commonElements<T: Sequence, U: Sequence>(_ lhs:T, _ rhs:U) -> [Any]
where T.Iterator.Element: Equatable, T.Iterator.Element == U.Iterator.Element{
var ret = [Any]()
for lhsItem in lhs {
for rhsItem in rhs {
if lhsItem == rhsItem {
ret.append(rhsItem)
}
}
}
return ret
}
var a = commonElements(["1","2","3"], ["2","1"])
print(a)
var b = commonElements([1,2,4], [2,4])
print(b)
总结:
1. swift编写函数时候如果类型不确定可以用泛型,也可以进一步对泛型进行限制。
2. Any是任意基本类型,AnyObject是任意引用类型
3. 函数使用泛型更好些,因为swift编译器会进行类型检测,而使用Any会跳过编译器的类型检测,这样不好。
4. 因为swift是类型安全语言,也就是在定义变量等时候要写上存储的类型,但是oc不需要,所以导致swift中泛型用的更多。
5. 函数中的返回值数据类型如果用新的泛型可能导致报错可以用Any等。
Swift和OC比较
- OC中有自增,自减运算符,但是swift中没有。可能swift认为这种运算容易出错吧。
- OC中没有元组的概念,swift中有,它是对数组和字典的增强,适合在存储混合类型时候用。
- OC中运算符前后两者变量类型不必完全相同。但是swift中运算符前后如果是变量,那么要求类型必须完全相同,字面量除外
- OC中的switch语句只能是整数,但是swift可以是字串,但是必须要有default。增强的同时又保证了安全性。
- OC中没有可选类型概念,但是swift中有。
- OC中变量可以不赋值初始值,但是swift中定义变量要求要有初始值和类型。