美文网首页
Swift 学习的知识点

Swift 学习的知识点

作者: 荷码人生 | 来源:发表于2019-09-29 14:09 被阅读0次
    1. 大数据: 可以插入 "_" 对数据进行分割 比如:100万 可以写成 1_00_0000

    2. 浮点型: 使用科学计数法: 1.2x10^3--->1.2e3

    3. 可以使用'_'忽略一些数值。

    4. print

    (1)字符串的插值操作。

    print("(x) * (y) = (z)");

    (2)separator 分隔符 默认情况是一个空格 terminator默认情况是回车

    5.注释可嵌套 : ///**/

    1. 求余运算:浮点型也可以。

    7.repeat--while

    1. switch (可以是任意类型的值)

    (1)case "a","A"{} 可以是多种情况并列书写。也可以 判断区间 case 1...90 case (a,b) 元组

    (2)需要罗列出所有的可能情况

    1. break 可以跳出指定循环体:比如:

      使用给for循环命名的语法,执行break跳出的循环体。

        //x^4 - y^2 = 15*x*y;
        FindAnswer:for m in 1...300 {
            for n in 1...300 {
                if m*m*m*m - n*n == 15*n*m {
                    print("m is \(m) , n is \(n)");
                    break FindAnswer;
                }
            }
        }
    
    1. case where 使用,他可以使用在switch,for 语句中,在if中使用在swift3.x 中更换成了“,”.

    2. guard 的使用方法方式,用于边缘值的判断。
      /*
      如果条件不满足,就执行else
      */
      guard 条件 else {
      执行体
      }

    3. 字符串.count,基于unicode,所以每一个表情或者中文,都看作是一位。读取更加精准。

    4. 在Swift3.0 advancedBy使用以下代替:

    let index = testName.index(testName.startIndex, offsetBy: 1)

    14.删除t冗余字符。

    let str = CharacterSet(charactersIn: "_ -"); //这里是删除多余的 "_-" 这两种符号。

    tmpStr.trimmingCharacters(in: str);

    1. 可选型:强制解包(!),if let , "??"

    解包: (1)if let 变量1=要解包的变量,let 变量2=要解包的变量,进一步条件限制比如:变量1=="404"

    (2) 可选变量??"数值" <====>可选变量==nil?"数值":可选变量!;

    (3)OPtional Chaining:尝试解包(?)比如: errorMessage?.uppercased();等价于 if let 解包。

    (4)隐式可选型:let ageInt :String! = nil;可以不付初值,但是在使用的时候,一定要保证有值。

    1. indexOf ===> firstIndex(of: 3)或者 lastIndex(of:);//元素的位置index

    2. 忽略外部参数名,使用 "_"

    3. 参数传递:inout 应该写在参数类型的前面:比如:func swapOut ( _ num1:inout Int , _ num2:inout Int )

    4. 枚举类型的不同,枚举可以有数值型,关联类型,以及枚举可以遵守协议。

    数值型: enum 枚举名称:数值类型 { case .枚举值类型 = 数值(RawValue)}

    关联类型: enum 枚举类型 { case .枚举值(参数1,参数2,...)}; 如:调用的时两种类型

    (1)case let .枚举值(参数1,参数2,...)

    (2)case .枚举值(let 参数1,var 参数2,...) let var 可同时存在。

    1. 可选型也是一个枚举类型。

    21.递归枚举类型 indirect enum 枚举类型。

    22.类和其他的结构体、枚举类型的不同点:

    (1)它内部的成员变量必须带有初始值,除了可选类型以外。

    23.结构体或者枚举中声明方法时,需要在 func 前面 加上 mutating,

    24.M_PI ----更换成了----> Double.pi

    1. "===" 判断 两个引用类型 是否指向了同一片内存区域。

    26.延迟属性:lazy var 属性名称 : 属性类型 = { ... return 返回值}()

    27.类方法直属于类,而不是类的实例变量。 需要在func 前面加上 static ,
    同理,类属性也是,在var \ let 前面加上 static.

    28.属性观察器:
    注意:didSet willSet 在初始化的时候不会被调用,或者第一次 赋值的时候也不调用。
    使用场景:再给一个变量 赋值前后,分别触发 wilSet didSet 并且 会分别 : 返回一个数值:newValue \ oldValue;

    29.private 原本设计需要分文件处理在可以使得 private 私有属性生效,现在不需要了,仅仅是,写上 private 关键字 ,就可以生效。

    30.final 表示 该类不能够拥有子类,也就是说,别的类不能即成该类。

    31.当父类中声明了某一个属性后,子类也想声明该属性,则可以在声明时,使用 override 来修饰。用来覆盖父类中的方法或者属性。如果某一个父类中的属性或者方法不想被子类覆盖,可以使用final 进行修饰。
    这就是重载。

    1. swift的两段式构造原则: 子类中的特殊属性,优先初始化,然后在使用父类的初始化方法,再去初始化共有属性,在子类函数中,使用到的父类的属性。如果想要使用某些属性的时,需要在super.init 方法之后使用self.属性进行调用,否则就会报错。
      (1)第一步:先初始化本类属性
      (2)第二步:在使用父类的初始化函数(super.init), 初始化父类属性
      (3)第三步:最后进行相关逻辑的操作,对相关属性的操作。

    33.便利构造器: convenience. ---> 就是构造函数中,还调用另一个构造函数,此时外层的构造函数需要使用 convenience 修饰 表明是便利构造器

    特点:
    (1)一个构造函数,一定调用的它本身的另一个构造函数(指定的构造函数)

    (2)便利构造函数 能够 调用 self. 某一个函数 ,而 普通的构造函数,才能够调用 super.

    34.构造函数是以 init 开头的

    1. 父类构造函数的继承规则

    (1)如果子类实现了父类的所有的指定构造函数(),则子类会自动的继承父类的所有的便利构造函数()。
    (2)如果子类没有实现任何父类的指定构造函数(),则子类会自动继承父类的所有的指定构造函数以及便利构造函数()。

    1. 使用 required 表示必须被子类所实现的函数

    特点:
    (1)required 修饰的方法 在子类中,不需要使用 override 而是 使用 required 修饰。

    1. 文档注释

    pragma mark --------------------文档注释--------------------

    1. swift 下标问题 Subscript 函数设置 角标问题: 参数可以任意类型的,形式:

    ///根据下标 获取 相应的数值 --> 设置成 数字角标 0,1,2

        subscript(index:Int)->Double?{
            
            get{
                switch index {
                case 0: return x;
                case 1: return h;
                case 2: return z;
                default:
                    return nil;
                }
            }
            set{
                
                guard let newValue = newValue else { return }
                
                switch index {
                case 0: x = newValue;
                case 1: h = newValue;
                case 2: z = newValue;
                default:
                    return ;
                }
            }
            
        }
    
    //调用 表达
    v[1] = 200;
    v[1]
    
    1. assert 断言 , 错误 提示

    2. 运算符重载 语法 --> func 方法名() { return }

    比如:运算符 重载

    func + (left: Vector3 , right: Vector3) -> Vector3{
        return Vector3(x: left.x + right.x, h: left.h + right.h, z: left.z + right.z);
    }
    
    prefix 前缀 修饰符 postfix 后缀运算符
    
    比如:
    prefix func - (vector:Vector3)->Vector3{
        return Vector3(x:-vector.x,h:-vector.h,z:-vector.z);
    }
    
    1. 自定义运算符 :

    (1) 声明运算符

    <1> 单目运算符声明 使用 operator 修饰

    向前结合: prefix operator 自定义运算符; 向后结合: postfix operator 自定义运算符;

    <2> 双目运算符声明 使用 infix operator 修饰

    向前结合: prefix operator 自定义运算符; 向后结合: postfix operator 自定义运算符;

    选择的字符范围:/ = - + ! * % < > & | ^ ~ 或者 unicode 码

    <3> 定义运算符的优先等级以及向左或右结合属性

    swift 3.0 之前 operator 自定义的运算符 { associativity left precedence 100} left 向左结合 100 优先等级数

    swift 3.0 之后 使用 precedencegroup 创建一个 优先等级组 :

    precedencegroup 优先级组名称 {
    higherThan: 较低优先级组的名称
    lowerThan: 较高优先级组的名称
    associativity: 结合性
    assignment: 赋值性
    }

    比如:

    precedencegroup AddPrecedence {
        associativity : left
        higherThan:MultiplicationPrecedence  --> 来源于文档中优先等级表。
    }
    infix operator ** : AddPrecedence
    func **(x: Double, p:Double) -> Double{
        return pow(x,p)
    }
    

    <4> 优先级分类 : AdditionPrecedence(+ 、-), MultiplicationPrecedence(* 、 /)

    1. extension 可以为类或结构体 添加方法、属性(不能是存储类型的属性,需要是,计算属性)、添加的必须是便利的构造函数,不能是指定的构造函数 语法: extension 要扩展的类 {}

    计算类型的属性:语法: 类型 属性名称 {get{return 数据} set{设置数据的值}} 、也可以扩展下标 :使用subscriptions , 也可以给系统的标准库添加扩展。

    1. Nested Type 嵌套类型 : 比如为某一个类 定义自己特有的枚举值,而 这个枚举 类型 就是一个嵌套类型 。

    形如:Rectangle.VertText.LeftBottom,String.Index

    1. 创建区间范围 : 从几到几 步长 多少 比如: 表示 2 ~ 20 步长 为 2 的区间

    闭区间 : stride(from: 2, through: 20, by: 2)
    开区间 : stride(from: 2, to: 20, by: 2)

    之前:

    开区间:2.stride(to 20, by: 2);
    闭区间:2.stride(through 20, by: 2);

    1. 给 UIColor 添加扩展 支持 16 进制 表示 色值

    2. 泛型函数 语法 : func 函数名 <T> (参数名:T){} 其中 T 可以是任意命名 也就是说 func 函数名 <Ting> (参数名:Ting){} 也可以。

      泛型类型 语法 : 多个 泛型 时, 需要使用 ',' 隔开 比如: <T1,T2,...>

      两个泛型 的 结构体()

        struct Pair<T1,T2>{
            var a:T1;
            var b:T2;
        }
        let pair = Pair<Int,String>(a:1,b:"黑猫警长");
    
    1. 协议protocol 中 只写方法的声明 属性需要 指定 它的访问权限 比如是 只读,可读可写 语法 :名称 : 类型 { get 或者 set 或者 get set }

      也可以进行声明 构造函数 当声明构造函数后,应该在遵循该协议的类中,将该构造函数 设定成 必须实现 的函数 ,也就是 使用 required 修饰 构造函数。

    (1) 让类遵循协议: var 类型 : 协议类型

    (2) associatedtype 相当于类中的别名,在协议中使用该修饰关键字 来声明别名,类中 使用 typealias 别名 = 原始名称

    (3) 场景描述:associatedtype 当有多个的类遵守同一个协议 ,并且 只有属性的类型不同时,也就是为不同类型的不同类型,设置统一的别名。 我们 可以通过 associatedtype 为 协议 定义 关联类型,让其在类的实现中,为该类型 关联不同的类型。
    var weigth :WeightType{get};

    代码如下: 在协议中, associatedtype 关联类型_A 在 类的实现中, typealias 关联类型_A = 要设定的类型; 缺一不可。

    protocol WeightCaculable{
        associatedtype WeightType;  //同一个别名 WeightType
    }
    
    class iPhone7 :WeightCaculable{
        typealias WeightType = Double; //关联的 Double 类型
        var weigth: WeightType{
            return 0.01124;
        }
    }
    
    class Ship :WeightCaculable{
        typealias WeightType = Int; //关联的 Int 类型 
        var weigth: WeightType;
        init(weigth:WeightType) {
            self.weigth = weigth;
        }
    }
    
    1. 协议 和 类 的混合使用 父类 要放在 协议的前面 也就是 语法: class 类名 : 父类名称 , 协议名称

    2. swift 标准库中的常用的协议:

    (1)Equatable --> 让类或者结构体 遵循此协议后,可以对任意类型的进行 == != 之间的比较。

    (2)Comparable --> 让类或者结构体 遵循此协议后,需要实现协议中的 "<" 方法重载 可以对任意类型的进行 == != 之间的比较,

    同时,可以在重载实现 < > >= <= 中任意一个就可以使用其他的三种,进行比较。

    同时,可以调用的该类型的数组,进行sort排序:比如:var JiLuS = [JiLuA,JiLuB,JiLuC,JiLuD]; JiLuS.sort();

    //(3)BooleanType --改成了--> ExpressibleByBooleanLiteral ,告诉编译器,某一个类型,当成是Bool 类型

    50.重点类型() 面向协议编程 : 对自定义以及系统类协议 也可以进行扩展。

    场景描述: 一个协议 被多个类遵守,并且 协议中的方法,在不同类型中有着相同的实现逻辑,这时,我们可以通过对协议进行扩展,将不同类中的协议方法或者属性,在协议的扩展中 添加默认() 实现。

    (1)特点:

    (1)在扩展的实现,是 默认实现 ,我们可以在 不同类型,更改相应的属性值以及方法实现,来覆盖 扩展中的实现。

    (2)协议聚合 ---> 让类的对象 遵从多个协议 使用 & 。 swift2 : protocol <Prizable , CustomStringConvertible> ---> swift3: Prizable & CustomStringConvertible

    比如 : func award(one: Prizable & CustomStringConvertible)  相应的类 需要遵从相同的协议。
    

    (3) 泛型的约束 :就是给泛型添加一定的约束条件 比如说: 让其遵守某个协议:<T:协议名称 & 协议名称>

    51.可选的协议方法:

    (1)需要在 protocol 前面添加 @objc

    (2)在 可选的协议方法或属性前面 添加 @objc optional

    (3)要求的 遵循该 协议的对象 必须是 Object--类 或者 继承于 Object--类;

    (4)被修饰的方法变成了 可选的类型 所以在使用的时候要对其进行解包的操作:比如:delegate.turnEnd?() 或者使用 if let 的方法解包

    1. 断言的几种方式:

    (1)assert()

    (2)assertionFailure(<#T##message: String##String#>)

    (3)assertionFailure()

    (4)fatalError()

    (5)fatalError(<#T##message: String##String#>)

    (6)do { try } catch {} 使用规则:

    <1> 对于函数声明时,声明成可抛异常的函数 : func 函数名称 () throws ->  返回值 或者 func 函数名称 () throws
    
    <2> 函数实现中 使用 throw 抛出异常  throw 但是 该异常 要是Error类型 或者 继承于 Error的类型。比如:
    
    enum ErrorType:Error , CustomStringConvertible {
        case NoEnoughMoneyError(Int)
        case NoGoodsError
        case UnKnowError
        
        var description: String{
            switch self {
            case .NoEnoughMoneyError(let price):
                return ("Not Enough Money. " + String(price) + " :Yuan needed");
            case .NoGoodsError :
                return ("No Goods");
            case .UnKnowError :
                return ("Unknow Error");
            }
        }
    }
    
    <3> 调用时,不能按照普通函数那样调用,要使用try进行修饰,try 表示尝试 忽略函数的异常, try? ---> 尝试 忽略; try! --> 表示 在确认该函数 没有异常情况的条件下,使用。
    <4> do catch 就是针对 <3> 中的调用结果的进一步处理。
    
        do {
    
            myMoney = try vendingMahine.vend(itemName: "Mineral Juice", money: myMoney);
            print(myMoney,"Yuan left");
    
        } catch let error as VendingMachine.ErrorType { //类似强制解包处理,类型转换 ,转换成功,就进行打印错误信息。
        
            print(error);
    
        } catch {
    
            print("Error occured during vending."); // 所有情况都为匹配到该错误时,才会的走该内容!
    
         }
    
         对于单个的错误情况,可以使用 if - let 的方式进行处理
    
        if let leftMoney = try? vendingMahine.vend(itemName: "Mineral Juice", money: myMoney){
            //未发生异常:
            print(leftMoney);
        }else{
            //Error Handling 异常处理
        }
    

    (7) 控制转移 defer 就是在一个作用于 结束的时候,调用,同时,如果一个作用域中,有多个defer的时候,先编译的后执行。 通常使用在错误提醒中。

    1. 内存管理

    (1)weak 使用的方法:所修饰的量应该是 var 类型可变的 二是 可选类型。

    (2)unowned 使用的方法:只能用来修饰类,不能修饰函数, 主要用来解决 weak 不能对 常量 不可选类型的 弱引用。 所修饰的量 可以修饰 可选类型. 同时,不能 对 函数进行修饰。

    (3)闭包中的强引用:可以使用隐式可选型,就是说,在初始化的时候,有一段时间可以为空,在后续的过程中,会给该变量赋初值。语法: var 名称:类型 !

    (4)Closure 的 强引用循环问题。 使用闭包列表 语法 [unowned self] 使用 unowned 或者 weak 将 self 变成 弱引用。

    (5)self 将 self 存储到 self 中 需要使用 反单引号 引用 即 self = self .

    /***********************闭包中 强引用 的 解决方案*********************************/
    
    /*
     unowned 的 写法
     
     temperatureChange = { [unowned  self] newTemprature in
     
           if abs(newTemprature - self.temperature) >= 10 {
     
               print("It's not healthy to do it!");
     
           }else{
     
               self.temperature = newTemprature;
     
               print("New temperate \(self.temperature) is set!");
           }
      }
     
     */
    
    /* weak 的 写法 */
    temperatureChange = { [weak  self] newTemprature in
        
        if let `self` = self {
            
            if abs(newTemprature - self.temperature) >= 10 {
                
                print("It's not healthy to do it!");
                
            }else{
                
                self.temperature = newTemprature;
                
                print("New temperate \(self.temperature) is set!");
                
            }
            
        }
        
    }
    
    1. weak && unowned 只能用在修饰类,不能修饰函数()

    2. 类型检查 使用 is 判断是否为同一类型,类型强制转换 使用 as 关键字: as? 尝试转换 , as! 强制转换。

    3. NSObject/AnyObject/Any

    相关文章

      网友评论

          本文标题:Swift 学习的知识点

          本文链接:https://www.haomeiwen.com/subject/tyaxpctx.html