swift标准库中常见的55个协议。

swift标准库中常见的55个协议。

  • 从协议名结尾字面上我们可以将Protocol分为able、Type、Convertible 三类

从功能角度上来讲的话可以总结为:

  1. 功能添加型(able结尾) "可以做什么?"

举例:

    1. Hashable: 给你的实例添加一个生成哈希值的功能。
    1. Equatable: 给你的实例添加一个判断相等的功能。

2.类型对比型(Type结尾) "这个实例是什么?"

举例:

    1. CollectionType: swift中所有的集合类型都要遵守的一个协议,告诉大家你的实例是一个集合类型的。
  1. 类型转换型(Convertable结尾) "这个实例可以转化成什么?"

举例:

    1. CustomStringConvertible: Print打印输出时比较常用的一个协议,这个协议可以将你的实例需要打印的信息转化成字符串。

我们在以后的日常中可以通过一个协议的命名方式大概推算出这个协议的作用。

Tips: 在项目开发中自定义协议的时候,命名规范就可以依据这三个方面来做协议的命名

内建集合类型

  • Set

基本定义:一组无序元素,且元素不会重复。可以看成是只有key没有value的字典。

项目使用场景:前几天才刚刚用字典的形式保存了用户学习课程的天数信息。现在看来,用set的形式去存储这些信息最为方便。。

集合代数:

和数学上的集合概念类似,set也有交并补的方法

并集 union() 交集 intersection() 补集 subtracting()

使用方法比较简单,这里直接把三个方法写到一起了

    let numSet:Set = [1,2,3,4,5]
    let otherSet:Set = [2,6]

    ///并集
    let unionSet = numSet.union(otherSet)
    print(unionSet) //[5, 6, 2, 3, 1, 4]

    ///交集
    let intersectionSet = numSet.intersection(otherSet)
    print(intersectionSet) //[2]

    ///补集
    let subtractingSet = numSet.subtracting(otherSet)
    print(subtractingSet) //[5, 3, 1, 4]

索引集合和字符集合

Foundation框架中实现了SetAlgebra协议的一共有三类:Set IndexSet CharacterSet

SetAlgebra 可以做什么? 提供了一些基础的数学运算:如 == 、contains(是否包含),交并补、subtract(剔除)等。

IndexSet

表示一个由正整数组成的集合,我们其实可有用Set 达到同等效果。 但IndexSet更加 高效 ,内部使用了 一组范围列表 进行实现。 eg.

存储1到1000
set可能是[1,2,3,4,......,1000]
IndexSet的内部只是真正存储了1,1000  首位和末位两个数字。 它会存储```连续的范围```。So 会更加高效

CharacterSet

是一个高效存储 Unicode 的字符集合。后面讲String的时候会具体讲的~

在闭包中使用集合

我们可以利用Set去给Sequence写一个扩展,来获取序列中所有唯一元素

Range

定义:两个值的区间 ..< 表示不包含上边界的半开范围 ... 表示包含上下边界的闭合范围

    let singleNum = 0..<10//不包括10

    let lowerLetters = Character("a")...Character("z")//包括z

注: 上面创建的两个都是可数范围CountableRange。这种类型类型是可以被迭代的。

  • 数组

数组的可变性:

数组和其他的集合一样,具有值语义,数组赋值时,这个数组的内容会被复制,如下:

swift:
var x = [6,6,6]
var y = x
y.append(6)
y // [6,6,6,6]
x // [6,6,6]

OC:
// NSMutableArray *x = [NSMutableArray arrayWithArray:@[@"1",@"2",@"3"]];
// NSMutableArray *y = x;
// [y addObject:@"4"];
// NSLog(@"x=%@",x); //1,2,3,4
// NSLog(@"y=%@",y); //1,2,3,4

swift中 Array是以struct的形式存在的。并非OC里面的class

实际上swift集合类型都使用的“写时复制”技术。

只有在复制的时候复制出来,其他时候都共享一个内部存储。
  • 数组和可选值

swift中不建议直接使用下标去访问一个数组

通过swift中一些操作去操作一个数组

1.迭代除第1个元素外的数组元素:for x in array.dropFirst()

2.迭代除最后5个元素外的数组元素:for x in array.dropLast(5)

3.(项目中最常用到的一个方法)所有元素和其下标: for (idx, obj) in array.enumerated()

4.寻找指定元素的位置 if let idx = array.index {someMatchingLogic($0) }

5.所有元素进行变形 array.map {someTransformation($0)}

6.筛选符合某个标准的元素 array.filter {someCriteria($0)}

7.两个数组变形合并 flatMap

swift不鼓励你去做索引计算,当在项目中写道array[idx]时,可以思考一下有没有更好的方法去解决。

切片 slice:

获取某个范围中的元素,我们可以使用切片 例如:获取除了第一个元素以外的元素集合

    let fruit = ["??","??","??"]
    let slice = fruit[1..<fruit.endIndex]
    print(slice)//["??", "??"]
    print("\(type(of: slice))")//ArraySlice<String>

