基礎非同步語法-async、await、Task 和 MainActor - Swift 新手入門

Поделиться
HTML-код
  • Опубликовано: 28 янв 2025

Комментарии • 46

  • @ChaoCode
    @ChaoCode  2 года назад +9

    影片最後講到的練習題連結在這裡~~ 👉tinyurl.com/swift217
    終於講到 concurrency,這是最多人留言問會不會介紹的,所以準備得特別緊張,講的過程也覺得... 沒有白板好難講... 希望大家還是吸收😅
    我學 async 其實是很久以前剛寫後端的事了,我寫了一個專案滿滿都是 async,但是我覺得我改版到第四次或第五次才真的理解
    語法本身不難,畢竟就只是一律在 async 前面加上 await,但重點是要考慮到「非同步」造成的後續影響,很容易出現意料之外的情況和 bug,所以我一直強調看到 await 要記得,這一行和下一行之間可能出現很大的變化

  • @dawei84_dev
    @dawei84_dev 8 месяцев назад +1

    Jane妳解釋得實在有夠清楚,超級感謝妳的影片

  • @jackgalileo4156
    @jackgalileo4156 Год назад

    謝謝!

  • @RaymondLung
    @RaymondLung 2 года назад +2

    老師你的語速越來越穩了,超喜歡妳的語調跟音色

    • @ChaoCode
      @ChaoCode  2 года назад +1

      謝謝~~ 但我反而覺得我越來越不會講了 🤣

  • @brieflyfun
    @brieflyfun 2 года назад +2

    原來MainActor是新的寫法,之前用GCD一陣子了,還沒注意有新的API耶~~

    • @ChaoCode
      @ChaoCode  2 года назад +2

      這幾個都是 5.5 去年更新的寫法 本來只有支援 iOS15 但現在都有 backport 到 iOS13,我覺得 backport 之後就變得蠻實用了~~

  • @卡路里-b9o
    @卡路里-b9o 2 года назад +2

    太棒了,之前都只能找國外影片,現在有中文頻道會更好理解,謝謝老師~

    • @cowton0517
      @cowton0517 2 года назад

      可以請老師全英文再講一次嗎>

    • @birdmichael126
      @birdmichael126 2 года назад

      @@cowton0517 ???

    • @birdmichael126
      @birdmichael126 2 года назад

      @@cowton0517 我很看好你哦~哈哈哈哈

  • @qianqian888
    @qianqian888 Год назад +1

  • @9rvmpc47
    @9rvmpc47 2 года назад +2

    設計跟 try error 思路解釋清楚,第一個我覺得用中文講 swift 語法清楚直接完整的頻道. 感謝分享

  • @fepo389
    @fepo389 2 года назад +1

    寫作業的時候覺得把deliveredCount 傳進去覺得很髒,沒想到原來還有defer這種寫法,學習新知識了,感謝!

  • @paulwen5877
    @paulwen5877 2 года назад

    感謝分享!!! 一直不是很懂async跟await 在swift怎麼用 都被之前的寫法卡住 看完影片茅塞頓開!

  • @yshlnhn
    @yshlnhn 2 года назад +1

    老师会安排Combine的讲解吗?这个要安排进去就更好了,多谢多谢

    • @ChaoCode
      @ChaoCode  2 года назад

      Combine 應該是不會,我的 Combine 知識要到能講解還差太遠 😂

  • @lyc7485
    @lyc7485 2 года назад +2

    這集的目的很明顯,就是想把耗時間的運作放到背景去執行,不要影響主要畫面的執行功能,不過作業寫出來還是有點不太一樣,不知道我寫得是不是正確的,第一題我把送達的食物數量計算放到extention Deliverable裡面,然後用if去判斷是否十個商品都送到,都送到再print,然後外面的item Forloop只有放 Task { await item.order() },印出來約3.25秒,不過我看解答是把計數放到defer去執行,雖然之前介紹過defer,但還是看不太懂解答的意思,第二題我寫得跟Jane的比較像,但url我是放在struct外面,fetch的function也是放在struct外面,不像Jane把它變成靜態屬性跟方法,forloop的程式碼一樣,但最終印出來順序跟解答不一樣,變成
    > 網路請求是否在 Main Thread?false
    > 網路請求是否在 Main Thread?false
    > 印出貓咪知識是否在 Main Thread?true
    🐈 貓咪知識:XXX
    > 印出貓咪知識是否在 Main Thread?true
    🐈 貓咪知識:XXX
    > 網路請求是否在 Main Thread?false
    > 印出貓咪知識是否在 Main Thread?true
    🐈 貓咪知識:XXX
    但因為執行速度太快,無法判斷三個下載是否有干擾,因此也不知道是不是有寫對作業,另外在看thread的地方一直有 Class property 'current' is unavailable from asynchronous contexts; Thread.current cannot be used from async contexts.; this is an error in Swift 6 的警告是正常的嗎?
    最後,我的專案裡面使用async優先進入main thread只有updateUI,但在fetch Data的部分我沒有使用await,是不是其實要把fetch Data改寫成使用await的code會比較理想呢?

    • @ChaoCode
      @ChaoCode  2 года назад +3

      嗨嗨,第一題的 defer 是每次這整個 Task 執行完要離開前會檢查目前送了幾個食物,如果跟總食物數量一樣就表示完成
      不過這個判斷是否所有 Task 都結束,其實後面其實會教更好的做法~
      第二題印出來的順序其實不重要,重點只是檢查網路請求必須是在背景 & 印出來的時候是在 main thread,所以你的結果是沒問題的
      你的印出來的結果看起來像是你的系統只能同時背景跑兩個 thread,所以是兩個跑完之後才換第三個。如果你不確定的話,可以再放到專案中改用手機測試看看,應該就會可以跑三個
      然後警告的部分是正常的,我這裡用 Thread.current.isMainThread 只是為了檢查作業,實際上寫專案時不會用這個
      而會有這警告是因為 Swift 從 5.5~6 正在一步一步調整異步工作的方法,會慢慢關掉和限制一些舊的做法,現在都還是黃字警告,到 Swift 6 的時候就會是紅字了
      最後你的專案的問題,你的意思是你現在 fetch data 是用舊的 api(要用 Result 或者 callback)的方式嗎?雖然沒有對錯之分,但如果不是為了配合最低 iOS 要求的話,我會建議一率都用新的 async api,比較好讀也比較好維護,也是未來 Swift 的方向~

    • @lyc7485
      @lyc7485 2 года назад +1

      @@ChaoCode 了解,不過我是從ios15開始學的,所以也不知道舊版的語法哪些可以用哪些不能用,以目前業界製作的app大多都會向下支援到哪個版本呢?

    • @ChaoCode
      @ChaoCode  2 года назад +1

      @@lyc7485 iOS15 就是 Swift 加入 async 語法的時候哦,不過 async 有被 backport 到 iOS13,但只是語法的部分,api 很多還是要 iOS15+ 才有
      業界的話現行版本 -1 -2 我覺得都是合理的,但當然也有一些公司要求更多😅

  • @sugoilang
    @sugoilang Год назад

    如果Task的功能是把裡面的任務丟到其他thread處理,那在25:44的部分,加上MainActor 又強制所有內容丟回main thread執行,是否等於Task完全沒有意義? 或者Task只代表將任務獨立為非同步,而不能保證他要在哪個thread執行 謝謝

    • @wandahu8058
      @wandahu8058 Год назад +1

      我也有这个疑问!!!!

    • @wandahu8058
      @wandahu8058 Год назад +1

      好像是因为Task并不代表或者不一定代表丢到其他thread处理,却依然可以创建异步的任务

  • @pig2000b
    @pig2000b 2 года назад +1

    想請問ChaoCode老師
    作業中的第一題的解答Task { defer {}} 應該不是在mainTread上
    這樣好像會印出2個以上完成任務時間?
    還想請教文件裡面定義的 Task where Success == Never, Failure == Never
    這段的意思是永遠不會有成功失敗嗎(上網好像沒有找到有用的知識,自己亂猜的)

    • @ChaoCode
      @ChaoCode  2 года назад +2

      嗨嗨,第一題確實不是在 main thread 中執行,所以可能會印出很多次,也可能印不出來。這個後面會教比較好的做法~
      我當時只想到先從同時執行多件事情開始練習就沒想到這點,不好意思~我來改一下,謝謝你提醒 😊
      Never 代表的的確就是「不會發生」,同時也代表假如發生的話就要直接當掉(因為是非預期狀況)
      不過這裡會這樣寫只是因為內建的 sleep 是宣告在這組 Generic 之下(可以在這看到:github.com/apple/swift/blob/5eb942ce563e3b49619e3e5af31ccfb6e82b0181/stdlib/public/Concurrency/TaskSleep.swift)
      所以要用它就是要從這邊使用~
      另外現在的版本已經不需要這個 extension 了哦,現在有 Task.sleep(for: ) 這個方法,可以直接放入秒數

    • @pig2000b
      @pig2000b 2 года назад +1

      @@ChaoCode
      感謝老師回覆, Task.sleep(for)這個方法可以使用了
      但是我比較想了解文件裡面的寫法代表的是什麼意思,
      where代表他要遵守的條件
      但是Never == Success
      這是什麼怪怪的條件
      查文件也只有寫Available when Success is Never and Failure is Never.
      也是說當成功=never與失敗=never的時候
      才可以使用, 但是我還是沒有很明白這句英文表是的是哪一種狀況下會發生Never == Success?

    • @ChaoCode
      @ChaoCode  2 года назад +2

      @@pig2000b 嗨嗨,Never 就是前面說的不會發生,所以成功是 Never、失敗是 Never 基本上就是不存在的。所以這個方法是被「靜態方法」,你並不會建立這個 Task 實例哦,只是要設定 extension 一定要明確寫出類型宣告才這樣寫~

  • @stanleyhuang2186
    @stanleyhuang2186 2 года назад +2

    想請問一下,如果有了 async/await 的功能,那還需要 combine 嗎?
    感覺 combine 的功能,好像都可以利用 async 寫出來,而且更符合直覺內容,
    ( combine 感覺好難理解 😥)

    • @ChaoCode
      @ChaoCode  2 года назад +1

      很多人都會問這個問題
      我個人覺得 async await 是完全取代了 GCD + completion + Result
      至於 combine 的話,我覺得有一些重疊,但還是有我覺得 combine 寫起來比較順的,像是處理錯誤或是 streams(也可能只是我還不會習慣新寫法)
      所以對我來說是兩個共存~

    • @birdmichael126
      @birdmichael126 2 года назад

      @@ChaoCode 就像chaocode说的,我理解的Async/Await 是提供提供的一套非常lower-level APIs. 取代了 GCD向现代编程迈进.
      而combine,是一套提供超级多预设操作符来解决复杂业务场景的框架.

  • @撞到牆
    @撞到牆 2 года назад

    妳會不會下載檔案到sandbox的documents資料夾裡?

    • @ChaoCode
      @ChaoCode  2 года назад

      沒有試過耶,我只有存到文件的 Shared Playground Data 資料夾而。
      感覺 FileManager 應該可以?但我不確定,因為 Playground 很多東西都要另外再 import 😔

    • @撞到牆
      @撞到牆 2 года назад

      @@ChaoCode 我的playgrounds不能import appkit,設定ios或macos都不能一樣耶,它卡到陰了

    • @ChaoCode
      @ChaoCode  2 года назад

      @@撞到牆 那 import SwiftUI 看看~裡面也有 NSImage 的

    • @撞到牆
      @撞到牆 2 года назад

      @@ChaoCodeimport SwiftUI, 一樣沒有NSImage

    • @ChaoCode
      @ChaoCode  2 года назад

      @@撞到牆 😔😔😔 Playground 的問題,我想你只能開專案試了

  • @Sunalamye
    @Sunalamye 2 года назад +1

    看到你用 Task
    去查了一下最低版本支持
    發現只支持13之後
    (╯°□°)╯︵ ┻━┻
    公司專案不使用工具包
    用你的寫法大概可以少好一段代碼
    心動但專案到底標是iOS 10
    只能自己做小專案的時候用了⋯⋯

    • @ChaoCode
      @ChaoCode  2 года назад +2

      10?! 這是我聽過最低的了... 感覺維護起來好累喔🤯

    • @Sunalamye
      @Sunalamye 2 года назад

      @@ChaoCode 幾乎就是純objc 了,真的會遇到很神奇的Bug 😂

  • @result0924
    @result0924 2 года назад +1

    老師您好:首先非常感謝您這一系列的影片讓我獲益良多。
    但我在影片範例照著練習時發現
    for number in 1...5 {
    Task {
    work(name: "員工 \(number) 號")
    }
    }
    執行時、發現雖然不會跑在Main thread
    但一次只會跑一個Thread
    不會像您影片上一樣
    一次跑8個Thread
    但如果用dispatchqueue.global().async
    就可以跑多個Thread
    不知道是因為什麼原因、
    所以想問問看
    再次感謝

    • @ChaoCode
      @ChaoCode  2 года назад +3

      你是在 Playground 上執行還是在其他專案中執行呢?
      如果不是在 playground,因為Task 會繼承現有的 actor(後面幾集會講到),所以如果是在其他環境中可能會有不一樣的行為
      如果是在 playground 還有這個問題的話,我就不太確定為什麼了,也許可以把 playground 的 platform 改成 macOS 看看?

    • @result0924
      @result0924 2 года назад

      @@ChaoCode
      我是在Playground上運行的。
      另外我把platform改成macOS就可以了、
      非常感謝、這困擾了我很久~~