Swift语法复习

// 教程地址:https://www.bilibili.com/video/BV1mT4y1C7JZ?p=16&vd_source=84310ee3c28453390868c23631486732

import UIKit
class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        do {
            // 数据类型转换
//            let i: Int = 10
//            let j = 0.1
//            let c = Int(j) + i
//            print("c:\(c)")
//            
//            // 元组
//            let error = (tit: 400, ddd: "not found")
//            let d = error.0
//            print("d:\(d)")
//            
//            let (code, des) = error
//            print(code, des)
//            
//            let _ = error.tit
        }
        
        do {
            // if语句
//            var i = 10
//            if i > 0 {
//                print("i 大于 0")
//            }
        }

        // 循环 还可以使用where条件
        do {
//            var i = 10
//            repeat {
//                print(10)
//            } while i < 10
//            
//            for i in 0...3 {
//                print(i)
//            }
//            
//            for i in 0..<3 where i > 1 {
//                print(i)
//            }
//            
//            let array = [1, 2, 3 ,4]
//            for item in array[0..<2] {
//                print("haha\(item)")
//            }
//            
//            for item in array[...2] {
//                print(item)
//            }
        }
        
        // switch
        do {
            var c = "c"
            
            switch c {
            case "1":
                print("haha")
            case "2", "3":
                print("aaaa")
            default:
                break
            }
            
            // 区间匹配
            var index = 10
            switch index {
            case 0...1:
                fallthrough
                
            case 2...3:
                break
                
            default:
                break
            }
            
            // 元组匹配
            let tuple = (1, 1)
            switch tuple {
            case (_, 1):
                break
                
            case (1...2, 1):
                break
                
            case (1...2, 1..<3):
                break
                
            default:
                break
            }
            
            // 值绑定
            switch tuple {
            case (2, let a):
                print(a)
                
            case let (x, y):
                print(x, y)
                
            case let (a, b) where a > b: // 使用where过滤条件
                print(a)
            }
        }
    }

}

/// ------------
// 函数
func 函数() {
         
    // 有入参 有返回值
    func func1(a: Int, b: Int) -> Int {
        return a + b
    }
    // 无入参无返回值
    func fun2() {
        
    }
    // 带参数标签和默认参数值
    func fun3(outname inname: Int = 10) {
        
    }
    
    // 可变参数
    func fun4(numbers: Int..., age: Int) {
        for index in numbers {
            print(index)
        }
    }
    
    // 输入输出参数
    func fun5(a: inout Int) {
        a += 5
    }
    
    
}

/// ------------
 