得到的类型是ArraySlice 而不是Array,其实切片只是Array的一种表现形式。我们在开发过程中可以把它当做数组来看。 类型转换直接Array(ArraySlice)

集合类型协议 序列

序列: sequence

满足sequence协议只需提供一个返回迭代器(iterator):的makeIterator方法。 集合<-Sequence<-Iterator

迭代器:Iterator

里面只有一个方法next( )

public protocol IteratorProtocol {
    ///关联类型 Element 指定了迭代器产生的值的类型
    ///如 subViews的迭代原生类型就是View 可以不用写,编译器根据next()的返回值自动判断。
    associatedtype Element

    ///你只需要在每次调用的时候返回下一个值,结束时返回nil
    public mutating func next() -> Self.Element?
}

next( )方法是用 mutating 关键字修饰。 几乎所有的迭代器都要求是可变状态,这样才可以管理在序列中的当前位置

注:迭代器是单向结构,只能按照增加的方向前进,不能倒退或者重置。

准守序列(sequence)协议自定义迭代器和自定义集合

第一步: 创建一个迭代器(Iterator)

struct PrefixStrIterator:IteratorProtocol {
    var string: String
    var offset: String.Index
    init(string:String) {
        self.string = string
        offset = string.startIndex
    }
    ///写协议方法
    mutating func next() -> String? {
        guard offset < string.endIndex else { return nil}
        offset = string.index(after: offset)
        return String(string[string.startIndex..<offset])
    }
}

第二步: 创建一个使用这个迭代器的序列(sequence)

///step2.创建一个属于你的集合
struct PrefixSequence: Sequence {
    var string: String

    ///协议方法:返回一个迭代器
    func makeIterator() -> PrefixStrIterator {
        return PrefixStrIterator(string: string)
    }
}

第三步: run

        ///myfirstSquence 我的第一个集合
        for prefixStr in PrefixSequence(string: "Hi~LiaoWorking!") {
            print(prefixStr)
        }
  • 迭代器和值语义

值语义 struct,应该还有其他类型。待补充。 赋值时不存在引用,复制了一份过去了 引用语义 class 赋值时存在引用 注:但AnyIterator这个是引用对象。

  • 基于函数的迭代器和序列

AnyIterator还有一个初始化方法就是直接接受next()函数来当做参数。然后通过引用语义的特性,可以不创建新的类型就写一个斐波那契迭代器

/// 通过引用语义的特性写斐波那契
func fibsIterator() -> AnyIterator<Any> {
    var startNum = (0, 1)
    return AnyIterator{
        let nextNum = startNum.0
            startNum = (startNum.1 , startNum.0 + startNum.1)
        return nextNum
    }
}

无限序列

序列可以是无限的,而集合是有限的。

不稳定序列

Sequence文档明确指出序列并不保证能被多次遍历。 原因是Sequence协议并不关心里面的序列元素会不会销毁。 这就是为什么在集合类型中.first 在序列中并不存在。

序列sequence和迭代器Iterator的关系

迭代器Iterator可以看成即将返回的元素组成的不稳定序列sequence

子序列

Sequence还有一个关联类型 SubSequence

在返回原序列Sequence的切片slice操作中,SubSequence会被当做返回值的子类。

SubSequence 有一些常用方法

prefix
suffix
dropFirst
dropLast
split
  • for 循环 Swift实现了两个范围操作符,闭合操作符和半开操作符。 第一个包括范围中的所有值。 例如,以下包括从0到4的所有整数: 0 ... 4 半开操作符不包括最后一个元素。 以下产生相同的0到4结果: 0 .. <5
  • 值类型、引用类型
struct Tutorial {
  var difficulty: Int = 1
}

var tutorial1 = Tutorial()
var tutorial2 = tutorial1
tutorial2.difficulty = 2
for _ in 0...4 {
  print("Hello!")
}

tutorial1.difficulty是1,而tutorial2.difficulty是2。 Swift中的结构是值类型,它们通过值而不是引用来复制

如果Tutorial是一个类,tutorial1.difficulty和tutorial2.difficulty将是2.在Swift中的类是引用类型。 对tutorial1的属性的任何更改都将反映到tutorial2中,反之亦然。

  • var与let
var view1 = UIView()
view1.alpha = 0.5

let view2 = UIView()
view2.alpha = 0.5

view1是一个变量,可以重新分配给一个新的UIView实例。 通过let声明只能赋值一次,所以下面的代码不编译:

view2 = view1 // Error: view2 is immutable

但是,UIView是一个具有引用语义的类,所以你可以改变view2的属性(这意味着最后一行将编译):

let view2 = UIView() view2.alpha = 0.5 // Yes!

  • 闭包简化步骤

let animals = ["fish", "cat", "chicken", "dog"]
let sortedAnimals = animals.sort { (one: String, two: String) -> Bool in
  return one < two
}

第一个简化与参数有关。类型推理系统可以计算闭包中的参数的类型,所以你可以摆脱它们:

let sortedAnimals = animals.sort { (one, two) -> Bool in return one < two }

