美文网首页
Swift 学习

Swift 学习

作者: 荷码人生 | 来源:发表于2020-04-25 21:11 被阅读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 = 15xy;
    FindAnswer:for m in 1...300 {
    for n in 1...300 {
    if mmmm - nn == 15nm {
    print("m is (m) , n is (n)");
    break FindAnswer;
    }
    }
    }

  2. case where 使用,他可以使用在switch,for 语句中,在if中使用在swift3.x 中更换成了“,”.

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

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

  5. 在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:"黑猫警长");

  3. 协议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/yhnlactx.html