func 别名typealias() {
    
    // 给元组声明一个别名
    typealias Date = (year: Int, month: Int, day: Int)
    
    func eatAt(date: Date) {
        print(date.0)
        print(date.year)
    }
    eatAt(date: (2011, 2, 1))
    
    // 给函数声明一个别名
    typealias DeleteFunc = (Int, Int) -> Int
    
    func operate(f: DeleteFunc, a: Int, b: Int) -> Int {
        return f(a, b)
    }
    
    
}
/// ------------
func 枚举enum() {
    
    // 原始值 rawValue
    enum Score: Int {
        case point = 2 // 设置原始值
        case grade = 43 // 设置原始值
    }
    
    let s = Score.grade
    // 打印原始值
    print(s.rawValue)
    
    let _ = Score(rawValue: 65)
    
    // 隐式原始值,如果枚举的原始值类型是Int或者String, swift会默认设置原始值
    enum Di: String {
        case source // swift会默认设置 case source  = "source"
        case north
    }
    
    
    typealias Location = (x: Int, y: Int)
    
    // 关联值
    enum Direction {
        case sourth(Location)
        case east(Int)
        case west(Float)
    }
    
    var dir = Direction.sourth((10, 20))
    // 可以根据类型推断出枚举类型  就可以用.省略类型
    dir = .east(1)
    print(dir)
    
    // 枚举结合switc
    switch dir {
    case .east(let value) where (10...20).contains(value):
        print(1)
    case .sourth(let location) where location.x == 10:
        print(location.x)
    default:
        break
    }
}
/// ------------
func 可选项optional() {
    // 类型后面+?
    var name: String? = "jack"
    name = nil
    
    print(name) // Optional(jack)
    
    // 可选值强制解包
    let n = name!
    print(n) // jack
    
    // 可选绑定
    if let number = Int("123123") {
        // number是解包后的值  123123
        
    } else {
        
    }
    // 可选绑定的if语句中 需要使用,分割
    if let a = Int("1"),
       let b = Int("2"),
       a > b {
        print("yes")
    }
    
    // 空合并运算符  a??b  , a为可选项 b为可选项或者值都可以
    
    var score1: String? = "11"
    var score2: String? = "2"
    print(score1 ?? score2)
    print(score1 ?? 2) // 如果返回score1  那么会强制解包,因为后面的是一个值 非可选项
    
    if let n = score1 ?? score2 {
        // 这种写法等价于 scrol1 != nil || score2 != nil
    }
    
    if let n = score1,
       let c = score2 {
        // 这种写法等价于 scrol1 != nil && score2 != nil
    }
    
    // guard语句,当条件为false的时候 会执行括号里面的代码
    // guard 条件 else { return、break、continue退出}
    guard let c = Int("adfasf") else {
        print("条件没有成立")
        return
    }
    print(c)
    
    // 隐式解包:如果一个可选值必定有值,可以在类型后面+!
    let s: Int! = Int("123")
    let d: Int = s
    print(d)
    
    // 多重可选项
    let t: Int? = Int("234234")
    let m: Int?? = t // 包装了一个可选值的可选值
    
    // 可选项本质是枚举
    enum Optional<T> {
        case same(T)
        case none // nil
    }
     
}
/// ------------


func 结构体struct() {
    // 编译器会默认给结构体增加一个初始化器 Initializer, 它的宗旨是保证所有的存储属性都有初始值
    struct Date {
        var year: Int
        var month: Int
        var day: Int
    }
    
    let d1 = Date(year: 2022, month: 2, day: 2)
    
    // 自定义初始化器
    struct Datt {
        var year: Int
        var m: Int
        // 自定义初始器,此时编译器就不会生成默认初始化器
        init(yy: Int, mm: Int) {
            self.m = mm
            self.year = yy
        }
    }
    
    // let类型的结构体 它的存储属性也是let类型不可以修改
    let d = Date(year: 11, month: 1, day: 1)
     // d.day = 22  会报错
    
}
/// ------------
func 类class() {
    
    // 编译器不会给类生成默认初始化器
    class Student {
        var age: Int
        var name: String
        
        init(age: Int, name: String) {
            self.age = age
            self.name = name
        }
    }
    
    let s = Student(age: 1, name: "jack")
    
}
/// ------------
///
func 闭包() {
    // swift中可以使用func来定义一个函数,也可以使用闭包来定义函数
    
    /*
      闭包格式
      {
        (参数列表) -> 返回值类型 in
        函数体代码
      }
    */
    
    // 使用func定义函数
    func sum(a: Int, b: Int) -> Int {
        a + b
    }
    
    // 使用闭包定义函数
    var fuck = {
        (a: Int, b: Int) -> Int in
        a + b
    }
    
    
    let _ = sum(a: 1, b: 2) // 调用func函数
    let _ = fuck(2, 4) // 调用闭包,闭包会省略参数标签
    
    // 如果闭包是函数的最后一个参数 可以使用尾随闭包
    func delete(a: Int, b: Int, fc: (Int ,Int) -> Int) -> Int {
        fc(a, b)
    }
    
    _ = delete(a: 1, b: 2) { a, b in
        a + b
    }
    
    _ = delete(a: 1, b: 3, fc: {
        $0 + $1
    })
}
/// ------------



