Sendable — ay isang Swift protocol na nagmamarka ng mga uri na ligtas para sa pagpapadala sa pagitan ng mga thread. Kapag nagtatrabaho sa concurrency (actor, async/await, Task), kinakailangan ng Swift compiler na ang lahat ng data na ipinapadala sa pagitan ng mga nakahiwalay na konteksto ay sumusunod sa Sendable. Ito ay nag-aalis ng aksidenteng pagpapadala ng mga hindi ligtas na uri na maaaring humantong sa race condition ng data. Ang protocol ay kumikilos bilang isang kontrata: isang uri na sumusunod sa Sendable ay ginagarantiyahan ang kawalan ng panloob na hindi naka-synchronize na estado. Ayon sa WWDC 2021, ang Sendable protocol ay isang mandatoryong elemento sa pagdidisenyo ng ligtas na multi-thread na arkitektura.
Mga Pangunahing
Sendable — ay isang protocol mula sa standard library ng Swift (SE-0302) na nagmamarka ng mga uri na ligtas para sa pagpapadala sa pagitan ng mga domain ng isolation. Ang domain ng isolation ay tumutukoy sa actor, Task, o @MainActor na konteksto. Ang Sendable ay hindi naglalaman ng mga kinakailangan — ito ay kumikilos bilang isang marker ng kaligtasan.
Bago ang Swift 5.5, ang mga developer ay maaaring magpadala ng anumang bagay sa pagitan ng mga thread sa pamamagitan ng DispatchQueue, at hindi sinusuri ng compiler kung ito ay ligtas. Sendable ay sumasara ng puwang na ito: ngayon ang compiler mismo ay sumusubaybay sa mga pagpapadala sa pagitan ng thread at hinaharangan ang mga hindi ligtas. Ginagawa nitong mas maaasahan ang concurrent code bago pa man ito patakbuhin.
struct UserProfile: Sendable {
let name: String
let age: Int
}
class NonSendableClass {
var counter: Int = 0
}
Sa halimbawa, ang UserProfile ay maaaring ligtas na maipadala sa pagitan ng mga thread, dahil ito ay isang istraktura na may pare-parehong mga pag-aari ng mga uri ng Sendable. Ang NonSendableClass ay magdudulot ng error sa compilation kapag sinubukang ipadala sa pamamagitan ng await o sa Task.
Mga uri ng Sendable sa Swift ay nahahati sa tatlong kategorya: mga uri ng halaga na may mga pag-aari ng Sendable, mga final na klase na may hindi nababagong estado, at mga function/pagsasara na minarkahan ng @Sendable. Awtomatikong tinutukoy ng compiler ang pagsunod sa Sendable para sa mga uri ng halaga.
Struct, enum at tuple ay awtomatikong nagiging Sendable kung ang lahat ng kanilang mga pag-aari at nauugnay na halaga ay Sendable din. Ito ay isang konserbatibong diskarte: kung kahit isang pag-aari ay hindi sumusunod sa Sendable, ang buong uri ay hindi ituturing na ligtas.
| Uri | Sendable | Kondisyon |
|---|---|---|
| Struct | Oo (walang tahasang indikasyon) | Lahat ng pag-aari ay Sendable |
| Enum | Oo (walang tahasang indikasyon) | Lahat ng associated values ay Sendable |
| Final class | Oo (may tahasang indikasyon) | Lahat ng let na pag-aari ay Sendable, walang var |
| Non-final class | Hindi | Hindi maaaring maging Sendable dahil sa mana |
Lahat ng built-in na uri ng Swift — Int, String, Double, Bool, Optional, Array, Dictionary, Set — ay sumusunod sa Sendable. Ginagawa nitong ligtas ang komposisyon ng uri bilang default. Ang developer ay kailangan lamang maging maingat sa mga custom na klase.
@unchecked Sendable — ay isang mekanismo na nagpapahintulot sa isang klase na tahasang ideklara ang sarili bilang Sendable, na lumalampas sa mga pagsusuri ng compiler. Ang developer ay umaako ng responsibilidad para sa kaligtasan ng thread ng naturang klase. Ito ay kapaki-pakinabang para sa mga tulay ng Objective-C at mga optimized na istraktura.
Ang @unchecked Sendable ay inilalapat kapag ang isang klase ay panloob na ginagarantiyahan ang kaligtasan sa pamamagitan ng mga lock o atomic na operasyon, ngunit hindi ito maaaring suriin ng compiler nang statically. Halimbawa, isang klase na may os_unfair_lock o pthread_mutex_t — ang kaligtasan ng thread nito ay sinisiguro ng code, ngunit hindi ito nakikita ng Swift.
final class AtomicCounter: @unchecked Sendable {
private var value: Int = 0
private let lock = NSLock()
func increment() {
lock.lock()
value += 1
lock.unlock()
}
}
Gamitin ang @unchecked Sendable nang maingat. Ito ay isang malinaw na senyales para sa ibang mga developer: “Sinuri ko, ito ay ligtas”. Ang isang error sa implementasyon ay maaaring humantong sa mga race condition na mahirap matukoy. Bago ilapat ang @unchecked, tiyakin na ang uri ay talagang hindi maisusulat muli bilang isang uri ng halaga.
Actor at Sendable ay dalawang panig ng parehong barya. Inihiwalay ng Actor ang estado nito, ngunit para sa pagpapalitan ng data sa labas ng mundo kailangan nitong magbalik ng mga uri ng Sendable. Kung ang isang pamamaraan ng actor ay nagbalik ng isang non-Sendable na uri, ang compiler ay naglalabas ng babala o error.
Kapag nagpapadala ang actor ng data sa panlabas na code, ang data na ito ay tumatawid sa hangganan ng isolation. Sendable ay ginagarantiyahan na ang tatanggap ay maaaring gamitin ang mga ito nang ligtas sa labas ng actor. Ang actor mismo ay nananatiling nakahiwalay — ang panloob na estado nito ay hindi nabubunyag.
struct AccountSnapshot: Sendable {
let id: UUID
let balance: Double
let lastUpdated: Date
}
actor BankActor {
private var balance: Double = 0
func snapshot() async -> AccountSnapshot {
return AccountSnapshot(
id: UUID(),
balance: balance,
lastUpdated: Date()
)
}
}
AccountSnapshot — ay isang Sendable na istraktura na naglalaman lamang ng let na mga pag-aari ng mga uri ng Sendable. Ang diskarte na ito ay best practice para sa pagkuha ng data mula sa isang actor. Ang snapshot ng estado ay ipinapadala ayon sa halaga, at hindi nawawalan ng kontrol ang actor sa estado nito.
@Sendable — ay isang attribute para sa mga function at pagsasara na ginagarantiyahan na ang pagsasara ay hindi kumukuha ng non-Sendable na data sa isang nababagong paraan. Kapag ang isang pagsasara ay ipinadala sa Task o pamamaraan ng actor, ito ay dapat na Sendable.
Sinusuri ng compiler na ang @Sendable na pagsasara ay hindi kumukuha ng nababagong mga sanggunian sa mga klase. Ang pagkuha ng let na mga pag-aari ng mga uri ng Sendable ay pinapayagan. Ang pagkuha ng var variable ng isang reference type ay magdudulot ng error, dahil ang pagsasara ay maaaring isagawa nang sabay sa mutation.
func performAsync(operation: @Sendable () -> Void) {
Task {
await operation()
}
}
let constant = "Safe"
var counter = 0
// counter — ang pagkuha ng var ay namumutate ng counter, error sa compilation
performAsync { // ❌ Mutation ng nakuhang var
print(constant)
}
Ang patakaran ay simple: ang @Sendable na pagsasara ay maaari lamang kumuha ng data na mismo ay Sendable at hindi mamumutate mula sa labas. Para sa mga klase, ang pagkuha ng weak self reference ay pinapayagan kung ang klase ay hindi minarkahan bilang Sendable. Pinipigilan nito ang mga klasikong retain cycle at race condition.
Mga Madalas Itanong
Sendable — ay isang marker na nagsasabi sa compiler: “Ang uri na ito ay maaaring ligtas na maipadala sa pagitan ng mga thread”. Ang mga istraktura at constant ay karaniwang Sendable bilang default, ang mga klase — hindi, maliban kung tahasang ipinahiwatig.
Mga uri ng halaga (struct, enum) na may mga pag-aari ng Sendable, mga final na klase na may hindi nababagong estado, pati na rin ang lahat ng pangunahing uri ng Swift: Int, String, Double, Bool, Array, Dictionary, Optional — ay awtomatikong sumusunod sa Sendable.
@unchecked Sendable — ay isang paraan upang ideklara ang isang klase bilang Sendable nang walang static na pagsusuri ng compiler. Ginagarantiyahan ng developer ang kaligtasan nang nakapag-iisa, madalas sa pamamagitan ng mga lock o atomic na operasyon.
Inihiwalay ng Actor ang estado nito, ngunit kapag nagbabalik ng data sa panlabas na code, ang data na ito ay tumatawid sa hangganan ng isolation. Sendable ay ginagarantiyahan na ang tatanggap ay hindi makakatagpo ng mga race condition kapag ginagamit ang data na ito sa labas ng actor.
Idagdag ang Sendable protocol sa isang final na klase na ang lahat ng mga pag-aari ay constant ng mga uri ng Sendable. Kung ang klase ay gumagamit ng mga lock, ang @unchecked Sendable ay maaaring ilapat, ngunit ito ay nangangailangan ng pag-iingat.
Buod
Gagawa kami ng mobile application na turnkey
Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.
Basahin din