ํฐ์คํ ๋ฆฌ ๋ทฐ
Swift ) Actor (3) - isolated parameter / nonisolated keyword
Zedd0202 2021. 8. 29. 19:11
๐ Actor (1) ์ฝ์ผ๋ฌ๊ฐ๊ธฐ
๐ Actor (2) ์ฝ์ผ๋ฌ๊ฐ๊ธฐ
์๋ ํ์ธ์ :) Zedd์ ๋๋ค.
Actor (2) - Actor isolation ๊ธ์์ Actor isolation์ ๊ณต๋ถํด๋ดค๋๋ฐ์.
์ค๋์ isolated parameter / nonisolated keyword์ ๋ํด์ ๊ณต๋ถํด๋ณด๊ฒ ์ต๋๋ค.
๋ฐ๋์ Actor (2) - Actor isolation ๊ธ์ ์ฝ๊ณ ์์ฃผ์ธ์.
# ํ๊ณ
Actor (2) - Actor isolation ๊ธ์์ BankAccount Actor๋ฅผ ์ ์ํ์์ต๋๋ค.
(extension์ ์๋ Transfer๋ฉ์๋๋ ์ ์ธํ๊ณ ๋ณด๋๋กํ์ฃ )
actor BankAccount {
let accountNumber: Int
var balance: Double
init(accountNumber: Int, initialDeposit: Double) {
self.accountNumber = accountNumber
self.balance = initialDeposit
}
func deposit(amount: Double) {
assert(amount >= 0)
self.balance = self.balance + amount
}
}
์ ์ฝ๋์๋ ํ๊ณ๊ฐ ์กด์ฌํฉ๋๋ค.
ํ๊ณ 1. deposit๋ฉ์๋๋ ๋ฐ๋์ actor์ ์ธ์คํด์ค๋ก๋ง ์ ๊ทผ ํ ์ ์์ต๋๋ค.
์ฆ, ๋๋ ์ด๋ค ๊ณ์ข ์ฃผ๊ณ ์ฌ๊ธฐ์ ์ ๊ธํด~ ๋ผ๊ณ ํ๊ณ ์ถ์ ์ ์์ฃ .
func deposit(amount: Double, to account: โ
BankAccount โ
) {
assert(amount >= 0)
account.balance = account.balance + amount
}
์ฆ ์ด๋ฐ์์ผ๋ก global function์ ๋ง๋ค๊ณ ์ถ์ง๋ง, ๊ทธ๊ฒ ์๋ฉ๋๋ค.
์์ธ์ง๋ ์์์ฃ !?!?
๊ธ์์ ๋ดค๋ Transfer์ ๋์ผํ ๊ฒ๋๋ค.
func deposit(amount: Double, to account: BankAccount) {
assert(amount >= 0)
account.balance = account.balance + amount // Actor-isolated property 'balance' can not be referenced from a non-isolated context
}
balance๋ฅผ ์ฐธ์กฐํด์ผํ๋๋ฐ, balance๋ actor-isolated ํ๋กํผํฐ์ด๊ธฐ ๋๋ฌธ์ด์ฃ .
์ด๊ฑด self๋ฅผ ํตํด ์ฐธ์กฐํ๋ ๊ฒ๋ ์๋์ด์ cross-actor reference์ ํด๋น๋ฉ๋๋ค.
2๋ฒ์์ ์์ธํ ๋ณด๋๋ก ํฉ์๋ค.
ํ๊ณ 2. actor์ธ๋ถ์์ synchronouslyํ๊ฒ ์ฌ์ฉํ ์ ์๋ computed property๋ฅผ ๋ง๋ค ์ ์๋ค.
์, BankAccount์ ์ด๋ฆ์ ์ง์ ํ ์ ์๊ณ ,
actor BankAccount {
let accountNumber: Int
var balance: Double
let accountName: String โ
var displayName: String {
return self.accountName + "์๋
ํ์ธ์" โ
}
init(accountNumber: Int,
initialDeposit: Double,
accountName: String) {
self.accountNumber = accountNumber
self.balance = initialDeposit
self.accountName = accountName
}
}
accountName์ ๋ฐ๊ณ , displayName์ accountName์ ๋ญ๊ฐ๋ฅผ ๋ถํ์ ๋ณด์ฌ์ฃผ๊ณ ์ถ์ต๋๋ค.
๊ฐ๋จํ computed property๋ค์.
actor BankAccount { ... }
let account = BankAccount(accountNumber: 1,
initialDeposit: 100,
accountName: "Zedd")
account.displayName // Actor-isolated property 'displayName' can not be referenced from a non-isolated context
actor์ธ๋ถ์์ BankAccount ์ธ์คํด์ค๋ฅผ ๋ง๋ค๊ณ , displayName์ ํธ์ถํ๋ ค๊ณ ํ๋ฉด ์ปดํ์ผ ์๋ฌ๊ฐ ๋ฉ๋๋ค.
Actor (2) - Actor isolation ๊ธ์์ ๋งํ๋ฏ์ด, actor์ ์ ์๋
- stored, computed instance properties
- instance methods
- instance subscripts
๋ ๋ชจ๋ actor-isolated ์ํ์ ๋๋ค.
๊ทธ๋ฆฌ๊ณ ์ง๊ธ account.displayName์
actor ์ธ๋ถ์์ actor-isolated ์ ์์ ๋ํด ์ฐธ์กฐํ๋๊ฒ์ด๊ธฐ ๋๋ฌธ์ cross-actor reference๋ผ๊ณ ํ ์ ์์ต๋๋ค.
cross-actor reference๋ฅผ ํ๊ธฐ ์ํด์๋ ์๋ 2๊ฐ์ง ์กฐ๊ฑด ์ค ํ๋์ ๋ฐ๋์ ํด๋นํด์ผํฉ๋๋ค.
1. ๋ถ๋ณ ์ํ์ ๋ํ cross-actor reference. (๊ฐ์ ๋ชจ๋ ๋ด์์๋ง)
2. ๋น๋๊ธฐ ํจ์ ํธ์ถ๋ก ์ํ๋๋ ํ์
displayName์ let์ผ๋ก ์ ์ธ๋์ด์์ง ์๊ธฐ ๋๋ฌธ์ 1๋ฒ์๋ ํด๋น์ด ์๋๋ฏ๋ก ๋ฐ๋์ ๋น๋๊ธฐ๋ก ํธ์ถํด์ผํฉ๋๋ค.
์ฆ,
actor BankAccount { ... }
let account = BankAccount(accountNumber: 1,
initialDeposit: 100,
accountName: "Zedd")
await account.displayName โ
await๊ณผ ํจ๊ป ํธ์ถํด์ผํ๋ฉฐ, ์ ์ฝ๋๋ ์ด๋ ํจ์ ๋ด์์ ๋ถ๋ฆดํ ๋ ํจ์๋ฅผ async๋ก ๋ง๋ค๊ฑฐ๋, async ํธ๋ค๋ฌ ๋ด์์ ํธ์ถํด์ผ๊ฒ ์ฃ .
๊ทธ๋ฌ๋๊น ๊ฒฐ๋ก ์ ๋ถํธํ๋ค๋๊ฒ๋๋ค.
actor ์ธ๋ถ์ด๊ธด ํ์ง๋ง displayName์ ๋๋ ๊ทธ๋ฅ synchronouslyํ๊ฒ ํธ์ถํ๊ณ ์ถ์์์?
ํ๊ณ 3. Hashable conform ๋ถ๊ฐ
actor BankAccount {
...
static func someStaticThing() {
//
}
}
BankAccount.someStaticThing() โ
BankAccout์์ ์๋ static ํ๋กํผํฐ๋ ๋ฉ์๋๋ actor-isolated ํ์ง ์์ต๋๋ค.
์ฆ, actor์ธ๋ถ์์ ๋ณ๋ค๋ฅธ ์ ์ฝ์์ด ํธ์ถ์ด ๊ฐ๋ฅํฉ๋๋ค.
BankAccount๊ฐ Equatable์ ์ค์ํ๋๋ก ํด์ฃผ๊ฒ ์ต๋๋ค.
extension BankAccount: Equatable {
static func == (lhs: BankAccount, rhs: BankAccount) -> Bool {
return lhs.accountNumber == rhs.accountNumber
}
}
ํ์ํ static ๋ฉ์๋๋ฅผ ๊ตฌํํด์คฌ์ต๋๋ค.
accountNumber๋ let. ์ฆ ๋ถ๋ณ์ํ์ ์ ๊ทผ์ด์๊ณ , ==๋ static ๋ฉ์๋์ด๊ธฐ ๋๋ฌธ์ ์ ์ ์๋ ๋ฌธ์ ๊ฐ ์์ต๋๋ค.
(๋ง์ฝ ๋น๊ต์ balance๋ฅผ ๋ฃ์์ผ๋ฉด ์ปดํ์ผ์ด ์๋๊ฒ ์ง๋ง์.)
BankAccount๊ฐ Hashable์ ์ค์ํด์ฃผ๋๋ก ํ๊ฒ ์ต๋๋ค.
extension BankAccount: Hashable {
func hash(into hasher: inout Hasher) {
hasher.combine(self.accountNumber) // Actor-isolated instance method 'hash(into:)' cannot be used to satisfy a protocol requirement
}
}
WWDC21 Protect mutable state with Swift actors ๋ฅผ ๋ณด๋ฉด
์ค๋ฅ๋ฉ์์ง๊ฐ ์ด๋ ๊ฒ ๋ฌ๋ ๊ฒ ๊ฐ์๋ฐ..์๋ฌดํผ Xcode13 Beta 5 ๊ธฐ์ค์ผ๋ก
Actor-isolated instance method 'hash(into:)' cannot be used to satisfy a protocol requirement
์ด๋ ๊ฒ ๋์ต๋๋ค.
์ ์ ์ปดํ์ผ ์๋ฌ๊ฐ ๋ ๊น์?
Swift ์ปดํ์ผ๋ฌ : BankAccount๊ฐ Hashable์ ์ค์ํ์ด? ๊ทธ๋ผ ์ด hash(into:)๋ actor์ธ๋ถ์์ ํธ์ถ๋ ์ ์๊ฒ ๊ตฐ...
ํ์ง๋ง hash(into:)๋ ๋น๋๊ธฐ๊ฐ ์๋๋๊น actor-isolated๋ฅผ ์ ์ง ํ ์ ์์ด!
Actor-isolated instance method 'hash(into:)' cannot be used to satisfy a protocol requirement
๋ ๊ทธ๊ฑธ ๋ํ๋ด๊ณ ์์ฃ .
actor์ instance method๋ ๊ธฐ๋ณธ์ ์ผ๋ก actor-isolated ์ํ์ธ๋ฐ,
Actor-isolated์ธ ๋ฉ์๋ hash(into:)๋ protocol requirement๋ฅผ ์ถฉ์กฑํ๋๋ฐ ์ฌ์ฉํ ์ ์๋ค.
์ธ๊ฒ๋๋ค.
์ด๊ฒ 3๋ฒ์งธ ํ๊ณ์ ๋๋ค.
Hashable์ ์ค์ํ ์ ์๋ค๋๊ฑด, Set<BankAccount>๋ฅผ ๋ง๋ค ์ ์๋ค๋ ๊ฑธ ์๋ฏธํฉ๋๋ค.
# ์์ธ
์..ํ๊ณ์ ๋ค์ ๊ฐ๋จํ ์์ฝํด๋ณด๋ฉด,
1. deposit๋ฉ์๋๋ ๋ฐ๋์ actor์ ์ธ์คํด์ค๋ก๋ง ์ ๊ทผ ํ ์ ์์ต๋๋ค.
2. actor์ธ๋ถ์์ synchronouslyํ๊ฒ ์ฌ์ฉํ ์ ์๋ computed property๋ฅผ ๋ง๋ค ์ ์๋ค.
3. Hashable conform ๋ถ๊ฐ
์ 3๊ฐ๋ค ์์ธ์ด ๋ญ์๋์?! ๋ค ๊ทธ๋์ actor-isolated ๋๋ฌธ์ธ๊ฒ๋๋ค (๋ถ๋ ธ)
actor์ ์ ์๋
- stored, computed instance properties
- instance methods
- instance subscripts
๋ค์ด ๊ธฐ๋ณธ์ ์ผ๋ก actor-isolated ์ํ๋ผ๋ ์ฌ์ค์์ ๋น๋กฏ๋ ํ๊ณ์ ๋ค์ ๋๋ค.
๐ : ๊ทธ๋ actor-isolated์ธ ์ํ๊ฐ ์ค์ํ๋จ๊ฑด ์๊ฒ ์ด ใ ๊ทผ๋ฐ actor-isolated ์ํ๊ฒ ๋ง๋ค ์ ์๋?
๐ง๐ป : ใ ใ ์๊ฐ๋ฅ
# ๊ฐ์
๊ทธ๋์ ์ด proposal์
1. ํจ์์ ํ๋ผ๋ฏธํฐ ์ค ์ด๋ค๊ฒ์ด isolated์ธ์ง ํ์ํ๊ฑฐ๋
2. ์ ์ธ ์์ฒด๋ฅผ actor๋ก ๋ถํฐ isolatedํ์ง ์์์ผ๋ก์จ
actor-isolated๋ฅผ ์ ํํ ์ ์๋๋ก ํฉ๋๋ค.
# isolated parameter
ํ๊ณ์ ์ค 1๋ฒ์ ๊ฐ์ ํด๋ณด๊ฒ ์ต๋๋ค.
deposit์ global function์ผ๋ก ๋ง๋๋๊ฑฐ์์ฃ ?
func deposit(amount: Double, to account: BankAccount) {
assert(amount >= 0)
account.balance = account.balance + amount // โ Actor-isolated property 'balance' can not be referenced from a non-isolated context
}
์ ์ฝ๋๋
actor-isolated property์ธ balance๋ non-isolated context์์ ์ฐธ์กฐ๋ ์ ์์ด ใ ํ๊ณ ์๋ฌ๋ฅผ ๋ ๋๋ค.
์ด๊ฒ ๋์๊ฐ๊ฒ ํ๋ ค๋ฉด ์ด ํจ์๊ฐ isolated context๋ฅผ ๊ฐ์ง๊ฒ ํ๋ฉด ๋ฉ๋๋ค.
func deposit(amount: Double, to account: โ
isolated โ
BankAccount) {
assert(amount >= 0)
account.balance = account.balance + amount
}
ํจ์์ ํ๋ผ๋ฏธํฐ์ isolated ํ์๊ฐ ๋์์ต๋๋ค.
โ๏ธ ํจ์๋ ํ๋ผ๋ฏธํฐ ์ค ํ๋๊ฐ isolated ํ์๊ฐ ๋๋ฉด actor-isolated๊ฐ ๋๋ค.
์ฆ, deposit์ actor ์ธ๋ถ์ ์ ์๋์ด์์ผ๋ฏ๋ก ์๋๋ actor-isolated๊ฐ ์๋๋๋ค.
๊ทผ๋ฐ account ํ๋ผ๋ฏธํฐ์ isolated๋ก ํ์ํ๊ฒ ๋๋ฉด์, deposit์ actor-isolated ํจ์๊ฐ ๋๊ฒ๋๋ค.
func deposit(amount: Double, to account: isolated BankAccount) {
assert(amount >= 0)
account.balance = account.balance + amount โ
}
์๋ ์๋ฌ๊ฐ ๋ฌ๋ ์ ์ฝ๋๋ ์๋ฌ๊ฐ ๋์ง ์์ต๋๋ค.
์๋? ์ด์ deposit์ด isolated context๋ฅผ ๊ฐ๊ธฐ ๋๋ฌธ์ด์ฃ .
๊ทธ๋์ account.balance. ์ฆ actor-isolated ์ํ์ ์ง์ ์ ๊ทผ์ ํ ์ ์๊ฒ ๋๊ฒ๋๋ค.
# nonisolated
ํ๋ผ๋ฏธํฐ๋ฅผ isolated๋ก ํ์ํ๋๊ฒ ๋ชจ๋ ํ๊ณ์ ์ ํด๊ฒฐํด์ฃผ๋ ๊ฑด ์๋๋๋ค.
์๋ฅผ ๋ค์ด ํ๊ณ์ ์ค 2๋ฒ์ธ
2. actor์ธ๋ถ์์ synchronouslyํ๊ฒ ์ฌ์ฉํ ์ ์๋ computed property๋ฅผ ๋ง๋ค ์ ์๋ค.
๋ ์ฌ์ ํ ์์ฃ . ์ด๋ฌํ ํ๊ณ์ ์ ํด๊ฒฐํ๊ธฐ์ํ nonisolated ํค์๋๊ฐ ์์ต๋๋ค.
actor BankAccount {
let accountNumber: Int
var balance: Double
let accountName: String
โ
nonisolated โ
var displayName: String {
return self.accountName + "์๋
ํ์ธ์"
}
init() { ... }
}
nonisolated ํค์๋๋ ์ ์ฝ๋์ฒ๋ผ ํ๋กํผํฐ๋ ํจ์์ ์ ์ ์์ ๋ถํ ์ ์์ต๋๋ค.
actor์ ์ ์๋
- stored, computed instance properties
- instance methods
- instance subscripts
๋ ๊ธฐ๋ณธ์ ์ผ๋ก actor-isolated์ํ์ธ๋ฐ, nonisolated๋ฅผ ๋ถํ๊ฒ ๋๋ฉด ์ด ๋์์ ๋นํ์ฑํ ํ ์ ์๊ฒ ๋ฉ๋๋ค.
actor BankAccount {
let accountNumber: Int
var balance: Double
let accountName: String
nonisolated var displayName: String {
return self.accountName + "์๋
ํ์ธ์"
}
}
let account = BankAccount(accountNumber: 1,
initialDeposit: 100,
accountName: "Zedd")
print(account.displayName) // Zedd์๋
ํ์ธ์ โ
์ฆ, ์ด๋ ๊ฒ displayName์ ๋ํด ๋๊ธฐ์ ์ฐธ์กฐ๊ฐ ๊ฐ๋ฅํด์ง๋๋ค.
๐คฏ : ์ ใ ใ actor-isolated ๊ฐ๋ต๋ตํ๋๋ฐ
actor BankAccount {
nonisolated let accountNumber: Int
nonisolated var balance: Double
nonisolated let accountName: String
nonisolated var displayName: String {
return self.accountName + "์๋
ํ์ธ์"
}
}
๋ค nonisolated ํด๋ฒ๋ คใ กใ ก
๐ง๐ป : ์ ์๋ผ
actor BankAccount {
nonisolated let accountNumber: Int
nonisolated var balance: Double // โ Nonisolated' can not be applied to stored properties
nonisolated let accountName: String
nonisolated var displayName: String {
return self.accountName + "์๋
ํ์ธ์"
}
}
balance์ชฝ์์ ์ปดํ์ผ ์๋ฌ๊ฐ ๋๋๋ฐ์. ์๋ฌ๋
Nonisolated' can not be applied to stored properties
์ด๋ ๊ฒ ๋์ค์ง๋ง..
balance๊ฐ let์ด ์๋ var์ด๊ณ concurrent code์์ data race๊ฐ ๋ฐ์ํ ์ ์์ผ๋ฏ๋ก ๋ง์๋์ ๊ฒ ๊ฐ์ต๋๋ค ใ
nonisolated๋ก ์ธํด ํ๊ณ์ ์ค 3๋ฒ๋ ํด๊ฒฐ ๊ฐ๋ฅ!
extension BankAccount: Hashable {
โ
nonisolated โ
func hash(into hasher: inout Hasher) {
hasher.combine(accountNumber)
}
}
์ฐธ๊ณ (๋์ค์ Xcode 13 ์ ์ ๋ฆด๋ฆฌ์ฆ ๋๋ฉด ํ์ธํด๋ณผ ๊ฒ.)
์ ๋ถ๋ถ..proposal์์๋ ๋ณ๋ค๋ฅธ ์ธ๊ธ์ ์๋๋๋ฐ ใ ใ .. Xcode 13 Beta 5์์ ์ปดํ์ผ์ด ์๋ฉ๋๋ค.
์์ธ์
Actor-isolated property 'hashValue' cannot be used to satisfy a protocol requirement
Add 'nonisolated' to 'hashValue' to make this property not isolated to the actor
์ธ๋ฐ์..
Swift 4.1์์ hashValue๋ ๋ชจ๋ ํ๋กํผํฐ๊ฐ ๊ฐ๊ฐ Equatable ๋๋ Hashable์ ์ค์ํ๋ฉด, ๊ผญ ๊ตฌํํด์ฃผ์ง ์์๋ ๋์๊ณ ,
ํ๋ฌผ๋ฉฐ ์ง๊ธ์ hashValue๊ฐ deprecated ์ธ ์ํ์ธ๋ฐ์.
์ ์ด๋ฐ ์๋ฌ๊ฐ ๋๋์ง ๋ชจ๋ฅด๊ฒ ๋ค์ ใ ใ ...
๊ฒฐ๊ตญ hashValue๋ ์ ์ธํด์ nonisolated๋ก ํด์ฃผ๋๊น
extension BankAccount: Hashable {
nonisolated func hash(into hasher: inout Hasher) {
hasher.combine(accountNumber)
}
nonisolated var hashValue: Int {
return accountNumber.hashValue ^ accountNumber.hashValue &* 16777619
}
}
์ปดํ์ผ์ด ๋๊ธด ํ๋ค์! ์ฐธ๊ณ ํ์๊ธธ ใ ใ
Actor์์ ์ ์๋์ด์๋ ์ธ์คํด์ค ๋ฉ์๋๋ฅผ nonisolated๋ก ํ๊ธฐ ์ ์๋ ์ฃผ์ํด์ผํฉ๋๋ค.
extension BankAccount {
func steal(amount: Double) {
self.balance -= amount
}
}
self๋ฅผ ํตํด balance์ ์ ๊ทผํ๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ ์ ์ฝ๋๋ ๋ฌธ์ ๊ฐ ์์๋๋ฐ, ์ด๊ฑธ nonisolated๋ก ํด๋ฒ๋ฆฌ๋ฉด
extension BankAccount {
โ
nonisolated โ
func steal(amount: Double) {
self.balance -= amount // ๐จ error: actor-isolated property 'balance' can not be referenced on non-isolated parameter 'self'
}
}
์๋ฌ๊ฐ ๋ฉ๋๋ค. balance๊ฐ actor-isolated ํ๋กํผํฐ์ธ๊ฑด ๋ง์ง๋ง, ์ ๋ฉ์๋๊ฐ actor-isolated๊ฐ ์๋๊ธฐ ๋๋ฌธ์ ๋ฐ์ํ๋ ์๋ฌ์์!
๊ทธ๋ฌ๋๊น self์ฌ๋ ๋์ด์ ์ ๊ทผ์ ๋ชปํ๊ฒ ๋๋๊ฒ์ด์ฃ .
๊ทธ๋ฆฌ๊ณ ํ๋ ๋! Actor (2) - Actor isolation ๊ธ์์
actor BankAccount {
let accountNumber: Int
...
}
// ๋ค๋ฅธ ๋ชจ๋
func outside_moudle_method() โ
async โ
{
let account = BankAccount(accountNumber: 1, initialDeposit: 10)
print(โ
await โ
account.accountNumber) โ
}
๋ถ๋ณ ์ํ์ ๋ํ cross-actor reference๋ ๊ฐ์ ๋ชจ๋ ๋ด์์๋ง ์ ์ฉ์ด ๋์๊ณ ,
์ ์ฝ๋ ์ฒ๋ผ ๋ค๋ฅธ ๋ชจ๋์์๋ accountNumber๊ฐ ๋ถ๋ณ ์ํ์ฌ๋ ๋น๋๊ธฐ๋ก ์ฐธ์กฐํด์ผํฉ๋๋ค.
actor BankAccount {
public nonisolated let accountNumber: Int
...
}
// ๋ค๋ฅธ ๋ชจ๋
func outside_moudle_method() {
let account = BankAccount(accountNumber: 1, initialDeposit: 10)
print(account.accountNumber) โ
}
ํ์ง๋ง accountNumber๊ฐ nonisolated๋ฉด ๋ค๋ฅธ ๋ชจ๋์์๋ ๋๊ธฐ์ ์ผ๋ก ์ฐธ์กฐ๊ฐ ๊ฐ๋ฅํฉ๋๋ค.
nonisolated์ ๊ธฐ๋ฅ์ผ๋ก ๋ณด๋ฉด ๋น์ฐํ๊ฑฐ์ฃ ?!
ํด! ์ค๋ ๊ณต๋ถํ ๋ถ๋ถ๋ Improved control over actor isolation๋ฅผ ๋ง์ด ์ฐธ๊ณ ํ์ด์ ใ ใ
ํ๋ฆฐ ๋ถ๋ถ์ด ์๋ค๋ฉด ๋๊ธ ๋ฌ์์ฃผ์ธ์.
๋ค์๊ธ์ ์๋ง๋ Sendable์ด ๋์ง ์์๊น!
'Swift > Concurrency' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
Combine โ Swift Concurrency(async/await)๋ก ๋ฐ๊พธ๊ธฐ (feat. ๋๋์ ) (3) | 2022.01.25 |
---|---|
Actor (4) - Sendable (3) | 2021.10.11 |
Swift ) Actor (2) - Actor isolation (7) | 2021.08.23 |
Swift ) Actor (1) (5) | 2021.08.22 |
[Swift Concurrency] Async/await (11) | 2021.03.25 |
- WidgetKit
- swift array
- Combine
- ์ค์ํํธ
- iOS delegate
- swift3
- ์ ์ด์จ ํ์ฑ
- ios 13
- swift sort
- ํ๊ณ
- Accessibility
- github
- np-hard
- ์ค์ํํธ ๋ฌธ๋ฒ
- SwiftUI
- WWDC
- Git
- Xcode
- swift ๊ณต๋ถ
- FLUTTER
- np-complete
- actor
- swift tutorial
- Swift
- WKWebView
- swift delegate
- UIBezierPath
- ํผ์๋ ธ
- fastlane
- IOS
- Total
- Today
- Yesterday