func 方法() {
    
    // 值类型如果想要在方法中修改属性  需要使用mutating关键字
    struct DDD {
        var x: Int = 10
        mutating func changeX(a: Int) {
            x = a
        }
    }
    
    class DS {
        // 相当于dispatch once
        static let a = "adfaf"
    }
    
    // 消除函数返回值未使用的警告@discardableResult
    @discardableResult func delete(a: Int, b: Int) -> Int {
        a - b
    }
    
    // 下标subscript
    class Person {
        var age: Int = 10
        
        // 下标方法可以是类方法  在前面增加static字段即可
        subscript(index: Int) -> Int {
            set {
                if index == 0 {
                    age = newValue
                }
            }
            
            get {
                if index == 0 {
                   return age
                }
                return 3
            }
        }
        
    }
    
}

/// ------------


func 继承() {
    
    // 类可以继承,结构体不行
    // 继承后可以重写父类的方法或者属性 使用override关键字
    
    class Animal {
        var name = ""
        var age:Int = 10
    }
    
    class Dog: Animal {
        // 重写父类属性为计算属性
        override var name: String {
            set {
                super.name = newValue
            }
            get {
                return ""
            }
            

        }
        
        // 在子类中给父类存储属性添加观察器, 也可以给父类的计算属性添加属性观察器
        override var age: Int {
            willSet {
                print(newValue)
            }
            
            didSet {
                print(oldValue)
            }
        }
        
        // 被final修饰的属性 方法,禁止被重写。类禁止被继承
        
        
    }
    
}

/// ------------

func 初始化构造链() {
    
    // 父类的属性在自己的初始化方法中给属性赋值,不会触发属性观察器
    // 父类的属性 在子类的初始化方法中给属性赋值,会触发属性观察器
    class Animal {
        var age: Int
        
        init(age: Int) {
            self.age = age
        }
    }
    
    class Dog: Animal {
        
        var name: String
        
        init(name: String) {
            // 1. 子类先初始化自己的东西
            self.name = name
            
            // 2. 再调用父类构造方法
            super.init(age: 1)
            
            // 第二阶段后 才可以使用self关键字
            
            // 3. 最后可以自定义一些东西
            age = 10
        }
    }
    
    // --------
    
    class Person {
        var age: Int
        // 使用关键字required  那么子类必须继承或者重写该指定初始化器
        required init(age: Int) {
            self.age = age
        }
    }
    
    class XiaoMing: Person {
        // 子类也必须使用required关键词重写  不用加override
        required init(age: Int) {
            super.init(age: age)
        }
    }
    
    // -----
    // 可失败初始化器
    class Bird {
        var age: Int
        init?(age: Int) {
            if age < 0 {
                return nil
            }
            self.age = age
        }
    }
    
    // ------
    // 反初始化器
    class Fish {
        // 先调用子类的deinit方法,后再调用父类的deinit方法
        // 父类的反初始化方法可以继承给子类,即子类销毁的时候 会调用父类的deinit方法
        deinit {
            print("销毁了")
            
        }
    }
    
}

func 可选链() {
    
    class Person {
        var age: Int = 0
    }
    
    var p: Person? = Person()
    // 结果是可选项 因为p有可能是nil,如果p是nil的情况  那么就不会继续调用.age方法
    let _ = p?.age
    // 如果本来就是可选项  那么可选链不会再次包装 也就是不会出现??的情况
    
    
    // ----
    // 利用可选链有值才会继续向后执行的特性
    // 第二行加上?  会判断 如果w有值才会继续赋值20, 如果w没有值  那么就不会执行后面的赋值操作了
    var w: Int? = 10
    w? = 20
    
    
}

/// ------------

 // 协议
