Task.initã®ã¯ãã¼ã¸ã£ã¼ã«[weak self]ã¯ãããªããTask.detachedã¨TaskGroup.addTaskãåæ§
2022å¹´7æ29æ¥ãã¤ã³ãã¬ã¹R&D社ããSwift Concurrencyã®è§£èª¬æ¬ããªãªã¼ã¹ãã¾ããã ãã¡ãã®æ¬ã¯ä¸åã§Swift Concurrencyã®æ©è½ãã»ã¼ç¶²ç¾ ããConcurrencyæ©è½ã®è§£èª¬æ¬ã§ãã æ¥æ¬èªã§Swift Concurrencyãå¦ã¹ã解説æ¬ã¯ã¾ã å°ãªãã®ã§ãSwift 5.5ããã®éåæå¦çããã¾ãæ¸ãããæ¹ã«ã¯å¿ è¦ã®æ¬ã¨ãªã£ã¦ãã¾ãã ãã¦ããã£ãããªãªã¼ã¹ããã°ãããªã®ã§ãããä¸é¨ã®ãµã³ãã«ã³ã¼ãããã¾ãè¯ãã³ã¼ãã§ã¯ããã¾ããã§ããã ãã§ã«ãµã³ãã«ã³ã¼ãã®ãªãã¸ããªã¯ä¿®æ£æ¸ã¿ã§ãããã©ã®ãããªä¿®æ£ããã£ãã®ãããã®è¨äºã§èª¬æãããã¨æãã¾ãã
2022å¹´7æ29æ¥ãã¤ã³ãã¬ã¹R&D社ããSwift Concurrencyã®è§£èª¬æ¬ããªãªã¼ã¹ãã¾ããã
ä¸åã§ãã¹ã¿ã¼ï¼Swift Concurrencyå ¥éã§ãã

