iOS 的 AsyncSequence 和 AsyncStream 教程

在本教程中,您将:

  • 比较同步和异步读取非常大的文件时的速度和内存运用情况。
  • 创立和运用自界说AsyncSequence.
  • 创立和运用根据拉的和根据推的AsyncStreams。

留意:这是一个中级教程。你应该了解“传统”并发——GCD(Grand Central Dispatch)和URLSession——以及基本的 Sw面试问题ift 并发线程池的七个参数特性,比方SwiftUI和SwiftUI 中的async/await和结构化并发中呈现的那些特性。

Data Files

ActorSearch的目的是帮助数据结构严蔚敏您经过从IMDb 数据集中查找name.basics.tsv.gz数据集来处理问询艺人名字的难题。该文件包括一个标题行来描绘每个称号的信息:

  • nconst(字符串)– 名字/人员的字母数字唯一标识符
  • primaryNam面试e(字符串)– 最常记入此人的名字
  • birthYear– YYYY 格局
  • deathYear– 如果适用,采用 YYYY 格局,否则为 ‘N’
  • primaryProfession(字符串数组)– 人的前三个职业
  • knownForTios模拟器itles(tconsts 数组)– 此人的闻名头衔

为了减少对您的网络数据结构c语言版第二版课后答案的需求并使其易于逐行阅读,发动项目已经包括data.tsv:这是解压缩的name.basicsios应用商店.tsv.iOSgz,已删去标题行。它是一个制表符分隔值 (TSV) 文件,格局为 UTF-8 字符集。

线程数越多越好吗不要试图经过在项目导航器中挑选它ios下载来检查data.tsv。翻开需求很长时刻,Xcode 变得无呼应http协议

在本教程中,您将探究将文件线程和进程的区别是什么内容读入值数组的不同办法Actordata.tsv包括 11,445,101 行而且需求很长时刻才干读入,因而您将仅运用它来比较内存运用情况。您将在较小的文件data-100.tsvdata-1000.tsv上测验大部分代码,它们别离包括前 100 和 1000 行。

留意:这些文件仅在发动项目中。如果要构建和运转该项目,请将它们复制到终究项目中。

Models

翻开面试问题大全及答案大全ActorAPI.swift面试自我介绍3分钟通用Actor是一个超级简略的结构,只要两个属性:idname

在此文件中,您将完结读取数据文件的不同办法。ActorAPI初始化程序承受一ios14.4.1更新了什么个参数fiios是什么意思lename并创立面试问题大全及答案大全.url它是一个ObservableObject发布Actor数组的。

starter 包括一个基本的同步办法:

func  readSync () throws {
   let start =  Date .now
   let contents =  try  String (contentsOf: url)
   var counter =  0 
  contents.enumerateLines { _ , _  in 
    counter +=  1
  }
  print ( " (counter) lines" )
   print ( "持续时刻: (Date.now.timeIntervalSince(start)) " )
}

String这只是从contentsOf文件的中创立一个url,然后核算行数并打印该数字以及花费ios是什么意思了多长时刻。

enum数据结构教程第5版李春葆答案erateLines(invoking:)是从St线程池的七个参数ringProtocol办法桥接的NSString办法enumerateLines(_:)

View

翻开ContentView.swiftContentView创立一个ActorAPI具有特定文件名的目标并显现该Actor数组,并带有一个查面试技巧和注意事项找字段。

searchable(https和http的区别text:)首要,http://192.168.1.1登录在闭包下面增加这个视图修饰符:

.onAppear {
  做{
    测验model.readSync()
  }捕捉 让过错 {
    打印(error.localizedDescription)
  }
}

readSync()在视图呈现时调用,捕获并打印任何r数据结构严蔚敏eadSync()抛出的过错。

现在,检查运转此应用程序时的内存运用情况。翻开调试导航器,然后构建并运转。当外表呈现时,挑选内存并观看:

iOS 的 AsyncSequence 和 AsyncStream 教程

在我的 Mac 上,读取这个 685MB 的文件需求 8.9 秒,并产生 1.9GB 的内存运用峰值。

接下来,您将测验一种 Swift 并发办法来读取文件。您将遍历一个异步序列

AsyncSequence

Sequence一直在运用该协议:数组、字典、iOS字符串、范围和Data都是序列线程和进程的区别是什么。它们带有许多便利的办法,例面试next()contains()filter()。对序列进行循环运用其内线程池置的迭代器,并在迭代器回来时停止nil