返回类型也可以推断,所以放弃它:

let sortedAnimals = animals.sort { (one, two) in return one < two }

$ i表示法可以替换参数名称:

let sortedAnimals = animals.sort { return $0 < $1 }

在单语句闭包中,可以省略return关键字。最后一条语句的返回值成为闭包的返回值:

let sortedAnimals = animals.sort { $0 < $1 }

对于字符串,有一个比较函数定义如下:

func <(lhs: String, rhs: String) -> Bool

这个整洁的小函数使你的代码像下面这样容易:

let sortedAnimals = animals.sort(<)

请注意,此渐进的每个步骤都会编译并输出相同的结果,并且创建了一个字符闭包!

原文地址:https://www.cnblogs.com/liuxiaokun/p/12680035.html

时间: 2024-08-06 08:02:30

swift标准库中常见的55个协议。的相关文章

Swift标准库中的协议_012_swift协议

//: Playground - noun: a place where people can play import UIKit //--Swift标准库中的协议---// //1.实例的比较:判断两个实例值是否相同 let a = 4, b = 4 a == b //(Int类型的比较) //自定义结构体类型,进行是否相等的比较 struct Games { var winCount : Int var loseCount : Int } let g1 = Games(winCount: 2

C零基础视频-28-C标准库中常见的字符串操作函数

目录 字符串的特殊性 字符串比较 获取字符串长度 复制字符串 连接字符串 字符串的特殊性 字符串不是基本数据类型.因此,像操作基本数据类型那样操作,可能会失败: #include <stdio.h> int main(int argc, char* argv[]) { char* szHello = "Hello"; char chAry[] = "Hello"; printf("%s, %s\r\n", szHello, chAry

STL笔记(6)标准库:标准库中的排序算法

STL笔记(6)标准库:标准库中的排序算法 标准库:标准库中的排序算法The Standard Librarian: Sorting in the Standard Library Matthew Austern http://www.cuj.com/experts/1908/austern.htm?topic=experts 用泛型算法进行排序    C++标准24章有一个小节叫“Sorting and related operations”.它包含了很多对已序区间进行的操作,和三个排序用泛型

c/c++标准库中的文件操作总结

1 stdio.h是c标准库中的标准输入输出库 2 在c++中调用的方法 直接调用即可,但是最好在函数名前面加上::,以示区分类的内部函数和c标准库函数. 3 c标准输入输出库的使用 3.1 核心结构体 FILE结构体 打开一个文件的时候获取它,然后就可以不用管它了. 3.2 核心方法 3.2.1 fopen 第一个字符串是文件的路径. 第二个参数是一个字符串,表示操作该文件的模式,"rb"表示read binary,即以二进制的形式来读该文件. 3.2.2 fseek 第一个参数是F

参考C++STL标准库中对了的使用方法

http://www.cppblog.com/zhenglinbo/archive/2012/09/18/191170.html 参考:http://www.cppblog.com/zhenglinbo/archive/2012/09/18/191170.html 当然是使用c++中的STL 的queue啦.下面简要介绍一下使用方法. 1 准备工作 头文件 #include<queue> 2 声明和定义的方法.STL的队列是泛型模板,支持任何内置和构造类型. 比如对于刚才那个牛奶问题.我把状态

C++标准库中next_permutation和pre_permutation实现原理

标准库中next_permutation函数:找当前序列中元素排列的下一个排列,按照字典顺序进行排列.比如说数组排列"123",那么它的下一个排列为"132",并且返回true.如果当前序列没有下一个排列,我们返回false,且把当前排列置为最小的排列,比如说:排列"321",因为该排列已经是最大的排列,所以它没有下一个排列.我们把该排列置为"123",并且返回false. 标准库实现两个重载版本的next_permutati

urllib库中常见的类和方法

from urllib.request import urlopenfrom http.client import HTTPResponse response = urlopen('http://www.baidu.com')# http.client.HTTPResponse对象print(type(response)) with response: print(1,response.status) print(2,response.reason) print(3,response.getur

Swift中如何化简标准库中冗长的类实例初始化代码

可能有些童鞋并不知道,在Swift中缩写点符号对于任何类型的任何static成员都有效. 我们实际写一个例子看一下: import UIKit class CFoo{ static let sharedInstance = CFoo() } struct SFoo{ static let sharedInstance = SFoo() } let foo:CFoo = .sharedInstance let f:SFoo = .sharedInstance 以上代码中可以看到,foo类型为CFo

linux下Qt调用非标准库中的函数调用----------如pthread_create、pthread_cond_***、、

在Linux下Qt中使用POSIX标准的pthread_creaet函数调用创建新线程,使用如下代码后编译通过 extern "C" { #include <pthread.h> } 但是运行后发现并未成功创建新线程,并且无报错!!! (编译链接时有添加:-lpthread) 其中原因本人尚不清楚... 并且pthread_mutex_*** (互斥锁).pthread_cond_*** (条件变量) 等相关函数估计也无效... 后来借鉴网友提供的方法:将C文件创建成函数库