protocol 协议 {
    func haha() // 定义方法
    var name: String { get set } // 定义属性 并声明可读可写权限, 子类可以实现一个存储属性 也可以是计算属性
    var age: String { get }
    subscript(index: Int) -> String { get set }
    // 定义类方法 必须用static关键字 不能使用class,因为有可能是结构体遵守这个协议
    static func eat()
    mutating func say() // 如果要在方法中修改属性值,必须在协议中增加mutating关键字
    
    // 协议中定义方法不能带默认参数值
    // 协议中定义属性必须用var  不能用let,因为实现的时候 有可能是计算属性 值是不确定的
    // 协议中声明的权限  实现的时候可以大于 不能小于,比如是get只读权限 实现的时候 可以为可读可写
    
    // 协议中还可以定义默认初始化方法。但是实现类必须加上required关键字
    init(age: Int)
        
}

protocol hha {
    
}
class PPPPP {
    
}
// 别名
typealias 多组合 = PPPPP & 协议 & hha
// 协议组合,要求参数是指定类型且遵守必要的协议
func eat(a: 多组合) {
    
}


/// ----------
/// 枚举遵循CaseIterable协议  就可以实现枚举遍历
enum Season: CaseIterable {
    case summer
    case winter
}

func 遍历season() {
    
    for cacse in Season.allCases {
        print(cacse)
    }
}

/// ----------
/// 对象遵守CustomStringConvertible并实现description方法 就可以自定义print内容
class CustomStringC: CustomStringConvertible {
    var age: Int = 0
    var description: String {
        return "\(age)哈哈"
    }
}


/// --------------
/// swift提供了两种特殊的类型 Any和AnyObject。或者说是两种协议
/// Any可以代表任意类型  枚举、结构体、类型、函数
/// AnyObject可以代表任意类类型,不能代表结构体。 如果协议后面注明AnyObject,表示只有类才能遵守这个协议
protocol ClassProtocol: AnyObject {
    
}
class BBB: ClassProtocol {
    
}

var anyArr = Array<Any>() //  存放任意类型的数组
var anyObjArr = Array<AnyObject>() // 存放任意类的数组
var anyDic = [Any]()
var anyObjDic = [AnyObject]()


/// --------------
/// is  as  as?  as!
/// is用来判断是否是某种类型
/// as用来做类型转换。 as?表示可选转换,  as!表示强制解包, as表示百分百转换成功  比如as Any时候可以用as
///
func is_as() {
    
    var a: Any
    a = 10
    if a is Int {
        print("是整型")
    }
    
    class Person {
        func eat() {
            print("eat")
        }
    }
    
    var p: Any = Person()
    // as?拿到的是可选类型 因为转换有可能失败
    // 第二个?代表是可选链调用eat方法,当前面成立 不为nil 才会调用eat方法
    (p as? Person)?.eat()
    
}

/// --------------
protocol haha {
    func test() -> Self
}
func self_type_AnyClass() {
    // X是类
    // X.self是一个元类型的指针,元类型中存放着类的相关信息,可以称为元类型 相当于oc的class
    // X.self是X.type类型
    class Person {
        required init() {
        }
    }
    
    var typet: Person.Type = Person.self
    // oc中使用class来创建vc ,在swift中可以使用元类型x.type来创建
    // [[class alloc] init];
    let _ = Person.self.init()

    func create(type: Person.Type) {
        let _ = type.init()
    }
    
    
    // Self一般用作返回值类型 或者参数类型,限定返回值必须跟方法调用者是同一个类型
    // 类似于oc的instancetype
    
    class Person1: haha {
        required init() {
        }
        
        func test() -> Self {
            return type(of: self).init()
        }
    }
    
    
}