AsyncSequence协议的作业原理类似于Sequence,但异步序列异步回来每个元素(呃!)。跟着更多元素跟着时刻的推移变得可用,您能够异步迭代其元素。

  • await每个元面试技巧和话术大全素,所以序列能够在获取或核算下一个值时暂停。
  • 序列生成元素的速度或许比您的代码运https和http的区别用它们的速度更快:一种AsyncStream缓冲其值,因而您的应用程序能够在需求时读取它们。

AsyncSequence为异步处理数据调集供ios系统给言语支持。有内置的AsyncSequences likeNotificationCenter.NotificationsURLSession.bytes(from:delegate:)以及它的子序列linescha数据结构严蔚敏ractersAsyncSequence您能够运用和AsyncIteratorProtocol或运用创立自己的自界说异步序列AsyncStream

留意:Apple 的As面试yncSequence 文档页面列出了一切内置的异步序列。

Reading a File Asynchronously

为了直接从 URL 处理数据集,URL基础面试问题大全及答案大全类供给了自己的AsyncSequencein完结URL.lines。这关于直接从 URL 创立异步行序列很有http://www.baidu.com用。

翻开ActorAPI.swift并将这个办法增加到ActorAPI

// 异步读取
func  readAsync () async  throws {
   let start =  Date .now
  var counter =  0 
  for  try  await  _  in url.lines {
    计数器+=  1
  }
  打印(“ (计数器)行”)
  print ( "持续时刻:(Date.now.timeIntervalSince(start)) " )
}

您在异步序列上异步迭代,边走边核算行数。

这里有一些 Swift 并发魔法:url.lines有自己的异步迭代器,for循环调用它的next()办法,直到序列线程经过回来nil.

留意URLSession有一个获取异步字节序列和常用URLResponse目标的办法。您能够检查呼应状况代码,然后调用lines此字节序列将其数据结构c语言版严蔚敏第二版答案数据结构c语言版换为异步行序列。

let (stream, response) =  try  await  URLSession .shared.bytes(from: url)
 guard (response as?  HTTPURLResponse ) ? .statusCode ==  200  else {
   throw  "服务器呼应过错。"
}
for  try  await line in stream.lines { 
   // ...
}

Calling anios越狱 Asynchronous Method From a View

要从 SwiftUI 视图调用异步办法,请运用task(priority:_:线程数是什么)视图修饰iOS符。

ContentView中,注释掉onAppear面试技巧和话术大全(perform:)闭包并增加以下代码:

.task {
  做{
    测验 等候model.readAsync()
  }捕捉 让过错 {
    打印(error.localizedDescription)
  }
}

翻开调试导航器,然后构建并运转。当外表呈现时,挑数据结构与算法内存并观看:

iOS 的 AsyncSequence 和 AsyncStream 教程

在我的 Mac 上,读取文件需求 3.7 秒,内存运用量稳定在 68面试问题大全及答案大全MB。不同很大!

在循环的每次迭代ios越狱fo面试自我介绍rlines序列都会从 URL 中读取更http://192.168.1.1登录多数据。由于这是分块产生的,所以内存运用量坚持不变。

Getting数据结构知识点总结 Actors

是时分填充actors数组httpwatch了,这样应用就能ios下载够显现一些东西了。

将此办法增加到Actor数据结构教程第5版李春葆答案API

func  getActors () async  throws {
   for  try  await line in url.lines {
     let name = line.components(separatedBy: " t " )[ 1 ]
     await  MainActor .run {
      actor.append(艺人(名字: 名字))
    }
  }
}

您无需核算行数,而是从每一行中提取称号数据结构有哪些,运用它来创立一个Actor实例,然后将其附加到actors.由于acios是苹果还是安卓tors是 SwiftUI数据结构 视图运用的已发布属性,所数据结构c语言版严蔚敏第二版答案以修改它必须在主队列上进行。

现在,在ContentViewtask包中,替换try await model.readAsync()为:

测验 等候model.getActors()

此外,model运用较小的数据文件之一更新声明,data-面试问题100.tsvdata-1000.tsv

@StateObject  private  var model =  ActorAPI (filename: "data-100" )

构建并运转。

iOS 的 AsyncSequence 和 AsyncStream 教程

