Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Swiftの生みの親による async/await for Swiftを徹底解説し 新しい非同期処理の手法を理解する

yimajo
September 02, 2018
4k

Swiftの生みの親による async/await for Swiftを徹底解説し 新しい非同期処理の手法を理解する

iOSDC Japan 2018 の資料です https://iosdc.jp/2018/

yimajo

September 02, 2018
Tweet

More Decks by yimajo

Transcript

  1. SwiftͷੜΈͷ਌ʹΑΔ async/await for SwiftΛపఈղઆ͠ ৽͍͠ඇಉظॲཧͷख๏Λཧղ͢Δ iOSDC Japan 2018 Track B

    17:40- ϨΪϡϥʔτʔΫ(30෼) גࣜձࣾΩϡϦΦγςΟιϑτ΢ΣΞࠓ৓ળۣ !ZJNBKP
  2. ʮSwift 5 async/await ݚڀಡຊʯ IUUQTCPPUIQNKBJUFNT • ٕज़ܥಉਓࢽ(epub, pdf) • async/awaitͱ͸Կ͔

    • HydraͰཧղ͢Δasync/await • Hydraͷasync/await࣮૷ΛಡΉ • ϓϩϙʔβϧͷղઆ • ͞·͟·ͳݴޠͰͷasync/awaitͱͦͷྺ࢙
  3. ඇಉظॲཧʹؔ͢Δ async/await دΓͷྺ࢙ ೥ϝϧϰΟϯɾίϯ΢ΣΠࢯͷ࿦จʹΑΔίϧʔνϯ͕ൃද ೥ΧʔϧɾώϡʔΠοτࢯɺϔϯϦʔɾϕΠΧʔࢯͷ࿦จʹΑΔ'VUVSF͕ൃද ೥$/&5'SBNFXPSLίϧʔνϯαϙʔτʢओʹZJFMEʣ ೥$Y/&5'SBNFXPSL3FBDUJWF&YUFOTJPOT 3Y ͕ಋೖ ೥$/&5'SBNFXPSLBTZODBXBJU

    5BTLϕʔε ೥%BSUBTZODBXBJUʢ'VUVSFϕʔεʣ͕ಋೖ ೥+BWB4DSJQU&4 &4 BTZODBXBJU 1SPNJTFϕʔε ͕ಋೖ ೥,PUMJOFYQFSJNFOUBMBTZODBXBJU %FGFSSFE TVTQFOE 3Yͬͯ೥΋લͰ ͔ͭBTZODBXBJUΑΓ લͳΜͩͶʔ
  4. w ΫϩʔδϟͰίʔϧόοΫ͢Δͱίʔυ͕ωετ͍ͯͬͯ͠͠·͏ w ΤϥʔॲཧΛϋϯυϥ͝ͱʹॻ͘ͷ͸ࠔ೉ w ৚݅ʹΑͬͯΫϩʔδϟΛݺͼग़͢ͷ͸ۤ௧ w ؔ਺͕஋Λฦ͔͢ɺதஅ͢Δ͜ͱΛՄೳʹ͢Δ w δΣωϨʔλʢZJFMEʣ΍ඇಉظϞσϧͦͷଞͷػೳΛ࣮૷͢Δͷʹ࢖༻Ͱ͖Δ

    w ͜ͷϓϩϙʔβϧͰ͸ίϯϓϦʔγϣϯϋϯυϥͷଟ͘ͷ໰୊Λഉআ w ࠷΋ҰൠతͳϢʔεέʔεʹ޲໋໊͔ͬͯ๏ͱ༻ޠΛόΠΞε͢Δ w BTZOD͔ZJFMET͔ʹ͍ͭͯ͸ίΞηϚϯςΟΫεʹ͸ؔ܎͠ͳ͍ w தஅʹؔ͢Δ"1*ʢCFHJO"TZOD TVTQFOE"TZODʣ w 'VUVSFʹΑͬͯฒྻ࣮ߦΛߦ͏݅ w 0CK$ͷίϯϓϦʔγϣϯϋϯυϥϕʔεͷ"1*Λ 4XJGUͰ࢖͑ΔΑ͏ ม׵͢Δ w BTZODؔ਺΋UISPXTͰ͖ΔΑ͏ʹ͠ɺUSZBXBJUͰϋϯυϦϯάͰ͖ΔΑ͏ʹ͢Δ w ίϯύΠϥ͸Ϋϩʔδϟ͕ඇಉظ͔Ͳ͏͔؆୯ʹ൑ఆͰ͖Δ w EFGFS͸ίϧʔνϯ͕ഁغ͞Εͨࡍʹ΋ಈ࡞͢ΔΑ͏ʹ͢Δ w ʢϋϯυϥͳΒҾ਺Λ૿΍͕͢ʣBTZODͳSFUVSO͸݁ՌΛλϓϧͰฦͤΔ w ίϯύΠϥ͕ANZ2VFVFBTZOD\^Aͳهड़Λݕग़ͯ͠pYJUͰमਖ਼Ͱ͖Δ w "#*4UBCJMJUZʹӨڹ͠ͳ͍ w BTZODͳΒUISPXTͱ͢Δͱύλʔϯ͸ݮΔ͕ܽ఺͸͋Δ w BTZODͳΒσϑΥϧτUISPXTʹ͠ɺBTZOD OPOUISPXJOH ʹ͢Δͷ΋ܽ఺͸͋Δ w ίϧʔνϯΛ༻ҙ͍ͨ͠ͷͰ͋ͬͯBTZODBXBJUΛ࣮૷͍ͨ͠ͷͰ͸ͳ͍ w $ͷΑ͏ʹҰൠతͳBTZODBXBJU͸'VUVSFΫϥεΛฦ͢͜ͱʹͳΔ w ͦ͏ͳΔͱBTZODBXBJUΛݴޠϨϕϧͰ࣮૷͢Δ͜ͱʹͳͬͯ͠·͏ w ͜ͷఏҊ͸AYBXBJUGPP CBS AͷΑ͏ʹνΣΠχϯάΛ͏·͘Ͱ͖Δ w ۩ମྫ͸ͳ͍͕͜ͷఏҊ͔Βকདྷ΁ͷ֦ுੑɺ΍͍͖ͬͯΛड़΂͍ͯΔ ͜ͷϓϩϙʔβϧʹ͍ͭͯ ಈػίϯϓϦʔγϣϯϋϯυϥ͸࠷దͰ͸ͳ͍ ղܾࡦ͸ίϧʔνϯ 0CK$Πϯϙʔλͷม׵ طଘػೳͱͷ૬ޓ࡞༻ աڈͷίʔυͱͷޓ׵ੑ "#*TUBCJMJUZ΁ͷӨڹ ଞͷγϯλοΫε ୅ସҊ কདྷతͳํ޲ੑ ँࣙ
  5. w ΫϩʔδϟͰίʔϧόοΫ͢Δͱίʔυ͕ωετ͍ͯͬͯ͠͠·͏ w ΤϥʔॲཧΛϋϯυϥ͝ͱʹॻ͘ͷ͸ࠔ೉ w ৚݅ʹΑͬͯΫϩʔδϟΛݺͼग़͢ͷ͸ۤ௧ w ؔ਺͕஋Λฦ͔͢ɺதஅ͢Δ͜ͱΛՄೳʹ͢Δ w δΣωϨʔλʢZJFMEʣ΍ඇಉظϞσϧͦͷଞͷػೳΛ࣮૷͢Δͷʹ࢖༻Ͱ͖Δ

    w ͜ͷϓϩϙʔβϧͰ͸ίϯϓϦʔγϣϯϋϯυϥͷଟ͘ͷ໰୊Λഉআ w ࠷΋ҰൠతͳϢʔεέʔεʹ޲໋໊͔ͬͯ๏ͱ༻ޠΛόΠΞε͢Δ w BTZOD͔ZJFMET͔ʹ͍ͭͯ͸ίΞηϚϯςΟΫεʹ͸ؔ܎͠ͳ͍ w தஅʹؔ͢Δ"1*ʢCFHJO"TZOD TVTQFOE"TZODʣ w 'VUVSFʹΑͬͯฒྻ࣮ߦΛߦ͏݅ w 0CK$ͷίϯϓϦʔγϣϯϋϯυϥϕʔεͷ"1*Λ 4XJGUͰ࢖͑ΔΑ͏ ม׵͢Δ w BTZODؔ਺΋UISPXTͰ͖ΔΑ͏ʹ͠ɺUSZBXBJUͰϋϯυϦϯάͰ͖ΔΑ͏ʹ͢Δ w ίϯύΠϥ͸Ϋϩʔδϟ͕ඇಉظ͔Ͳ͏͔؆୯ʹ൑ఆͰ͖Δ w EFGFS͸ίϧʔνϯ͕ഁغ͞Εͨࡍʹ΋ಈ࡞͢ΔΑ͏ʹ͢Δ w ʢϋϯυϥͳΒҾ਺Λ૿΍͕͢ʣBTZODͳSFUVSO͸݁ՌΛλϓϧͰฦͤΔ w ίϯύΠϥ͕ANZ2VFVFBTZOD\^Aͳهड़Λݕग़ͯ͠pYJUͰमਖ਼Ͱ͖Δ w "#*4UBCJMJUZʹӨڹ͠ͳ͍ w BTZODͳΒUISPXTͱ͢Δͱύλʔϯ͸ݮΔ͕ܽ఺͸͋Δ w BTZODͳΒσϑΥϧτUISPXTʹ͠ɺBTZOD OPOUISPXJOH ʹ͢Δͷ΋ܽ఺͸͋Δ w ίϧʔνϯΛ༻ҙ͍ͨ͠ͷͰ͋ͬͯBTZODBXBJUΛ࣮૷͍ͨ͠ͷͰ͸ͳ͍ w $ͷΑ͏ʹҰൠతͳBTZODBXBJU͸'VUVSFΫϥεΛฦ͢͜ͱʹͳΔ w ͦ͏ͳΔͱBTZODBXBJUΛݴޠϨϕϧͰ࣮૷͢Δ͜ͱʹͳͬͯ͠·͏ w ͜ͷఏҊ͸AYBXBJUGPP CBS AͷΑ͏ʹνΣΠχϯάΛ͏·͘Ͱ͖Δ w ۩ମྫ͸ͳ͍͕͜ͷఏҊ͔Βকདྷ΁ͷ֦ுੑɺ΍͍͖ͬͯΛड़΂͍ͯΔ ͜ͷϓϩϙʔβϧʹ͍ͭͯ ಈػίϯϓϦʔγϣϯϋϯυϥ͸࠷దͰ͸ͳ͍ ղܾࡦ͸ίϧʔνϯ 0CK$Πϯϙʔλͷม׵ طଘػೳͱͷ૬ޓ࡞༻ աڈͷίʔυͱͷޓ׵ੑ "#*TUBCJMJUZ΁ͷӨڹ ଞͷγϯλοΫε ୅ସҊ কདྷతͳํ޲ੑ ँࣙ
  6. async/awaitͷίʔυྫʢٖࣅίʔυͰ͢ʣ // async/await @IBAction func touchUpButton(_ sender: Any) { beginAsync

    { let image = await ௨৴ͯ͠ը૾औಘ͢Δ() imageView.image = image } } // ैདྷͷίϯϓϦʔγϣϯϋϯυϥํࣜ @IBAction func touchUpButton(_ sender: Any) { ௨৴ͯ͠ը૾औಘ͢Δ() { image in imageView.image = image } }
  7. async/awaitͷίʔυྫʢٖࣅίʔυͰ͢ʣ // async/await @IBAction func touchUpButton(_ sender: Any) { beginAsync

    { let image = await ௨৴ͯ͠ը૾औಘ͢Δ() imageView.image = image } } // ैདྷͷίϯϓϦʔγϣϯϋϯυϥํࣜ @IBAction func touchUpButton(_ sender: Any) { ௨৴ͯ͠ը૾औಘ͢Δ() { image in imageView.image = image } } CFHJO"TZODͷதͰ BXBJUΩʔϫʔυΛ͚ͭΔ ͜ͱͰಉظॲཧͷΑ͏ʹॻ͚Δ
  8. ෳ਺ͷawaitͷྫʢٖࣅίʔυͰ͢ʣ @IBAction func touchUpButton(_ sender: Any) { beginAsync { let

    src = await ௨৴ͯ͠ը૾औಘ͢Δ() let image = await දࣔ༻ʹը૾Ճ޻͢Δ(src) imageView.image = image } }
  9. ෳ਺ͷawaitͷྫʢٖࣅίʔυͰ͢ʣ @IBAction func touchUpButton(_ sender: Any) { beginAsync { let

    src = await ௨৴ͯ͠ը૾औಘ͢Δ() let image = await දࣔ༻ʹը૾Ճ޻͢Δ(src) imageView.image = image } } ෳ਺ͷBXBJUͰ Ұ࣮ͭͣͭߦͰ͖Δ
  10. @IBAction func touchUpButton(_ sender: Any) { beginAsync { do {

    let image = try await ը૾औಘ͢Δ() imageView.image = image } catch CocoaError.userCanccelled { // Ϣʔβ͕ࣗ෼ͰΩϟϯηϧͨ͠ͷͰԿ΋͠ͳ͍ } catch { present(error) } } } ΤϥʔϋϯυϦϯά͸EP DBUDI USZ͕࢖͑Δʢٖࣅίʔυʣ
  11. @IBAction func touchUpButton(_ sender: Any) { beginAsync { do {

    let image = try await ը૾औಘ͢Δ() imageView.image = image } catch CocoaError.userCanccelled { // Ϣʔβ͕ࣗ෼ͰΩϟϯηϧͨ͠ͷͰԿ΋͠ͳ͍ } catch { present(error) } } } ΤϥʔϋϯυϦϯά͸EP DBUDI USZ͕࢖͑Δʢٖࣅίʔυʣ ίϯϓϦʔγϣϯϋϯυ ϥํࣜͷΑ͏ʹFSSPSΛҾ਺Ͱ ౉͞ͳͯ͘΋ྑ͘ͳΔ
  12. // Τϥʔ͕͋Ε͹ throw ͢Δͱఆٛ͢Δ func ը૾औಘ͢Δ() async throws -> UIImage

    {} // Τϥʔ͸ throw ͠ͳ͍ͱఆٛ͢Δ func ը૾औಘ͢Δ() async -> UIImage {} asyncؔ਺ͷthrowsͷఆٛํ๏͸2ύλʔϯࣔ͞Ε͍ͯΔ ύλʔϯΤϥʔΛUISPXT͍ͨ͠ͳΒUISPXT͚ͭΔ ύλʔϯΤϥʔΛUISPXTͨ͘͠ͳ͍ͳΒOPOUISPXJOH
  13. // Τϥʔ͕͋Ε͹ throw ͢Δͱఆٛ͢Δ func ը૾औಘ͢Δ() async throws -> UIImage

    {} // Τϥʔ͸ throw ͠ͳ͍ͱఆٛ͢Δ func ը૾औಘ͢Δ() async -> UIImage {} // Τϥʔ͸ throw ͠ͳ͍ͱఆٛ͢Δ func ը૾औಘ͢Δ() async(nonthrowing) -> UIImage {} // async ͸ throws ͱΈͳ͞ΕΔ func ը૾औಘ͢Δ() async -> UIImage {} asyncؔ਺ͷthrowsͷఆٛํ๏͸2ύλʔϯࣔ͞Ε͍ͯΔ ύλʔϯΤϥʔΛUISPXT͍ͨ͠ͳΒUISPXT͚ͭΔ ύλʔϯΤϥʔΛUISPXTͨ͘͠ͳ͍ͳΒOPOUISPXJOH
  14. // Τϥʔ͕͋Ε͹ throw ͢Δͱఆٛ͢Δ func ը૾औಘ͢Δ() async throws -> UIImage

    {} // Τϥʔ͸ throw ͠ͳ͍ͱఆٛ͢Δ func ը૾औಘ͢Δ() async -> UIImage {} // Τϥʔ͸ throw ͠ͳ͍ͱఆٛ͢Δ func ը૾औಘ͢Δ() async(nonthrowing) -> UIImage {} // async ͸ throws ͱΈͳ͞ΕΔ func ը૾औಘ͢Δ() async -> UIImage {} asyncؔ਺ͷthrowsͷఆٛํ๏͸2ύλʔϯࣔ͞Ε͍ͯΔ (JU)VCʹ͋Δ4XJGU ͷ1VMM3FRVFTUʹ͸ͪ͜Βͷ࣮૷͕ॻ͔ Ε͍ͯΔ ύλʔϯΤϥʔΛUISPXT͍ͨ͠ͳΒUISPXT͚ͭΔ ύλʔϯΤϥʔΛUISPXTͨ͘͠ͳ͍ͳΒOPOUISPXJOH
  15. ͜Ε͕async/await஍ࠈʁ(ٖࣅίʔυ) @IBAction func touchUpButton(_ sender: Any) { beginAsync { let

    src1 = await ௨৴ͯ͠ը૾औಘ͢Δ() let src2 = await ௨৴ͯ͠ը૾औಘ͢Δ() let image = ը૾߹੒͢Δ(src1, src2) imageView.image = image } }
  16. ͜Ε͕async/await஍ࠈʁ(ٖࣅίʔυ) @IBAction func touchUpButton(_ sender: Any) { beginAsync { let

    src1 = await ௨৴ͯ͠ը૾औಘ͢Δ() let src2 = await ௨৴ͯ͠ը૾औಘ͢Δ() let image = ը૾߹੒͢Δ(src1, src2) imageView.image = image } } ಉ࣌ʹݺͼग़ͤΕ͹͍͍ͷʹ ແବʹBXBJUͯ͠͠·͏
  17. FutureΛ࢖ͬͯฒྻ࣮ߦ͢ΔྫʢٖࣅίʔυͰ͢ʣ @IBAction func touchUpButton(_ sender: Any) { beginAsync { let

    f1 = Future { await ௨৴ͯ͠ը૾औಘ͢Δ() } let f2 = Future { await ௨৴ͯ͠ը૾औಘ͢Δ() } let image = ը૾߹੒͢Δ(try await f1.get(), try await f2.get()) imageView.image = image } }
  18. FutureΛ࢖ͬͯฒྻ࣮ߦ͢ΔྫʢٖࣅίʔυͰ͢ʣ @IBAction func touchUpButton(_ sender: Any) { beginAsync { let

    f1 = Future { await ௨৴ͯ͠ը૾औಘ͢Δ() } let f2 = Future { await ௨৴ͯ͠ը૾औಘ͢Δ() } let image = ը૾߹੒͢Δ(try await f1.get(), try await f2.get()) imageView.image = image } } BXBJUͯ͠Δ͚Ͳ 'VUVSFͷΠχγϟϥΠβ ͸಺෦ͰCFHJO"TZOD͢Δ HFUϝιουͰ଴ͬͯ͘ΕΔ
  19. class Future<T> { private enum Result { case error(Error), value(T)

    } private var result: Result? = nil private var awaiters: [(Result) -> Void] = [] // Fulfill the future, and resume any coroutines waiting for the value. func fulfill(_ value: T) { precondition(self.result == nil, "can only be fulfilled once") let result = .value(value) self.result = result for awaiter in awaiters { awaiter(result) } awaiters = [] } // Mark the future as having failed to produce a result. func fail(_ error: Error) { precondition(self.result == nil, "can only be fulfilled once") let result = .error(error) self.result = result for awaiter in awaiters { awaiter(result) } awaiters = [] } func get() async throws -> T { switch result { // Throw/return the result immediately if available. case .error(let e)?: throw e case .value(let v)?: return v // Wait for the future if no result has been fulfilled. case nil: return await suspendAsync { continuation, error in awaiters.append({ switch $0 { case .error(let e): error(e) case .value(let v): continuation(v) } }) } } } // Create an unfulfilled future. init() {} convenience init(_ body: () async -> T) { self.init() beginAsync { do { self.fulfill(await body()) } catch { self.fail(error) } } } } class Future<T> w ϓϩϙʔβϧʹ͸ΫϦε͞Μͷ࣮૷ྫ w ଞͷݴޠͰ͸1SPNJTF5BTL%FGFSSFE͕͋Δ
  20. class Future<T> { private enum Result { case error(Error), value(T)

    } private var result: Result? = nil private var awaiters: [(Result) -> Void] = [] // Fulfill the future, and resume any coroutines waiting for the value. func fulfill(_ value: T) { precondition(self.result == nil, "can only be fulfilled once") let result = .value(value) self.result = result for awaiter in awaiters { awaiter(result) } awaiters = [] } // Mark the future as having failed to produce a result. func fail(_ error: Error) { precondition(self.result == nil, "can only be fulfilled once") let result = .error(error) self.result = result for awaiter in awaiters { awaiter(result) } awaiters = [] } func get() async throws -> T { switch result { // Throw/return the result immediately if available. case .error(let e)?: throw e case .value(let v)?: return v // Wait for the future if no result has been fulfilled. case nil: return await suspendAsync { continuation, error in awaiters.append({ switch $0 { case .error(let e): error(e) case .value(let v): continuation(v) } }) } } } // Create an unfulfilled future. init() {} convenience init(_ body: () async -> T) { self.init() beginAsync { do { self.fulfill(await body()) } catch { self.fail(error) } } } } class Future<T> w ϓϩϙʔβϧʹ͸ΫϦε͞Μͷ࣮૷ྫ w ଞͷݴޠͰ͸1SPNJTF5BTL%FGFSSFE͕͋Δ HFUϝιουͰ TVTQFOE"TZODΛ࢖͍ͬͯΔͷͰ͜Ε ΛཧղͰ͖Ε͹͞ΒʹBTZODBXBJUΛ׬ શʹཧղͰ͖ͦ͏
  21. func suspendAsync<T>( _ body: (_ continuation: @escaping (T) -> (),

    _ error: @escaping (Error) -> ()) -> () ) async throws -> T suspendAsync ͸ ैདྷͷίϯϓϦʔγϣϯϋϯυϥܕͷؔ਺Λ async/await ͷؔ਺ʹͰ͖Δ΋ͷ
  22. func suspendAsync<T>( _ body: (_ continuation: @escaping (T) -> (),

    _ error: @escaping (Error) -> ()) -> () ) async throws -> T Ҿ਺ͷDPOUJOVBUJPOΫϩʔδϟ͸ ࠶։͍ͨ͠ॲཧͱ஋Λ౉͢ suspendAsync ͸ ैདྷͷίϯϓϦʔγϣϯϋϯυϥܕͷؔ਺Λ async/await ͷؔ਺ʹͰ͖Δ΋ͷ
  23. suspendAsync ͷར༻ྫʢΤϥʔ͸লུʣ // ίʔϧόοΫAPIΛasync/awaitԽ͢Δϥούʔ func getStuff() async -> Stuff {

    return await suspendAsync { continuation in // ↓ैདྷͷίʔϧόοΫAPIΛݺͼग़͢ getStuff { stuff in // ඇಉظॲཧ׬ྃޙʹcontinuationΛ࣮ߦ continuation(stuff) } } } // ैདྷͷΫϩʔδϟͰ݁ՌΛฦ͢ίʔϧόοΫAPI func getStuff(completion: (Stuff) -> ()) { ... }
  24. suspendAsync ͷར༻ྫʢΤϥʔ͸লུʣ // ίʔϧόοΫAPIΛasync/awaitԽ͢Δϥούʔ func getStuff() async -> Stuff {

    return await suspendAsync { continuation in // ↓ैདྷͷίʔϧόοΫAPIΛݺͼग़͢ getStuff { stuff in // ඇಉظॲཧ׬ྃޙʹcontinuationΛ࣮ߦ continuation(stuff) } } } // ैདྷͷΫϩʔδϟͰ݁ՌΛฦ͢ίʔϧόοΫAPI func getStuff(completion: (Stuff) -> ()) { ... } λεΫͷऴྃ࣌ʹDPOUJOVBUJPOΫ ϩʔδϟΛݺͼग़͠
  25. class Future<T> { // লུ … convenience init(_ body: ()

    async -> T) { self.init() beginAsync { do { self.fulfill(await body()) } catch { self.fail(error) } } } } ·ͣ Future ͷΠχγϟϥΠβ͔ΒίʔυΛݟͯΈΔ
  26. class Future<T> { // লུ … convenience init(_ body: ()

    async -> T) { self.init() beginAsync { do { self.fulfill(await body()) } catch { self.fail(error) } } } } ·ͣ Future ͷΠχγϟϥΠβ͔ΒίʔυΛݟͯΈΔ ฒྻ࣮ߦ͍ͨ͠ίʔυΛ ඇಉظͰݺͼग़͠BXBJU͠ ݁ՌΛGVMpMMʹ౉͢ɻ
  27. class Future<T> { private enum Result { case error(Error), value(T)

    } private var awaiters: [(Result) -> Void] = [] // লུ … func get() async throws -> T { switch result { // Throw/return the result immediately if available. case .error(let e)?: throw e case .value(let v)?: return v // Wait for the future if no result has been fulfilled. case nil: return await suspendAsync { continuation, error in awaiters.append({ switch $0 { case .error(let e): error(e) case .value(let v): continuation(v) } }) } } } } Futureͷget͸ʁ
  28. class Future<T> { private enum Result { case error(Error), value(T)

    } private var awaiters: [(Result) -> Void] = [] // লུ … func get() async throws -> T { switch result { // Throw/return the result immediately if available. case .error(let e)?: throw e case .value(let v)?: return v // Wait for the future if no result has been fulfilled. case nil: return await suspendAsync { continuation, error in awaiters.append({ switch $0 { case .error(let e): error(e) case .value(let v): continuation(v) } }) } } } } Futureͷget͸ʁ HFUΑΓલʹॲཧ׬ྃ͠GVMpMM͞Εͯ Ε͹HFU͞ΕͨΒ͙݁͢ՌΛฦ͢
  29. class Future<T> { private enum Result { case error(Error), value(T)

    } private var awaiters: [(Result) -> Void] = [] // লུ … func get() async throws -> T { switch result { // Throw/return the result immediately if available. case .error(let e)?: throw e case .value(let v)?: return v // Wait for the future if no result has been fulfilled. case nil: return await suspendAsync { continuation, error in awaiters.append({ switch $0 { case .error(let e): error(e) case .value(let v): continuation(v) } }) } } } } HFUΑΓલʹGVMpMM͞Εͯͳ͚Ε͹ BXBJUFSΫϩʔδϟ഑ྻʹ DPOUJOVBUJPOΛ ݺͼग़͢ΫϩʔδϟΛBQQFOE͠ GVMpMM͞ΕͨλΠϛϯάͰ݁ՌΛฦͤΔ Futureͷget͸ʁ HFUΑΓલʹॲཧ׬ྃ͠GVMpMM͞Εͯ Ε͹HFU͞ΕͨΒ͙݁͢ՌΛฦ͢
  30. class Future<T> { private enum Result { case error(Error), value(T)

    } private var result: Result? = nil private var awaiters: [(Result) -> Void] = [] // লུ … func fulfill(_ value: T) { precondition(self.result == nil, "can only be fulfilled once") let result = .value(value) self.result = result for awaiter in awaiters { awaiter(result) } awaiters = [] } } ࣍ʹFutureͷfulfill͕Ͳ͏ͳ͍ͬͯΔ͔
  31. class Future<T> { private enum Result { case error(Error), value(T)

    } private var result: Result? = nil private var awaiters: [(Result) -> Void] = [] // লུ … func fulfill(_ value: T) { precondition(self.result == nil, "can only be fulfilled once") let result = .value(value) self.result = result for awaiter in awaiters { awaiter(result) } awaiters = [] } } Ҿ਺͔Β݁ՌΛ3FTVMUͱ͠ BXBJUFSΫϩʔδϟ഑ྻʹ͋ΔΫϩʔδϟΛ 3FTVMUΛҾ਺ʹݺͼग़͠ ࣍ʹFutureͷfulfill͕Ͳ͏ͳ͍ͬͯΔ͔
  32. ࢀߟϙϓςϐϐοΫIUUQNBOHBMJGFXJOUBLFTIPCPDPKQSFOTBJQPQVUF • ݁ՌͷܕTͷ஋Λͦͷ··ฦ͢͜ͱͰࣗવͳϝιουνΣΠϯ ͕Ͱ͖ΔΑ͏ʹͳΔ • x = await foo().bar()ͷΑ͏ʹͰ͖Δ •

    C#͸ x = await (await foo()).bar()ͷΑ͏ʹͳΔ ͦͷଞͷϝϦοτ ࢀߟϙϓςϐϐοΫIUUQNBOHBMJGFXJOUBLFTIPCPDPKQSFOTBJQPQVUF
  33. private struct StateMachine : IAsyncStateMachine { public int state; //

    ະॲཧ, ॲཧத, ॲཧ׬ྃ, ΤϥʔͷΑ͏ʹ࢖ΘΕΔ private TaskAwaiter<double> awaiter; public void MoveNext() { try { // stateʹΑΔ෼ذॲཧ͕͋Γɺඇಉظॲཧ͸ίʔϧόοΫʹొ࿥͞ΕΔ // ϓϩάϥϚ͕ॻ͍ͨasync/awaitΛ࢖͏ίʔυ͕await࢖Θͳ͍ܗͰ͜ͷՕॴʹདྷΔ } catch (Exception exception) { this.state = -2; return; } } } async double CalcAsync(double r) { await Task.Delay(1000) return r } ϓϩάϥϚ͕ॻ͍ͨasync/awaitΛ࢖͏ίʔυͷྫ ίϯύΠϥʹΑͬͯࣗಈੜ੒͞ΕΔίʔυͷ Ұ෦෼Λলུ͠ൈਮͨ͠΋ͷ
  34. beginAsync಺Ͱωετ͞ΕΔͱಡΉͷ͕ΩπΠ @IBAction func touchUpButton(_ sender: Any) { beginAsync { let

    src = await ௨৴ͯ͠ը૾औಘ͢Δ() CoreSpotlight༻ʹը૾Ճ޻͢Δ(src) { image in addSpotlight(image) { self.saved = true } } let image = await දࣔ༻ʹը૾Ճ޻͢Δ(src) imageView.image = image } }
  35. beginAsync಺Ͱωετ͞ΕΔͱಡΉͷ͕ΩπΠ @IBAction func touchUpButton(_ sender: Any) { beginAsync { let

    src = await ௨৴ͯ͠ը૾औಘ͢Δ() CoreSpotlight༻ʹը૾Ճ޻͢Δ(src) { image in addSpotlight(image) { self.saved = true } } let image = await දࣔ༻ʹը૾Ճ޻͢Δ(src) imageView.image = image } } ͭ໨ͷBXBJUͷؒʹ΍Δҙຯ ͸͋ΔͩΖ͏͚Ͳ ωετ͕ؾʹͳͬͯ͠·͏
  36. awaitͨؔ͠਺Λॲཧͨ͠Ωϡʔʹґଘ͢Δ func queueHopping() async -> Void { doSomeStuff() await DispatchQueue.main.syncCoroutine()

    // Ҏ߱ϝΠϯεϨουͰͷૢ࡞ʹͳΔ doSomeStuffOnMainThread() await backgroundQueue.asyncCoroutine() // Ҏ߱ϝΠϯͰͳ͍εϨουͰͷૢ࡞ʹͳΔ doSomeStuffInBackground() }
  37. awaitͨؔ͠਺Λॲཧͨ͠Ωϡʔʹґଘ͢Δ func queueHopping() async -> Void { doSomeStuff() await DispatchQueue.main.syncCoroutine()

    // Ҏ߱ϝΠϯεϨουͰͷૢ࡞ʹͳΔ doSomeStuffOnMainThread() await backgroundQueue.asyncCoroutine() // Ҏ߱ϝΠϯͰͳ͍εϨουͰͷૢ࡞ʹͳΔ doSomeStuffInBackground() } ϝΠϯΩϡʔΛಉظ
  38. awaitͨؔ͠਺Λॲཧͨ͠Ωϡʔʹґଘ͢Δ func queueHopping() async -> Void { doSomeStuff() await DispatchQueue.main.syncCoroutine()

    // Ҏ߱ϝΠϯεϨουͰͷૢ࡞ʹͳΔ doSomeStuffOnMainThread() await backgroundQueue.asyncCoroutine() // Ҏ߱ϝΠϯͰͳ͍εϨουͰͷૢ࡞ʹͳΔ doSomeStuffInBackground() } ϝΠϯΩϡʔΛಉظ όοΫάϥ΢ϯυ ΩϡʔΛಉظ
  39. ΋͠௨৴ͯ͠ը૾औಘ͢Δͷ͕ผεϨουͳΒ… @IBAction func touchUpButton(_ sender: Any) { beginAsync { let

    image = await ϝΠϯεϨου֎Ͱ௨৴ͯ͠ը૾औಘ͢Δ() DispatchQueue.main.async { // ϝΠϯεϨουʹ੾Γସ͑ͯViewΛૢ࡞ imageView.image = image } } }
  40. ΋͠௨৴ͯ͠ը૾औಘ͢Δͷ͕ผεϨουͳΒ… @IBAction func touchUpButton(_ sender: Any) { beginAsync { let

    image = await ϝΠϯεϨου֎Ͱ௨৴ͯ͠ը૾औಘ͢Δ() DispatchQueue.main.async { // ϝΠϯεϨουʹ੾Γସ͑ͯViewΛૢ࡞ imageView.image = image } } } ैདྷͷ%JTQBUDI2VFVFNBJO Ͱ΋੾Γସ͑Ͱ͖Δ͕ʜ ੾Γସ͑΍Γͨ͘Ͷʔͳʔ
  41. ཁ๬ɿ ϗϯτ͸͜͏ͳͬͯཉ͍͠ΑͶ… @IBAction func touchUpButton(_ sender: Any) { beginAsync(.main) {

    let image = await ϝΠϯεϨου֎Ͱ௨৴ͯ͠ը૾औಘ͢Δ() // ͜͜ͷίϯςΩετ͸ϝΠϯεϨουͳͷͰͦͷ··ViewΛૢ࡞ imageView.image = image } }
  42. ཁ๬ɿ ϗϯτ͸͜͏ͳͬͯཉ͍͠ΑͶ… @IBAction func touchUpButton(_ sender: Any) { beginAsync(.main) {

    let image = await ϝΠϯεϨου֎Ͱ௨৴ͯ͠ը૾औಘ͢Δ() // ͜͜ͷίϯςΩετ͸ϝΠϯεϨουͳͷͰͦͷ··ViewΛૢ࡞ imageView.image = image } } CFHJO"TZODͷ Ҿ਺ʹΩϡʔΛࢦఆ͠ ίϯςΩετΛࢦఆͤͯ͞Α
  43. • malcommac/Hydra • https://github.com/malcommac/Hydra • ಛ௃ • JSͷasync/awaitΛࢀߟʹ͍ͯͯ͠ • Promise<T>Λฦ͢

    • Google/Promises • https://github.com/google/promises • ಛ௃ • ίΞ͕Objective-CͰॻ͔Ε͍ͯΔ • SwiftͰ΋΋ͪΖΜ࢖͍΍͍͢ ϥΠϒϥϦ͸ίϧʔνϯͰ͸ͳ͘εϨουʹΑΓॲཧΛ࠶։ͨ͠Γఀࢭ͢Δ let asyncFunc = async({ _ -> Int in let loggedUser = try await(loginUser(username, pass)) let followersList = try await(getFollowers(loggedUser)) let countUnfollowed = try await(unfollow(followersList)) return countUnfollowed }).then({ value in print("Unfollowed \(value) users") })