func 错误error() {
    // swift可以自定义运行时错误
    // 可以自定义类 遵守Error协议, 可以是枚举或者类或者结构体
    enum MyError: Error {
        case local(String)
        case remote(Int)
    }
    
    // 方法需要增加throws关键字
    // 方法内部抛出错误使用throw关键字
    func delete(a: Int, b: Int) throws -> Int {
        
        if a < b {
            throw MyError.local("haha")
        }
        return a - b
    }
    
    // 调用的时候  可以使用try  try?   try!
    // 1,调用时候一般使用do catch来捕捉错误
    do {
        
        print(1)
        var _ = try delete(a: 10, b: 1) // 如果这一步异常了 就不会执行下面print2
        print(2)
        
    } catch let MyError.local(ll) {
        print(ll)
    } catch let MyError.remote(rrr) {
        print(rrr)
    } catch {
        print("兜底")
    }
    
    // 语法糖
    do {
        try delete(a: 10, b: 1)
    } catch let error as MyError {
        print(1)
    } catch is MyError {
        print(23)
    } catch {
        
    }
    
    
    // 2. 调用方法的时候 还可以不处理 使用throws继续往上抛
    func callDelete() throws {
      var _ =  try delete(a: 10, b: 1) // 如果这一行执行报错 后面print也不会再执行了
        print(3)
    }
    
    // 3.使用try? try!
    var _ = try? delete(a: 10, b: 10) // 返回的是Int?类型  如果正常是可选值Optional(Int)  如果错误是nil ,跟下面的写法等价
    do {
        try delete(a: 10, b: 10)
    } catch {
        
    }
    
    // 还可以使用try! 强制解包
    let _ = try! delete(a: 10, b: 10) // 返回值是Int类型
    
    
}


func 懒执行defer() {
    // 用来定义任何方式离开前  都必须会执行的代码,包括return 抛异常error
    defer {
        
    }
}


func 泛型() {
    
    // 1.方法中使用泛型
    // 交换参数
    func swapValue<T>(a: inout T, b: inout T) {
        (a, b) = (b , a)
    }
    var a = 10
    var b = 2
    swapValue(a: &a, b: &b)
    
    // 把泛型函数赋值给变量
    let fu: (inout Int, inout Int) -> () = swapValue
    fu(&a, &b)
    
    // 2.类中使用泛型
    class Stack<T> {
        
        var array = [T]()
        func push(t: T) {
            array.append(t)
        }
    }
    // 创建类的时候 需要显式标明类型
    var s = Stack<Int>()
    // 如果是子类继承 也需要增加泛型
    class SSStack<T>: Stack<T> {
        
    }
    
    
}


/// ------
func associatedType关联类型() {
    
}

// 给协议中用到的类型 定义一个占位名称,可以简单理解协议中想要实现泛型  不能用上面的<T>这种方式 只能使用关联类型这种方式
// 协议中可以定义多个类型
protocol Stack {
    associatedtype element

    mutating func push(e: element)
}

// 遵守协议的时候, 可以通过typealias来指定类型,也可以省略typealias 让编译器自己根据我们写的方法类型判断
class BBBB: Stack {
    typealias element = Int
    func push(e: Int) {
        print(1)
    }
}

/// -------- 类型约束
/// 约束泛型t的类型或者必须遵守协议
func mutal<T: PPPPP & Stack>(a: T) -> T {
    return a
}
/// 约束协议中的泛型必须遵守协议
protocol Hadaf {
    associatedtype T: Stack
}

// 还可以在func中增加where语句做更细致的类型约束
func aasdfas<T, M>(a: T, b: M) where T == M {
    
}
/// some 限制只能返回一种类型,不透明协议
protocol Masdfasf {
    associatedtype T
}
class Flya: Masdfasf {
    typealias T = Int
}
class FlaB: Masdfasf {
    typealias T = Double
}

func getf(a: Int) -> some Masdfasf { // 限制方法内部 只能返回一种遵守Masdfasf的类型 不能返回两种
    return FlaB()
}


///-------- 溢出运算符
/// swift支持溢出运算 &+  &-  &*
var max = Int8.max
var mmm = max + 1 // 会崩溃 因为溢出了
var mmmm = max &+ 1 // 不会崩溃  但是会变成最小值 因为溢出了