该列表很快呈现。下拉屏幕以检查查找字段并测验一些查找。运用模拟器的软件键盘 (Command-K) 能够更轻松地撤销查找词的首字母大写。

Custom AsyncSequence

到目前为止,您一直在运用 URL API 中内置的异步序列。您还能够创立自己的自界说AsyncSequence,例如AsyncSequenceActor

要界说一个AsyncSequenceover 数据集,您需数据结构c语言版求遵从其协议并构造一个AsyncIterahttp 500tios16or回来调集中httpwatch数据序列的下一个元素的 an。

AsyncSequence o数据结构有哪些f Actors

你需求两个结构——一个符合,AsyncSequence另一个符合AsyncIteratorProtocol.

HTTPActorAPI.swift的 outsideActorAPI中,增加这些最小结构:

struct  ActorSequence : AsyncSequence {
   // 1 
  typealias  Element  =  Actor 
  typealias  AsyncIterator  =  ActorIterator
  // 2 
  func  makeAsyncIterator () -> ActorIterator {
     return  ActorIterator ()
  }
}
struct  ActorIterator : AsyncIteratorProtocol {
   // 3 
  mutating  func  next () -> Actor ? {
    回来 零
  }
}

留意:如果您乐意,能够在结构内部界说迭代器结构AsyncSequence

以下是此代码的每个部分的作用:

  1. AsyncSeqhttps和http的区别uence生成一个Element序列。在这种情况下,ActorSeqios系统uenceActors 的序列。AsyncSequence期望一个AsyncIterator,你typealias线程和进程的区别是什么ActorIterator
  2. AsyncSequence协议需求一个makeAsyncIterator()办法,该办法回来一个ActorIterator.此办法不能包括任何异步或抛出代码。像这样的代码进入ActorIterator.
  3. Ashttp协议yncIteratorProtocol协议需求一个面试自我介绍一分钟next()办法来回来下一个序列元素,或许nil, 来表示序列的完毕。

现在,要填写结构,请将这些行增加到ActorSequ面试技巧ence

让文件名:字符串
让网址:网址
init(文件名:字符串){
   self .filename =文件名
  self .url =  Bundle .main.url(forResource:文件名,withExtension:“tsv”)!
}

该序列需求文件名的参数和存储文件 URL 的属性。您在初始化程序中设置这些。

makeAsyncIterator()中,您将遍历uHTTPrl.lines

将这些行增加到ActorIterator

让url: URL
var迭代器: AsyncLineSequence < URL . 异步字节>。异步迭代器
初始化(网址:网址){
   self .url = url
  迭代器= url.lines.makeAsyncIterator()
}

您显式地获取了异步迭代器,url.lines因而next()能够调用迭代器https和http的区别next()办法。

现在,修正ActorItios14.4.1更新了什么erator()调用makeAsyncios模拟器Iterator()

回来 ActorIterator (url: url)

接下来,替换next()为以下内容:

变异 func  next () async -> Actor?{
   do {
     if  let line =  try  await iterator.next(), ! line.isEmpty {
       let name = line.components(separatedBy: " t " )[ 1 ]
       return  Actor (name: name)
    }
  }捕捉 让过错 {
    打印(error.localizedDescription)
  }
  回来 零
}

您将asyn面试自我介绍简单大方c关键字增加到签名中,由于此办法运用异步序列迭代器。只是为了改动,你在这里处理http://192.168.1.1登录过错而不是数据结构c语言版抛出它们。

现在线程数是什么,在 中ActorAPI,修改getActors()以运用此自界说AsyncSequence

func  getActors () async {
   for  await  actor  in  ActorSequence ( filename : filename ) {
     await  MainActor .run {
      艺人.追加(艺人)
    }
  }
}

处理任何过错的next()办法,因而不会抛出,而且您不必处理.ActorIhttp代理terator``getActors()``try await``ActorSequ面试自我介绍3分钟通用ence

您迭代Actor面试自我介绍3分钟通用Sequence(filename:),它回来Actor值供您附加到actors.

终究,在 中ContentView,将task闭包替换为:

.task {
  等候模型.getActors()
}

代码要简略得多,现在getActors()不会抛出。

构建并运转。

iOS 的 AsyncSequence 和 AsyncStream 教程

一切都相同。

AsyncStream

自界说异步序列的唯一缺点是需求创立和命名结构,这会增加到应用程序的命名空间中。AsyncStream让您“即时”创立异步序列。

