swift速览

314 阅读7分钟

基本用法

  1. 变量
var a = 3
var b: NSInteger? = 3
var c: NSInteger?
var d: NSInteger
d = 0
  1. 数组字典
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?]()
  1. 流程控制与遍历
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)
}
  1. 元组
//元组存储混合复杂类型
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. 对于存有混合类型的数据比较适合用元组
  1. 函数
//带参函数
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)
  1. 闭包
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)
闭包还可以作为数据回调,就是属性回调传值
  1. 对象和类
//类和对象的简单使用
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就是解包。
  1. 枚举和结构体

    1. 枚举类型
    
        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)")
    }
    
    
    1. 结构体
    //结构体
    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. 结构体很像类,它内部可以定义变量,函数,构造器等,和类的区别就是一个是传值,一个是传引用
     
    
  2. 协议和扩展

//协议
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方法用关联对象的方式。
  1. 错误处理
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)

  1. 泛型
//泛型来重复任意元素
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比较

  1. OC中有自增,自减运算符,但是swift中没有。可能swift认为这种运算容易出错吧。
  2. OC中没有元组的概念,swift中有,它是对数组和字典的增强,适合在存储混合类型时候用。
  3. OC中运算符前后两者变量类型不必完全相同。但是swift中运算符前后如果是变量,那么要求类型必须完全相同,字面量除外
  4. OC中的switch语句只能是整数,但是swift可以是字串,但是必须要有default。增强的同时又保证了安全性。
  5. OC中没有可选类型概念,但是swift中有。
  6. OC中变量可以不赋值初始值,但是swift中定义变量要求要有初始值和类型。