///-------- 运算符重载
struct HhhAAA {
    // 运算符重载方法 需要增加static关键字
    static func +(a: HhhAAA, b: HhhAAA) -> HhhAAA {
        return a
    }
    
    static func +=(a: HhhAAA, b: HhhAAA) -> HhhAAA {
        return a
    }
    
}
/// equatable协议 就是重载==运算符
class Eafafd: Equatable {
    var name: Int = 0
    static func ==(lhs: Eafafd, rhs: Eafafd) -> Bool {
        return lhs.name == rhs.name
    }
}

/// Comparable协议 用来重载<实现比较大小
//class ASDFAFD: Comparable {
//    static func < (lhs: ASDFAFD, rhs: ASDFAFD) -> Bool {
//        return true
//    }
//
//}


/// 自定义运算符  使用operator关键字
///
/// ------------  拓展 entension,类似于oc的分类
/// 可以添加方法、计算属性、下标、(便捷)初始化器、嵌套类型、协议等等
//扩展不能办到的事情:
//  口不能覆盖原有的功能
//  口不能添加存储属性,不能向已有的属性添加属性观察器
//  口不能添加父类
//  口不能添加指定初始化器,不能添加反初始化器
class Paer {
}
extension Paer {
}


/// ------------  访问控制 权限控制
/// 访问权限控制这块,Swift提供了5个不同的访问级别(以下是从高到低排列,实体指被访问级别修饰的内容)
/// 模块可以理解为一个可执行文件  target,一个动态库或者静态库是一个模块
//口open:允许在定义实体的模块、其他模块中访问,允许其他模块进行继承、重写(open只能用在类、类成员上)
//口public:允许在定义实体的模块、其他模块中访问,不允许其他模块进行继承、重写
//口internal:只允许在定义实体的模块中访问,不允许在其他模块中访问
//口fileprivate:只允许在定义实体的源文件中访问
//口private:只允许在定义实体的封闭声明中访问

//访问级别的使用准则
//一个实体不可以被更低访问级别的实体定义,比如
//变量\常量类型 >= 变量\常量
//口参数类型、返回值类型  >= 函数
//父类子类 >= 父协议子协议
//原类型  >=  typealias
//原始值类型、关联值类型 >= 枚举类型
//定义类型A时用到的其他类型 >= 类型A



/// ----- 内存管理 weak  unowned
/// weak定义的必须是可选类型的var 因为销毁后arc会自动把该弱引用置为nil  类似于oc的weak
/// unowned 类似于oc的assing  对象销毁后还保存着该指针 再次访问容易引发野指针崩溃
// 如果想在定义闭包属性的同时引用self,这个闭包必须是lazy的(因为在实例初始化完毕之后才能引用self)

func weakUnowned() {
    class Person {
        //左边的闭包fn内部如果用到了实例成员(属性、方法)
        lazy var fn: (() ->()) = {
            [weak self] in
            //口编译器会强制要求明确写出self
            self?.run()
        }
        func run() { print("run") }
        deinit { print("deinit") }
    }
    
    //如果lazy属性是闭包调用的结果,那么不用考虑循环引用的问题(因为闭包调用后,闭包的生命周期就结束了)
    class Person1 {
        var age: Int = 0
        lazy var getAge: Int = {
            self.age
        }()
    }
}

///---------- 逃逸闭包escaping
///逃逸闭包、逃逸闭包,一般都是当做参数传递给函数
///非逃逸闭包:闭包调用发生在函数结束前,闭包调用在函数作用域内
///逃逸闭包:闭包有可能在函数结束后调用,闭包调用逃离了函数的作用域,需要通过@escaping声明
///
func 逃逸闭包escaping() {
    typealias Fn = () -> ()
    //fn是非逃逸闭包
    func test1(_ fn: Fn) { fn() }
 
    //fn是逃逸闭包
    var gFn: Fn?
    func test2(_ fn: @escaping Fn) { gFn = fn }
}