typealias您只需运用元素类型初始化您的,而不是运用 a ,AsyncStr面试eam然后在其尾随闭包中创立序列。

其实有两种AsyncStream。一个有unfolding闭包。像AsyncIterator,它供给next元素。它只在使命要求一个值时创立一系列值,一次一个。将其视为根据拉动或需求驱动的

AsyncStream: Pullhttpclient-based

首要,您将创立根据拉取AsyncStreamActorAsyncSequence.

将此办法增加到ActorAPI

// AsyncStream: 根据拉取的
func  pullActors () async {
   // 1 
  var iterator = url.lines.makeAsyncIterator()
  // 2 
  let actorStream =  AsyncStream < Actor > {
     // 3 
    do {
       if  let line =  try  await iterator.next(), ! line.isEmpty {
         let name = line.components(separatedBy: " t " )[ 1 ]
         return  Actor (name: name)
      }
    }捕捉 让过错 {
      打印(error.localizedDescription)
    }
    回来 零
  }
  // 4 
  for  await  actor  in  actorStream {
     await  MainActor .run {
      艺人.追加(艺人)
    }
  }
}

这是您运用此代码所做的作业:

  1. 您依然创立一个AsyncIteratorforurl.lines
  2. 然后你创立一个AsyncStream,指定Element类型Actor
  3. next()并将办法的内容复制ActorIterator到闭包中。
  4. 现在数据结构知识点总结actorStream是一个异步序列,与 完全相同ActorSequence,因而您能够像在getActors().

Contios14.4.1更新了什么entView中,调用pullActors()而不是getActors()

等候模型.pullActors()

构建并运转,然后检查它是否依然能够正常作业。

iOS 的 AsyncSequence 和 AsyncStream 教程

AsyncStream: Push-based

另一种AsyncStreambuild闭包。它创立一系列值并缓冲它们,直到有人要求它们为止。将其视为根据推送或供给驱动的iOS

将此办法增加到ActorA数据结构PI

// AsyncStream: 根据推送的
func  pushActors () async {
   // 1 
  let actorStream =  AsyncStream < Actor > { continuation in 
    // 2 
    Task {
       for  try  await line in url.lines {
         let name = line.components(separatedBy: " t " )[ 1 ]
         // 3 
        continuation.yield( Actor (name: name))
      }
      // 4
      连续.finish()
    }
  }
  关于 actorStream中的等候 艺人 {
     await MainActor .run {  
      艺人.追加(艺人)
    }
  }
}

这是您在此办法中所做的作业:

  1. ios15不需求创立迭代器。相反,您会得到一个continuation.
  2. build闭包不是异步的数据结构严蔚敏,因而您必须在Task异步序列上创立一个 to 循环url.lines
  3. 关于每数据结构知识点总结ios模拟器行,您调用连续的yield(_:)办法线程池的七个参数Actor值推入缓冲区。
  4. 当你抵达结尾时url.lines,你调用连续的finish()办法。

留意:由于build闭包不是异步的,所以你能够运用这个版本AsyncStream来与非异步http协议 API 交互,比方fread(_:_:_:_:HTTP).

ContentView中,调用pushActors()而不是pullActors()

等候模型.pushActors()

构建并运转并承认它能够作业。

Continuations

自 Apple 首次推出 Grand Central Dispatch 以http://192.168.1.1登录来,它就向开发人员供给了怎么避免线程爆破风险的建议。

当线程多于 CPU 时,调度程序在线程之间分时同享 CPU线程数越多越好吗,履行上下文切换以换出正在运转的线程并换入堵塞的线程。每个线程都有一个堆栈和相关的内核数据结构,因而上下文切换需求时刻。

当应用程序创立大量线程时——例如,当它下载成百上千张图画线程撕裂者时——CPU面试问题 会花费太多时刻进行上下文切换,而没有足够的时刻做有用的作业。

在 Swift 并发体系中,线程的数量最多只要 CPU 的数量。

线程池面试题线程在 Swift 并发下履行作业时,体系运用一个HTTP称为continuation的轻量级目标来盯梢在何处康复暂停使命的作业。在使命连续之间切换比履行线程ios应用商店上下文切换更便宜、更有效。

iOS 的 AsyncSequence 和 AsyncStream 教程

留意:这个带有连续的线程图画来自 WWDC21 Session 10254。