ãã¡ãã®æ¬ã¯ä¸åã§Swift Concurrencyã®æ©è½ãã»ã¼ç¶²ç¾
ããConcurrencyæ©è½ã®è§£èª¬æ¬ã§ãã
æ¥æ¬èªã§Swift Concurrencyãå¦ã¹ã解説æ¬ã¯ã¾ã å°ãªãã®ã§ãSwift 5.5ããã®éåæå¦çããã¾ãæ¸ãããæ¹ã«ã¯å¿
è¦ã®æ¬ã¨ãªã£ã¦ãã¾ãã
詳ããå
容ã¯ãã¡ããã覧ãã ããã
å人èªã¨ãã¦å
ã«ãªãªã¼ã¹ãã¾ãããã忥çãåãå
容ã¨ãªã£ã¦ãã¾ãã
å人çã¯BOOTHã§è²©å£²ä¸ã§ãã
ãã¦ããã£ãããªãªã¼ã¹ããã°ãããªã®ã§ãããä¸é¨ã®ãµã³ãã«ã³ã¼ãããã¾ãè¯ãã³ã¼ãã§ã¯ããã¾ããã§ããã
ãã§ã«ãµã³ãã«ã³ã¼ãã®ãªãã¸ããªã¯ä¿®æ£æ¸ã¿ã§ãããã©ã®ãããªä¿®æ£ããã£ãã®ãããã®è¨äºã§èª¬æãããã¨æãã¾ãã
Task.initã®ã¯ãã¼ã¸ã£ã¼ã«[weak self]ã¯ãããªã
ãã¨ãã¨ã®ãµã³ãã«ã³ã¼ãã§ã¯ãã®ããã«Task.init
ã®ã¯ãã¼ã¸ã£ã¼ã«[weak self]
ãã¤ãã¦ãã¾ããã
[weak self]
ããã¦ç´ æ´ã«å¾ªç°åç
§ãåé¿ãããã¨ããã³ã¼ãã«ãã¦ãã¾ããã
Task { [weak self] in
let mypageData = await self?.fetchMyPageData()
print(mypageData ?? "")
}
ã¨ããããTask.init
ã®ã¯ãã¼ã¸ã£ã¼å
ã§self
ãåç
§ãã¦ã循ç°åç
§ã®æããããã¾ããã§ããã
ããã@_implicitSelfCaptureã¨ããç¹å¥ãªå±æ§ãæ©è½ãã¦ãã¦ãã¯ãã¼ã¸ã£ã¼å
ã«æç¤ºçã«self
ã¨æ¸ããªãã¦ãã³ã³ãã¤ã«ãéãã¾ãã
Task {
let mypageData = await fetchMyPageData() // self.fetchMyPageData()ã§ãªãã¦ãã
print(mypageData)
}
ãªããã®æ¸ãæ¹ãã§ããã®ããé ã追ã£ã¦èª¬æãã¾ãã
ã¨ã¹ã±ã¼ãã¯ãã¼ã¸ã£ã®ãããã
Task.init
ã®å®ç¾©ãXcodeã®å®ç¾©ã¸ã£ã³ãã§è¦ã¦ã¿ã¾ãã
extension Task where Failure == Never {
public init(priority: TaskPriority? = nil, operation: @escaping @Sendable () async -> Success)
}
operation
弿°ã¯ã¯ãã¼ã¸ã£ã¼ã«ãªã£ã¦ãã¦@escaping
屿§ãã¤ãã¦ãããã¨ãåããã¾ãã
@escaping
屿§ããããããã¦ã¿ã¾ãããã
@escaping
屿§ã¯é¢æ°ã®å¼æ°ã¨ãã¦æ¸¡ãããã¯ãã¼ã¸ã£ãã颿°æ¬æãçµäºããå¾ã«å¼ã³åºãããå ´åã«ã¤ãããã屿§ã§ãã
@escaping
屿§ãã¤ããããã¯ãã¼ã¸ã£ã¼å
ã§ã¯self
ã¤ã³ã¹ã¿ã³ã¹ã®ã¢ã¯ã»ã¹ã¯æç¤ºçã«self
ãã¤ããªãã¨ã³ã³ãã¤ã«ã¨ã©ã¼ã«ãªãã¾ãã
ããã¯èª¤ã£ã¦å¾ªç°åç
§ãçºçããªãããã«éçºè
ã«æ³¨æãä¿ãç®çãããã¾ãã
ä¾ãã°ã次ã®ãããªã³ã¼ããããã¨ãã¾ãã
class SampleClouser {
var value: Int = 0
var completion: () -> Void = {}
func add(value: Int, completion: @escaping () -> Void) {
self.value += value
completion()
}
func addOne() {
add(value: 1) {
print(value) // Reference to property 'value' in closure requires explicit use of 'self' to make capture semantics explicit
}
}
init() {}
}
add
ã¡ã½ããã®å¼æ°completion
ã¯@escaping
屿§ãã¤ããã¯ãã¼ã¸ã£ã¼ã§ãã
å¥ã®ã¡ã½ããaddOne
ã§add
ã¡ã½ãããå¼ã³åºããéã«ã¯ãã¼ã¸ã£ã¼å
ã§self
ã®ã¤ã³ã¹ã¿ã³ã¹ãããã§ã¯value
ãåç
§ãã¦ãã¾ãã
ãããããã®ã¾ã¾ã§ãã¨å¾ªç°åç
§ã®å±éºãããããã³ã³ãã¤ã«ã¨ã©ã¼ã¨ãªãã¾ãã
Reference to property 'value' in closure requires explicit use of 'self' to make capture semantics explicit
// [çè
訳] ã¯ãã¼ã¸ã£ã¼å
ã®`value`ããããã£ã®åç
§ã¯æç¤ºçã«selfã使ç¨ããæç¤ºçãªãã£ããã£ã使ãã¦ãã ããã
ãã ãããã®ã¾ã¾value
ããããã£ã«self
ãã¤ããã¨å¾ªç°åç
§ãèµ·ãããã¡ã¢ãªãªã¼ã¯ãçºçãã¾ãã
func addOne() {
add(value: 1) {
print(self.value)
}
}
çç±ã¯ãself
ã§ããSampleClouser
ãcompletion
ã¯ãã¼ã¸ã£ã¼ãããããã£ã¨ãã¦å¼·åç
§ãã¦ãã䏿¹ã§ãcompletion
ã¯ãã¼ã¸ã£ã¼ãã¯ãã¼ã¸ã£ã¼å
ã§self
ãå¼·åç
§ãã¦ãããããã循ç°åç
§ãå¼ãèµ·ããããã§ãã
@escaping
屿§ãã¤ããã¯ãã¼ã¸ã£ã¼ã§ããè¡ã循ç°åç
§ã®è§£æ¶æ¹æ³ã¯[weak self]
ã§self
ããã£ããã£ããæ¹æ³ã§ãã
ããã«ãã£ã¦ã循ç°åç
§ãèµ·ãããself
ã®ã¤ã³ã¹ã¿ã³ã¹ã«ã¯ãã¼ã¸ã£ã¼å
ã§ã¢ã¯ã»ã¹ãã§ããããã«ãªãã¾ãã
func addOne() {
add(value: 1) { [weak self] in
print(self?.value ?? "")
}
}
ã¨ã¹ã±ã¼ãã¯ãã¼ã¸ã£èªä½ã解説ã¯The Swift Programming Language(æ¥æ¬èªç)ãåç §ãã ããã
Task.initã®ã¯ãã¼ã¸ã£ã¼ã®selfåç §
ã¨ããããTask.init
ã®ã¯ãã¼ã¸ã£ã¼å
ã§ã¯@escaping
屿§ãããã«ãé¢ããããæç¤ºçãªself
åç
§ãèæ
®ããªãã¦ã循ç°åç
§ã®åé¡ãçºçãã¾ããã
Taskãææ¡ãããSE-304 Structured concurrencyã®ãããã¼ã¶ã«ãè¦ã¦ã¿ã¾ãããã
Implicit "self" ã¨ããç¯ã«æ¸ããã¦ãã¾ãã
The intent behind requiring self. when capturing self in an escaping closure is to warn the developer about potential reference cycles. The closure passed to Task is executed immediately, and the only reference to self is what occurs in the body. Therefore, the explicit self. isn't communicating useful information and should not be required.
[çè 訳]ã¨ã¹ã±ã¼ãã¯ãã¼ã¸ã£å ã§selfããã£ããã£ããéã«self.ãå¿ é ãªèæ¯ã¯éçºè ã«å¾ªç°åç §ã®å¯è½æ§ãè¦åããããã§ãã䏿¹ã§Taskã«æ¸¡ãããã¯ãã¼ã¸ã£ã¼ã¯å³æã«å®è¡ãããselfã¸ã®å¯ä¸ã®åç §ã¯ã¯ãã¼ã¸ã£ã¼æ¬æã§çºçããã ãã§ãããããã£ã¦ãselfãæç¤ºãããã¨ã¯æå¹ãªæ å ±ãä¼ãã¦ããããå¿ é ã«ãã¹ãã§ãããã¾ããã
Task.init
ã®ã¯ãã¼ã¸ã£ã¼ã¯å³æã«å®è¡ãããself
ã¤ã³ã¹ã¿ã³ã¹ã¸ã®å¾ªç°åç
§ã®æãããªãã®ã§æé»çã«self
åç
§ãã¦ãåé¡ãªãã¨ããè¨è¼ãããã¦ãã¾ãã
æ´ã«Swiftã®ãªãã¸ããªããTask.init
ã®å®ç¾©ãã¿ã¦ã¿ã¾ãããã
extension Task where Failure == Error {
@discardableResult
@_alwaysEmitIntoClient
public init(
priority: TaskPriority? = nil,
@_inheritActorContext @_implicitSelfCapture operation: __owned @Sendable @escaping () async throws -> Success
)
operation
ã¯ãã¼ã¸ã£ã¼ã®å¼æ°ã®åã«@_implicitSelfCapture
ã¨ãã屿§ãã¤ãã¦ãã¾ãã
ã¢ã³ãã¼ã¹ã³ã¢ãã¤ãã¦ãã屿§ã¯æ£å¼ãªè¨èªæ©è½ã¨ãã¦ã¯ã¾ã è°è«ä¸ã®å±æ§ã§ãã
@_implicitSelfCapture
ã¯self
ãåç
§åã§ãã£ã¦ãã¯ãã¼ã¸ã£ã¼å
ã§ãã£ããã£ãããªãã¦ãself
ã«ã¢ã¯ã»ã¹ãã§ããããã«ãªã屿§ã§ãã
class C {
func f() {}
func g(_: @escaping () -> Void) {
g({ f() }) // error: call to method 'f' in closure requires explicit use of 'self'
}
func h(@_implicitSelfCapture _: @escaping () -> Void) {
h({ f() }) // ok
}
}
Task.init
ã®ã¯ãã¼ã¸ã£ã¼ã«ã¯@_implicitSelfCapture
ãã¤ãããã¦ãããããæç¤ºçã«self
ãã¤ããªãã¦ãself
ã®ã¡ã½ãããããããã£ã«ã¢ã¯ã»ã¹ãã§ããã¨ãããã¨ã§ãã
åé ã®ãµã³ãã«ã³ã¼ããããä¸åº¦æ²è¼ãã¾ãã
Task {
let mypageData = await fetchMyPageData() // self.fetchMyPageData()ã§ãªãã¦ãã
print(mypageData)
}
fetchMyPageData
ã¡ã½ããã¯self
ã«å®ç¾©ããã¦ããã¡ã½ããã§ãã
é常ã®@escaping
ãã¤ããããã¯ãã¼ã¸ã£ã¼ã§ã¯self.fetchMyPageData()
ã¨ããªããã°ã³ã³ãã¤ã«ã¨ã©ã¼ã«ãªãã¾ãããTask.init
ã¯@_implicitSelfCapture
ãã¤ãããã¦ãããããself
ãã¤ããªãã¦ãã³ã³ãã¤ã«ã¨ã©ã¼ãèµ·ãããªãã®ã§ãã
Xcodeã®å®ç¾©ã¸ã£ã³ãã§ã¯@_implicitSelfCaptureã確èªã§ããªã
ãã ãå¥å¦ãªãã¨ã¯Xcodeã®å®ç¾©ã¸ã£ã³ãã§ã¯Task.init
ã®å®ç¾©ã«@_implicitSelfCapture
ã®ã¤ãã¦ãããã¨ã¯ç¢ºèªã§ãã¾ããã§ããã
æå ã§ç¢ºèªããã®ã¯æ¬¡ã®ãã¼ã¸ã§ã³ã§ãã
- Xcode 13.4.1
- Xcode 14 beta4
ãã®ããã«operation
弿°ã¯@escaping
ãã¤ããããé常ã®ã¯ãã¼ã¸ã£ã¼ã«ã¿ãã¾ãã
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
extension Task where Failure == Never {
public init(priority: TaskPriority? = nil, operation: @escaping @Sendable () async -> Success)
}
ã¢ã³ãã¼ã¹ã³ã¢ãã¤ãããã屿§ã¯æ£å¼ãªè¨èªæ©è½ã¨ãã¦æ±ºå®ãããã®ã§ã¯ãªãã®ã§ãå®ç¾©ã¸ã£ã³ãããã§ã¯é ããã¦ãã¾ã£ã¦ããã®ããããã¾ããã
Task.init
ã§ã¯ãã¼ã¸ã£ã¼å
ã«self
ãã£ããã£ãä¸è¦ãªçç±ã¯@_implicitSelfCapture
ãä»ä¸ããã¦ãããã¨ãè¦ãã¦ããã¾ãããã
ãã®ãã¡æ£å¼ãªå±æ§ã«ãªã£ãéã«ã¯Xcodeããã§ã確èªãã§ããããã«ãªãã§ãããã
Task.detachedã¨TaskGroup.addTaskã®ã¯ãã¼ã¸ã£ã¼ã[weak self]ãããªã
SE-304ã®Implicit "self"ç¯ã§ã¯ãTask.init
ã®ä»ã«ãTask.detached
ã¨TaskGroup.addTask
ã®ã¯ãã¼ã¸ã£ã¼ã«ãself
ã®æç¤ºçãªãã£ããã£ã¯å¿
è¦ãªãã¨æ¸ããã¦ãã¾ãã
ã¤ã¾ããã®2ã¤ã®ã¯ãã¼ã¸ã£ã¼å¼æ°ã[weak self]
ã¯ããã¾ããã
ãªã®ã§æ¬¡ã®ããã«Task.detached
ã§[weak self]
ã§ã¯ãã¼ã¸ã£ã¼å
ã§self
ãã£ããã£ãå¼±åç
§ã«ããå¿
è¦ãããã¾ããã
// â ã¯ãã¼ã¸ã£ã¼ã§[weak self]ããå¿
è¦ãªã
Task.detached(priority: .low) { [weak self] in
guard let self = self else { return }
async let _ = await self.sendLog(name: "didTapButton")
}
// â ã¯ãã¼ã¸ã£ã¼å
ã§selfã«ç´æ¥ã¢ã¯ã»ã¹ãã¦ãã
Task.detached(priority: .low) {
async let _ = await self.sendLog(name: "didTapButton")
}
ããããTask.init
ã¨ã¯ç°ãªãæé»çãªself
ãã£ããã£ã¯ã§ããªãããã§ãã
Swiftã®ãªãã¸ããªã§Task.detached
ã®å®ç¾©ãã¿ã¦ã¿ã¾ãã
@discardableResult
@_alwaysEmitIntoClient
public static func detached(
priority: TaskPriority? = nil,
operation: __owned @Sendable @escaping () async -> Success
) -> Task<Success, Failure> {
Task.init
ã¨ã¯ç°ãªãoperation
ã¯ãã¼ã¸ã£ã¼ã®å¼æ°ã«@_implicitSelfCapture
屿§ã¯ã¤ãããã¦ãã¾ããã§ããã
ã§ãã®ã§ãã¯ãã¼ã¸ã£ã¼å
ã§ã¯æç¤ºçã«self
ãè¨è¿°ãå¿
è¦ã§ãã
// æé»çãªselfãã£ããã£ã¯ã§ããªãã
Task.detached(priority: .low) {
async let _ = await sendLog(name: "didTapButton") // Call to method 'sendLog' in closure requires explicit use of 'self' to make capture semantics explicit
}
ä¸è¨ã®ã³ã¼ãã§ã¯sendLog
ã¡ã½ããã«self.
ãæ¶ãã¨Call to method 'sendLog' in closure requires explicit use of 'self' to make capture semantics explicit
ã®ã³ã³ãã¤ã«ã¨ã©ã¼ã表示ããã¾ãã
æç¤ºçã«self.sendLog
ã¨self
ã®ãã£ããã£ãå¿
è¦ã§ãã
åããã¨ãTaskGroup.addTask
ã¨ThrowingTaskGroup.addTask
ã«ãè¨ãã¾ãã
TaskGroup.addTask
ã®å®ç¾©ã¯ãã¡ãã§ãã
@_alwaysEmitIntoClient
public mutating func addTask(
priority: TaskPriority? = nil,
operation: __owned @Sendable @escaping () async -> ChildTaskResult
) {
@_implicitSelfCapture
屿§ãããã¾ããã
ThrowingTaskGroup.addTask
ã®å®ç¾©ã¯ãã¡ãã§ãã
@_alwaysEmitIntoClient
public mutating func addTask(
priority: TaskPriority? = nil,
operation: __owned @Sendable @escaping () async throws -> ChildTaskResult
) {
åãã@_implicitSelfCapture
屿§ã¯ããã¾ããã
ãªã®ã§TaskGroup.addTask
ã¨ThrowingTaskGroup.addTask
ã®ã¯ãã¼ã¸ã£ã¼å
ã§ãself
ã®è¨è¿°ã¯çç¥ã§ãã¾ããã
ããã循ç°åç
§ã®æãã¯ãªãã®ã§æç¤ºçã«self.
ã¨æ¸ãã¦åé¡ãªãã§ãããã
Task.init
ã§ã¯@_implicitSelfCapture
ãã¤ããããTask.detached
ãTaskGroup.addTask
ãThrowingTaskGroup.addTask
ã§ã¯ã¤ãããã¦ããªãã®ã¯åç´ã«ä¸è²«æ§ããªãã¨æãããã®ã§ãSwiftã®ãã¼ã¸ã§ã³ããããã°ä¿®æ£ãããããããã¾ããã
éåæå¦çã®ãã£ã³ã»ã«
[weal self]ã¨guardæã§æ©æãªã¿ã¼ã³
ã¯ãã¼ã¸ã£ã¼ã§ã®ã³ã¼ã«ããã¯ã§éåæå¦çãæ¸ãå ´åã¯ã[weak self]
ã§ãã£ããã£ããå¾ãguard
æã§æ©æãªã¿ã¼ã³ããããã¨ãå¤ãã§ãã
request { [weak self] in
// æ©æãªã¿ã¼ã³
guard let self = self else { return }
// selfããªãã£ãã以éã®å¦çã¯å®è¡ãããªã
print(self.number)
}
å¦çããã£ã³ã»ã«ãããã¨ãç®çã«æ¸ãã¦ããæ¹ããããã¨æãã¾ãã
ããããTask.init
ã®ã¯ãã¼ã¸ã£ã¼å
ã§ã¯ãã®æ©æãªã¿ã¼ã³ãæå³ãããå ´é¢ã¯å¤ãã¯ãªãã§ãããã
次ã®ã³ã¼ãã¯View Controllerã®viewDidLoad
ã¡ã½ããã§Task.init
ãå¼ã³åºãã³ã¼ãã§ãã
override func viewDidLoad() {
super.viewDidLoad() // â
Task { [weak self] in
guard let self = self else { return } // â¢
try await Task.sleep(nanoseconds: 3 * NSEC_PER_SEC) // â£
}
print(number) // â¡
}
ã³ã¼ããå¼ã°ããé çªã¯â ãâ¡ãâ¢ãâ£ã®é çªã«ãªãã¾ãã
â¡ãçµãã£ãããã Task.init
ã®ã¯ãã¼ã¸ã£ã¼ãå¼ã°ãâ¢ãå®è¡ããã¾ãã
â¡ããâ¢ã®å®è¡ééã¯ã¨ã¦ãçãã®ã§ããã®éã«self
ããªããªããã¨ã¯å¤ãã®å ´åã¯ãªãã§ãããã
å
ã»ã©ã®ä¾ã§ã¯ãã»ã¨ãã©ã®å ´åâ£ã«å°éãã¦ãéåæå¦çãéå§ãã¦ãã¾ãã¾ãã
â£ã¯3ç§å¾
ã¤ã¨ããéãå¦çã§ãã
â¢ã§æ©æãªã¿ã¼ã³ãã¦ãself
ããªããªãå ´é¢ãéããã¦ããã®ã§ãã»ã¨ãã©ã®å ´åâ£ã®éãå¦çãéå§ããã¦ãã¾ãã¾ãã
Task.init
ã®ã¯ãã¼ã¸ã£ã¼ã«æ©æãªã¿ã¼ã³ããã¦ãTask.init
ã®ã¯ãã¼ã¸ã£ã¼å¦çããã£ã³ã»ã«ãããå ´åã¯éå®çã§ãã
ã§ã¯ã©ãããã°ããã§ããããï¼
Task.cancelã使ãã
Task.cancel
ã使ãã¾ãããã
ä»åã®ä¾ã§ã¯self
ãView Controllerã§ããã
ç»é¢ãé表示ã«ãªã£ããTask
ããã£ã³ã»ã«ãããã³ã¼ãã¯æ¬¡ã®ã¨ããã§ãã
var task: Task<Void, Error>?
override func viewDidLoad() {
super.viewDidLoad()
// taskãä¿æ
task = Task {
try await Task.sleep(nanoseconds: 3 * NSEC_PER_SEC)
print(number)
}
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
// ç»é¢é表示ã§ãã£ã³ã»ã«
task?.cancel()
}
Task
ã®ã¤ã³ã¹ã¿ã³ã¹ãtask
ã¨ãã¦ä¿æãã¾ãã
viewDidAppear
ã§task
ã®cancel
ã¡ã½ãããå¼ã³åºããã¨ã§ãã£ã³ã»ã«ãã§ãã¾ãã
cancelã¡ã½ããã§Task.initã¯ãã¼ã¸ã£ã¼ã®å¦çãå¿ ã忢ããããã§ã¯ãªã
ãã ããcancel
ã¡ã½ãããå¼ã³åºãã°ãå¿
ãTask.init
ã¯ãã¼ã¸ã£ã¼ã®å¦çãå¿
ã忢ããããã§ã¯ããã¾ããã
Task
ã®å¦çãå®éã«æ¢ããã«ã¯CancellationError
ã¨ããã¨ã©ã¼ãã¹ãã¼ããå¿
è¦ããããã¨ã©ã¼ãã¹ãã¼ããªã颿°ãå¼ãã§ããå ´åã¯cancel
ãã¦ãå¦çã¯æ¢ã¾ãã¾ããã
ä¾ãã°ãå
ã»ã©ã®ä¾ã§ã¯ã¹ãªã¼ãå¦çã«Task.sleep(nanoseconds:)
ã使ã£ã¦ãã¾ããã
ããã¯Task
ããã£ã³ã»ã«ãããã¨CancellationError
ãã¹ãã¼ããã®ã§ããã«å¦çã忢ãã¾ãã
task = Task {
// Taskããã£ã³ã»ã«ãããã¨ããã«åæ¢ãã
try await Task.sleep(nanoseconds: 3 * NSEC_PER_SEC)
}
Task
ã使ã£ãããä¸ã¤ã®ã¹ãªã¼ãå¦çã¯Task.sleep()
ã§ãã
ããã¯Task
ããã£ã³ã»ã«ããã¦ã忢ãã¾ããã
ç»é¢ãéãã¦ãããã£ã¡ã3ç§å¦çãå¾
ããªãã¨ããã¾ããã
task = Task {
// Taskããã£ã³ã»ã«ããã¦ã忢ããªã
await Task.sleep(3 * NSEC_PER_SEC)
}
ãã£ã³ã»ã«ãããå ´åã«å¦çãé©åã«åæ¢ãããå ´åã¯Task.checkCancellation()
ãTask.isCancelled
ãå©ç¨ã§ãã¾ãã
Task.checkCancellation()
ï¼Task
ããã£ã³ã»ã«ãããå ´åã«CancellationError
ãã¹ãã¼ããã¡ã½ãã- ã¨ããããå¦çãæ¢ããå ´åã«ä½¿ãã
Task.isCancelled
ï¼Task
ããã£ã³ã»ã«ãããå ´åã«true
ãè¿ã- ãã£ã³ã»ã«ãããå ´åã«ç¬èªå¦çãè¨è¿°ã§ãã
ä½¿ãæ¹ã¨ãã¦ã¯CancellationError
ã¹ãã¼ããªãå¦çã®åå¾ã«å¼ã³åºããã¨ã§ããã§ã«ãã£ã³ã»ã«ãã¦ããå ´åã«å¦çãæ¢ãããã¨ãã§ãã¾ãã
task = Task {
// ãã§ã«ãã£ã³ã»ã«ããã¦ãããå¦çã忢
ãã try Task.checkCancellation()
// CancellationErrorã¹ãã¼ããªãå¦ç
await Task.sleep(3 * NSEC_PER_SEC)
// ãã§ã«ãã£ã³ã»ã«ããã¦ãããå¦çã忢
try Task.checkCancellation()
}
ä¸ã®ä¾ã§ã¯Task.sleep()
ãå§ã¾ãåã«Task.checkCancellation
ãå¼ã³åºãã¦ããã§ã«ãã£ã³ã»ã«ããã¦ãããå¦çã忢ãã¾ãã
Task.sleep()
ãå®è¡ãããã¨ããã®éã«ãã£ã³ã»ã«ããã¦ã3ç§å¾
ã£ã¦ãã¾ãã¾ãã
ãããã®å¾ã«åã³Task.checkCancellation
ãå¼ã³åºããã¨ã§ãªãã¹ãç¡é§ãªæéãä½ããã«å¦çã忢ã§ãã¾ãã
Task.isCancelled
ã使ã£ãä¾ãè¦ã¦ããã¾ãããã
task = Task {
await Task.sleep(3 * NSEC_PER_SEC)
if Task.isCancelled {
// ç¬èªã®ãã£ã³ã»ã«å¦ç
// æå¾ã«ã¨ã©ã¼ãã¹ãã¼ããã¨å¦çã忢
throw CancellationError()
}
ãã£ã³ã»ã«ãããå ´åã¯Task.isCancelled
ãtrue
ã«ãªãã®ã§ãifæã®ãããã¯ã«ç¬èªã®ãã£ã³ã»ã«å¦çãå®è£
ã§ãã¾ãã
æå¾ã«ã¨ã©ã¼ãã¹ãã¼ãããã¨ã§å¦çã忢ã§ãã¾ãã
ããã§ã¯ä¾¿å®ä¸CancellationError
ãã¹ãã¼ãã¦ãã¾ãã
ç¬èªã®Error
åã§ãåé¡ãªãã§ãã
Task.initã¯ãã¼ã¸ã£ã¼ã®ã¡ã¢ãªè§£æ¾ã¿ã¤ãã³ã°
Task.init
ã¯ãã¼ã¸ã£ã¼ã®ã¡ã¢ãªè§£æ¾ã¿ã¤ãã³ã°ã¯ã¯ãã¼ã¸ã£ã¼ã®å¦çãå
¨ã¦å®äºãã¦ããã§ãã
ãã®éã¯self
ã¤ã³ã¹ã¿ã³ã¹ã®åç
§ãæ®ã£ã¦ãã¾ãã
self
ãæ¶ããã¨æã£ã¦ãå¦çãç¶ç¶ããå¯è½æ§ãããã®ã§ã注æãå¿
è¦ã§ãã
ä¾ãã°ãviewDidLoad
ã§3ç§ãããå¦çãTask.init
ã§å®è¡ããå ´åã3ç§æªæºã«ç»é¢ãé表示ããå ´åãèãã¾ãã
ç»é¢é表示ã§ç¹ã«Task.cancel
ã®å¦çã¯è¡ããªãæ³å®ã§ãã
override func viewDidLoad() {
super.viewDidLoad()
Task {
// 3ç§ãããå¦çã
// 3ç§ä»¥å
ç»é¢ãé表示ã«ãªã£ã¦ãå¦çã¯ç¶ç¶ãã
try await Task.sleep(nanoseconds: 3 * NSEC_PER_SEC)
print(number)
}
}
override func viewDidAppear(_ animated: Bool) {
// Taskã®ãã£ã³ã»ã«å¦çã¯ãã¦ããªã
super.viewDidAppear(animated)
}
viewDidLoad
ã§å¼ãã§ããTask.init
ã®å¦çã¯3ç§å¾
ã¤å¦çãããã¾ãã
viewDidLoad
ãå¼ã°ãã¦3ç§æªæºã«ç»é¢ãæ¶ãåä½ããã¦ããTask.init
ã®ã¯ãã¼ã¸ã£ã¼ã®å¦çã¯çµããããæå¾ã¾ã§å®è¡ããç¶ãã¾ãã
ã¤ã¾ãã3ç§çµã£ã¦ã¯ãã¼ã¸ã£ã¼ã®å¦çããã¹ã¦çµãã£ã¦ããself
ãè§£æ¾ãã¾ãã
ãã®ä¾ã§ã¯Task.sleep(nanoseconds:)
ã使ã£ã¦ããã®ã§ã¹ãªã¼ãããç§æ°éå¾
ã¦ã°self
ã¯è§£æ¾ããã¾ãããä¸ã«ã¯å¦çãç¡éã«çµãããªãå ´åãããã¾ãã
次ã®ããã«Notification
ã®ã¤ãã³ããfor await in
ã§å¾
ã¡åãããã³ã¼ããæ¸ããå ´åãfor await in
ã®ã³ã¼ãã¯ãã£ã³ã»ã«ãæç¤ºçã«ããªãéãç¡éã«ã¤ãã³ããå¾
ã¡åãã¾ãã
Task.init
ã«ã¯ãã¼ã¸ã£ã¼ã®å¦çã¯çµããããself
ã¤ã³ã¹ã¿ã³ã¹ã¯ãã¤ã¾ã§çµã£ã¦ãè§£æ¾ããã¾ããã
override func viewDidLoad() {
super.viewDidLoad()
Task {
// ã¤ãã³ããå¾
ã¡åãã
// ãã£ã³ã»ã«ããªãéãããã®å¦çã¯çµãããªããã¤ã¾ãselfãè§£æ¾ãããªã
for await notification in NotificationCenter.default.notifications(named: UIScene.willEnterForegroundNotification) {
print(notification)
}
}
}
ãã®ã³ã¼ãã¯ãUIScene.willEnterForegroundNotification
ã®ã¤ãã³ããfor await in
ã§å¾
ã¡åãã¦ãã¾ãã
ãã£ã³ã»ã«ã®ã³ã¼ãã¯æ¸ãã¦ããªãã®ã§ãç¡éã«ã¤ãã³ããå¾
ã¡åããã¾ãã
self
ã®ViewControllerãé表示ã«ãªã£ã¦ãself
ã¤ã³ã¹ã¿ã³ã¹ã¯è§£æ¾ããã¾ããã
Task.cancel
ã使ã£ã¦ã¿ã¹ã¯ããã£ã³ã»ã«ãã¾ãããã
Task
ãã¤ã³ã¹ã¿ã³ã¹ã¨ãã¦ä¿æãã¦ããã¦ãTask.cancel
ãè¡ã
ãTask.cancelã使ãããã®ç« ã§ãä¼ãããéãã§ãself
ããªããªãã¿ã¤ãã³ã°ã§ç¢ºå®ã«Task.cancel
ãè¡ããã¿ã¹ã¯ããã£ã³ã»ã«ããæ¹æ³ã§ãã
ç¹ã«for await in
ã§ã¯ç¡éã«ã¤ãã³ããå¾
ã¡åãããã®ã§æç¤ºçã«ãã£ã³ã»ã«ããã¦ãç¡é§ãªã¡ã¢ãªãè§£æ¾ãããã¨ãéè¦ã§ãã
override func viewDidLoad() {
super.viewDidLoad()
// taskã¤ã³ã¹ã¿ã³ã¹ãä¿æãã¦ãã
task = Task { [weak self] in
for await notification in NotificationCenter.default.notifications(named: UIApplication.willEnterForegroundNotification) {
print(notification)
}
}
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
// ç»é¢é表示ã§taskããã£ã³ã»ã«ãã
// for await inã®å¦çããã£ã³ã»ã«ããã -> ã¡ã¢ãªã®ç¡é§ããªããªã
task?.cancel()
}
éãå¦çãçµãã£ãå¾ã«self
ã¤ã³ã¹ã¿ã³ã¹ã®æç¡ã確èªãã
ä¸å¿éãå¦çãçµãã£ãå¾ã«self
ã¤ã³ã¹ã¿ã³ã¹ã®æç¡ã確èªãããã¨ã§ããã£ã³ã»ã«ã«ä¼¼ãåãããããã¨ãã§ãã¾ãã
å
ã»ã©ãéåæå¦çã®ãã£ã³ã»ã«ãã®ç« ã®ã[weal self]ã¨guardæã§æ©æãªã¿ã¼ã³ãã§ã¯ãTask.init
ã®ã¯ãã¼ã¸ã£ã¼ã®æåã§self
ã¤ã³ã¹ã¿ã³ã¹ã®æç¡ã確èªããã®ã¯ä¸è¦ã¨è©±ãã¾ããã
䏿¹ã§ãéãå¦çãçµãã£ãå¾ã«self
ã¤ã³ã¹ã¿ã³ã¹ã®æç¡ã確èªããã®ã¯å ´åã«ãã£ã¦ã¯å¦çããã£ã³ã»ã«ããæå³åããæããããã¾ãã
次ã®ã³ã¼ãã§ã¯3ç§å¾
ã¤å¦çã®å¾ã«self
ã®æç¡ããã§ãã¯ãã¦ãã¾ãã
override func viewDidLoad() {
super.viewDidLoad()
task = Task { [weak self] in
try await Task.sleep(nanoseconds: 3 * NSEC_PER_SEC)
// 3ç§ã®ã¹ãªã¼ãã®å¾ã«selfã®æç¡ãã§ãã¯
guard let self = self else { return }
// selfããªããã°ãã®å¦çã¯è¡ããªã
print(self.number)
}
}
ãããããã¨ã§å¦çãçµãã£ãå¾ã«self
ãè§£æ¾ããã¦ããå ´åã¯ãå¾ç¶ã®å¦çã¯è¡ããªããã¨ã表ç¾ã§ãã¾ãã
guard
æã使ããªãã¦ãself?
ã使ã£ã¦ããã®é½åº¦self
ã®æç¡ããã§ãã¯ã§ãã¾ãã
override func viewDidLoad() {
super.viewDidLoad()
task = Task { [weak self] in
try await Task.sleep(nanoseconds: 3 * NSEC_PER_SEC)
// 3ç§ã®ã¹ãªã¼ãã®å¾ã«selfã®æç¡ãã§ãã¯
// selfãnilãªãprintæã¯å®è¡ãããªã
print(self?.number)
}
}
ãã ããå人çã«ã¯ãTask.cancel
ãå©ç¨ããã»ããèªã¿ãããã¨ã¯æãã¾ãã
Task.initã§[weak self]ããããªããªãã®ã¯ã¨ã¦ãå¬ãã
Task.init
ãTask.detached
ãTaskGroup.addTask
ãThrowingTaskGroup.addTask
ã§ã¯ãã¼ã¸ã£ã¼ã§self
ã®å¾ªç°åç
§ãæ°ã«ããå¿
è¦ããªããªãã®ã¯ã¨ã¦ãããã§ããã
Swift Concurrencyã解決ããéåæå¦çã³ã¼ãã®åé¡ç¹ã®ä¸ã¤ã«ãã³ã¼ã«ããã¯ãå¼ã°ããªãåé¡ã¨ãããã®ãããã¾ãã
ä¾ãã°ã次ã®request
颿°ã§ãããã¨ã©ã¼çºçæã«ã³ã¼ã«ããã¯ãå¼ã°ãã¦ãã¾ããã
func request(url: URL, completionHandler: @escaping (Result<UIImage, Error>) -> ()) {
let task = URLSession.shared.dataTask(with: url) { data, response, error in
guard error == nil else { return } // ã³ã¼ã«ããã¯å¼ãã§ããªã
downloadImage(data: data) { result in
let image = try? result.get()
resizeImage(image: image) { result in
completionHandler(result)
}
}
}
task.resume()
}
ãã®ã¾ã¾ã§ã¯ã¨ã©ã¼çºçæã«å¼ã³åºãå´ã§å¾ç¶ã®å¦çãé²ã¾ãã«ãã°ã®åå ã«ãªãå¯è½æ§ãããã¾ãã
Swift Concurrencyã§ã¯async
ã§éåæé¢æ°ãå®ç¾©ãããã¨ã§å¿
ãæ»ãå¤ãã¨ã©ã¼ãã¹ãã¼ããã颿°ãå®ç¾©ã§ãã¾ãã
éåæé¢æ°:
async
ãã¤ãããã颿°ã»ã¡ã½ããã®ãã¨ã便å®çã«ããå¼ã³ã¾ããasync
ããªã徿¥ã®é¢æ°ã»ã¡ã½ããã¯å¯¾æ¯ã®ããã«åæé¢æ°ã¨å¼ãã§ãã¾ãã
func request(url: URL) async throws -> UIImage {
let (data, response) = try await URLSession.shared.data(from: url, delegate: nil)
let image = try await downloadImage(data: data)
let resizedImage = try await resizeImage(image: image)
return resizedImage
}
å¼ã³åºãå ã§ã¯æ»ãå¤ãã¨ã©ã¼ããã£ãããããã¨ã§å ¨ã¦ã®ãã¹ããã³ããªã³ã°ãå¯è½ã«ãªãã¾ãã
ã¤ã¾ãSwift Concurrencyã§ã¯éåæå¦çã§ãæ»ãå¤ããã颿°ã»ã¡ã½ããã®å®ç¾©ãéè¦ã«ãªãã¾ãã
ä»ã¾ã§ã¯ã¯ãã¼ã¸ã£ã¼ã弿°ã«æ¸¡ãã¦é¢æ°ã»ã¡ã½ããèªä½ã®æ»ãå¤ã¯Voidã«ãããã¨ãå¤ãã£ãã¨æãã¾ãããããã¨ã¯ç°ãªãã¨ãããã¨ã§ãã
æ»ãå¤ãéè¦ã«ãªããã¨ãå¤ããªãã¨ã[weak self]
ã§self
ããªãã·ã§ãã«ã§æ±ãã¨æ¸ãã¥ãããªãå ´é¢ãå¤ã
åºã¦ãã¾ãã
ä¾ãã°ãTask.init
ã[weak self]
ã§æ¸ãã¦ã¿ã¾ãã
Task { [weak self] in
let mypageData = await self?.fetchMyPageData() // æ»ãå¤ããªãã·ã§ãã«
print(mypageData ?? "")
}
func fetchMyPageData() async -> MypageInfo {
...
}
struct MypageInfo { ... }
fetchMyPageData
ã¡ã½ããã¯MypageInfo
ã¨ããstructãè¿ãã¡ã½ããã§ãã
ãã£ããé常ã®åãæ»ãå¤ã¨ãã¦ããã®ã«ãself?.fetchMyPageData
ã¨ãã¦ãããããã«æ»ãå¤mypageData
ããªãã·ã§ãã«ã«ãªããã¢ã³ã©ããããªãã¨ä¸èº«ãåãåºããªããªãã¾ãã
ã¾ãTask.init
ã®ã¯ãã¼ã¸ã£ã¼ã¯å¤ãè¿ããã¨ã§å¾ã§ãã®å¤ãå©ç¨ã§ãã¾ãã
// taskãä¿æãã¦ããã¦
let task = Task { () -> MypageInfo in
let mypageData = await fetchMyPageData()
return mypageData
}
Task {
// å¾ã§ä½¿ã
let value = await task.value
}
ãã®éã«[weak self]
ãæ¸ãã¦ãã¾ãã¨ãªãã·ã§ãã«ã®ã¢ã³ã©ããå¦çãã©ããã§å
¥ããå¿
è¦ãåºã¦ãã¦ãã¾ãã¾ãã
// self?.ã§è¨è¿°
let task = Task { [weak self] () -> MypageInfo? in // ã¯ãã¼ã¸ã£ã¼ã®æ»ãå¤ããªãã·ã§ãã«ã«ããï¼
let mypageData = await self?.fetchMyPageData()
return mypageData
}
// guard letã§è¨è¿°
let task = Task { [weak self] () -> MypageInfo? in
guard let self = self else { return nil }
let mypageData = await self.fetchMyPageData()
return mypageData
}
ããã¯é¢åã§ããã
ãªã®ã§self
ã®å¾ªç°åç
§ãæ°ã«ããå¿
è¦ããªãã®ã¯ã¨ã¦ãããããããã¨ã§ãã
åä½ç°å¢
ä¸è¨ã®ç°å¢ã§åä½ã確èªãã¾ããã
- Xcode 13.4.1
- Xcode 14beta4
ãµã³ãã«ã³ã¼ãã®ä¿®æ£ç¶æ³
æ¬æ¸ã®ãµã³ãã«ã³ã¼ãã¯ãã§ã«ä¿®æ£ãã¦ãã¾ãã
ä¿®æ£å
容ã¯ä¸è¨ããã確èªããé¡ããã¾ãã
- pull request
- release tag
æ¬ããã°ã®ãµã³ãã«ã³ã¼ã
Task.initã§selfãã£ããã£ãå¼·åç
§ããã³ã¼ããæ¬¡ã®gistã«æ®ãã¾ããã
åãã®ç¢ºèªã«ä½¿ã£ã¦ãã ããã
https://gist.github.com/SatoTakeshiX/c3cb6fe57ff1424931c21d97c5f1496a
åèè¨äº
Task.init
ã«æ¸¡ãã¯ãã¼ã¸ã£ãæé»çã«self
ããã£ããã£ãããã¨ã®èæ¯ã¨æ³¨æç¹Task.init
ã§[weak self]
ãæå¹ã§ãªããã¨ãä¸å¯§ã«è§£èª¬ãã¦ãã¦åèã«ãªãã¾ãã
- Taskã§[weak self]ã使ããªãã§ï¼
- ã¨ã¹ã±ã¼ãã¯ãã¼ã¸ã£ã¼ã®å¾ªç°åç §ãèµ·ããä»çµã¿ãåèã«ãªãã¾ãã
- iOSDC 2022 Swift Concurrency Next Step
- Swift Concurrencyã®æ°æ å ±ããå®è£ ã§æ°ãã¤ããã¹ãç¹ãã¾ã¨ã¾ã£ã¦ãã¾ãã
ä¸åã§ãã¹ã¿ã¼ï¼Swift Concurrencyå ¥é
æ¹ãã¦ããä¸åã§ãã¹ã¿ã¼ï¼Swift Concurrencyå
¥éãã¯Amazonã§è²©å£²ä¸ã§ãã
Swift Concurrencyãç¶²ç¾
ãã解説æ¸ã¯ã¾ã ä»ã«ã¯ãªãã§ãã
ãèå³ããã°ãã²æã«ã¨ã£ã¦ã覧ããã ããã°å¹¸ãã§ãã
ä¸åã§ãã¹ã¿ã¼ï¼Swift Concurrencyå ¥éã§ãã