///---------- 局部作用域  do, 类似于oc的{  }
func 局部作用域do() {
    
    do {
        var a = 10
    }
    
    do {
        var a = 2
    }
    
}


/// ------ 指针
func pointer() {
    
    func unsafePointer(a: UnsafePointer<Int>) {
        print(a.pointee)
    }
    
    func unsafeMPointer(a: UnsafeMutablePointer<Int>) {
        a.pointee = 20
    }
    
    var b = 10
    unsafePointer(a: &b)
    unsafeMPointer(a: &b)
    
//    Swift中也有专门的指针类型,这些都被定性为“Unsafe”(不安全的),常见的有以下4种类型:
//     UnsafePointer<Pointee>似 const Pointee *, 不可修改 只能访问
//     UnsafeMutablePointer<Pointee>似 Pointee *  ,可以修改指针指向的内容
//     UnsafeRawPointer似 const void *
//     UnsafeMutableRawPointer 类似 void *
    
}


/// ---- 通配符
///  _ 匹配任何值
///  _? 匹配非nil值  针对可选项来说
///
func 通配符() {
    
    enum Price {
        case a(Int, Int?)
        case b(Double?)
    }
    
    var c = Price.a(10, 10)
    
    switch c {
    case .a(let first, _): // 第二个值nil或者有值都可以
        print(first)
        
    case .b(_?): // 匹配非空
        print("afa")
    default:
        break
    }
    
}



/// ---- 枚举case模式
///
func enumcase() {
    
    var age = 10
    
    // if case等价于只有一个case的switch语句
    if case 0...9 = age {
        print("haha")
    }
    
    switch age {
    case 0...9:
        print("haha")
        
    default: break
    }
    
    
    // guard case模式
    guard case 0..<10 = age else {
        
        return
    }
    

}


/// ------ 注释
func 注释() {
    // FIXME: ADF
    // TODO: HAHD
    // MARK: ASDFAF
    // MARK: - ADFASF
    
}


/// --- oc调用swift
func oc调用swift() {
    
    @objc(NewClass) // 可以使用@objc自定义方法名和类名
    @objcMembers class Caaa: NSObject { // 需要继承自NSObject
        // @objcMembers可以把所有方法和属性都暴露给oc  相当于每个成员前面都增加@objc
        
        @objc func callrun() {
            perform(#selector(run))
            perform(#selector(run(a:)))
        }
        
        
        @objc  func run(a: Int) {
            
            
        }
        
    }
}


/// --- string  substring 字符串处理
func stringt() {
    
    // String可以通过下标、prefix、 suffix等截取子串,子串类型不是String,而是Substring
    var str = "1_2_3_4_5"
    //1_2
    var substr1 = str.prefix(3)
    var substr2 = str.suffix(3)
    var range = str.startIndex..<str.index(str.startIndex, offsetBy: 3)
    var substr3 = str[range]
    
    //最初的String,1_2_3_4_5
    print(substr3.base)
    
    // Substring -> String
    var str2 = String(substr3)
}



/// ------ swift 支持kvc kvo
/// 类需要继承自nsobject
/// 用@objc dynamic来修饰属性
///
///
///
/// ------ swift 关联对象 给拓展增加存储属性
class Prer {
}

extension Prer {
    
    private static var nameKey = true // 使用void?也行   因为都占用一个字节
    
    var name: Int {
        get {
            objc_getAssociatedObject(self, &Self.nameKey) as! Int
        }
        
        set {
            objc_setAssociatedObject(self, &Prer.nameKey, newValue, .OBJC_ASSOCIATION_ASSIGN)
        }
        
    }
    
}

/// ------ 可选项的map和flatMap
/// map和flatMap会先判断 如果是非nil才会继续执行,flatMap区别是会判断已经是可选项了 就不会再次包装   即不会出现??的情况
func optionalMap() {
    var age: Int? = 10
    var b = age.flatMap {
        $0 + 1
    }
    print(b as Any)
}

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容