当使命挂起时,它会持续捕获其状况。它的线程能够康复另一个使命的ios越狱履行,从它挂起时创立的连续中从头创立它的状况。这样做的代价是函数调用。

async当您线程池运用函数时,这一线程数是什么切都产生在幕后。

可是您也能够持续手动康复履行。的缓冲形式AsyncStream运用连续来yiios15eld流式传输元素。

不同的连续 API 可帮助您重用现有代码,如完结处理程序和托付办法。要了解怎么操作,请检查Swhttp 500ift 中的现代并发,第 5 章,“中心 async/await 和 CheckedContinuation”。

Push or Pull?数据结构

Push-based 就像工厂制造衣服并将它们存储在仓库或商店中,直到有人购买它们。Pull-bas线程是什么意思ed 就像从裁缝那里订购衣服。

在根据拉取和根据推送之间进行挑选时,请考虑与您的用例的潜在不匹配:

  • 根据拉的(展开)AsyncStream:您的代码需求比异步序列更快的值。
  • 根据推送(缓冲)AsyncStream:异步序列生成元数据结构c语言版第二版课后答案素的速度比您的代码读取它们的速度更快,或许以不规则或不行预测的时刻间隔生成元素,例如来自后台监视器的更新——告诉、位置、自界说监视httpwatch

下载大文件时,根据拉取的办法AsyncStream(仅在代码恳求时才下载更多字节)数据结构与算法能够让您更好地控制内存和网ios15络运用。根据推送(AsyncStream不暂停下载整个ios是苹果还是安卓文件)或许会导致内存或网络运用量激增。

要了解这两种 . 的面试自我介绍一分钟另一个差异Async数据结构教程第5版李春葆答案Stream,请检查如果您的代码不运用actorStream.

在和ActorAPI中注httpwatch释掉这段代码:pullAhttp 404ctors()``pushActors()

关于 actorStream中的等候 艺人 {
   await MainActor .run {  
    艺人.追加(艺人)
  }
}

接下来,在这两种办法中的这一行放置断点:

let name = line.components(separatedBy: " t " )[ 1 ]

编辑两个断点以记载iOS断点称号和命中计数,然后线程的几种状态持续:

iOS 的 AsyncSequence 和 AsyncStream 教程
现在,在 中ContentView,设置task为调用p面试自我介绍简单大方ullActors()

.task {
  等候模型.pullActors()
}

构建并运转,然后翻开调试控制台:

iOS 的 AsyncSequence 和 AsyncStream 教程

actorStream不会呈现日志消息,由于当您的代码不要求其元ios是什么意思素时,根据拉取的代码不会运转。除非您要求下一个元素,否则它不会从文件中读取。

现在,切换task到调用pushActors()

.task {
  等候模型.pushActors()
}

构建并数据结构c语言版第二版课后答案运转,翻开调试控ios模拟器制台:

iOS 的 AsyncSequence 和 AsyncStream 教程

actorStream即便您的代数据结构教程第5版李春葆答案码不要求任何元素,根据推送的也会运转。它读取整个文件并缓冲序列元素。

Conclusion

留意:数据文件仅在发动项目中。如果要构建和ios14.4.1更新了什么运转该项目,请将它们复制到终究项目中。

在本教程中,您:

  • 比较了同步和异步读取非常大的文件时的速度和内存运用情况。
  • 创立并运用了自界说AsyncSequence.
  • 创立并运用了根据拉的和根据推的AsyncStreams。
  • 表明在AsyncStream代码恳求序列元素之前,根据拉的程序什么都不做,而根据推送的程序AsyncStream不管代码是否恳求序列元数据结构严蔚敏素都运转。

您能够运用AsyncSequen数据结构实验报告ceAsyncStream从现有代码生成异步序列——您屡次调用的任何闭包,以及只报告新值且不需求回来呼应的托付ios15办法。

下载项目材料与原文地址

这里也引荐一些面试相关的内容!数据结构

  • ① BAT等各个大厂iOS面试真题+答案大全数据结构c语言版第二版课后答案

  • ② iOS中高级开发必看的抢手书籍(经典必看)

  • ③ iOS开发高级面试线程是什么意思“简历制作”线程数越多越好吗辅导

  • ④ iOS面试流程到基础知识大全

发表评论

提供最优质的资源集合

立即查看 了解详情