Sendable — bu Swift protokoludur ki, iplər arasında ötürmə üçün təhlükəsiz olan tipləri qeyd edir. Konkurentliklə (actor, async/await, Task) işləyərkən Swift kompilyatoru tələb edir ki, izolə olunmuş kontekstlər arasında ötürülən bütün məlumatlar Sendable-ə uyğun olsun. Bu, məlumat yarışlarına səbəb ola biləcək təhlükəsiz tiplərin təsadüfi ötürməsini istisna edir. Protokol müqavilə rolunu oynayır: Sendable-ə uyğun tip daxili sinxronizasiya olunmamış vəziyyətin olmamasına zəmanət verir. WWDC 2021-ə görə, Sendable protokolu təhlükəsiz çoxiplikli arxitekturanın layihələndirilməsində məcburi elementdir.
Əsas məqamlar
Sendable — bu Swift standart kitabxanasından (SE-0302) olan protokoldur ki, izolyasiya domenləri arasında ötürmə üçün təhlükəsiz tipləri qeyd edir. İzolyasiya domeni dedikdə actor, Task tapşırığı və ya @MainActor konteksti nəzərdə tutulur. Sendable tələblər ehtiva etmir — o, təhlükəsizlik markeri rolunu oynayır.
Swift 5.5-dən əvvəl tərtibatçılar DispatchQueue vasitəsilə iplər arasında istənilən obyekti ötürə bilirdi və kompilyator bunun təhlükəsiz olub-olmadığını yoxlamırdı. Sendable bu boşluğu bağlayır: indi kompilyator özü iplərarası ötürmələri izləyir və təhlükəsiz olanları bloklayır. Bu, konkurent kodu işə salınmamışdan əvvəl daha etibarlı edir.
struct UserProfile: Sendable {
let name: String
let age: Int
}
class NonSendableClass {
var counter: Int = 0
}
Nümunədə UserProfile iplər arasında təhlükəsiz şəkildə ötürülə bilər, çünki bu, Sendable tiplərinin sabit xüsusiyyətlərinə malik strukturdur. NonSendableClass await və ya Task vasitƏlsilƏ ötürməyə cəhd etdikdə kompilyasiya xətasına səbəb olacaq.
Sendable tipləri Swift-də üç kateqoriyaya bölünür: Sendable xüsusiyyətləri olan dəyər tipləri, dəyişməz vəziyyətə malik final siniflər və @Sendable ilə qeyd olunmuş funksiyalar/bağlanmalar. Kompilyator dəyər tipləri üçün Sendable-ə uyğunluğu avtomatik çıxarır.
Struct, enum və tuple bütün xüsusiyyətləri və əlaqəli dəyərləri də Sendable olduqda avtomatik olaraq Sendable olurlar. Bu mühafizəkar yanaşmadır: əgər heç olmasa bir xüsusiyyət Sendable-ə uyğun deyilsə, bütün tip təhlükəsiz sayılmayacaq.
| Tip | Sendable | Şərt |
|---|---|---|
| Struct | Bəli (açıq göstərişsiz) | Bütün xüsusiyyətləri Sendable |
| Enum | Bəli (açıq göstərişsiz) | Bütün associated values Sendable |
| Final class | Bəli (açıq göstərişlə) | Bütün let xüsusiyyətləri Sendable, var yoxdur |
| Non-final class | Xeyr | Miras səbəbindən Sendable ola bilməz |
Swift-in bütün daxili tipləri — Int, String, Double, Bool, Optional, Array, Dictionary, Set — Sendable-ə uyğundur. Bu, tiplərin kompozisiyasını standart olaraq təhlükəsiz edir. Tərtibatçı yalnız fərdi siniflərə diqqət etməlidir.
@unchecked Sendable — bu sinifə kompilyator yoxlamalarını keçmədən özünü Sendable elan etməyə imkan verən mexanizmdir. Tərtibatçı belə bir sinfin ip təhlükəsizliyi üçün məsuliyyəti üzərinə götürür. Bu, Objective-C körpüləri və optimallaşdırılmış strukturlar üçün faydalıdır.
@unchecked Sendable sinif daxili olaraq kilidlər və ya atom əməliyyatlar vasitəsilə təhlükəsizliyi təmin etdikdə tətbiq olunur, lakin kompilyator bunu statik olaraq yoxlaya bilməz. Məsələn, os_unfair_lock və ya pthread_mutex_t olan sinif — onun ip təhlükəsizliyi kodla təmin edilir, lakin Swift bunu görmür.
final class AtomicCounter: @unchecked Sendable {
private var value: Int = 0
private let lock = NSLock()
func increment() {
lock.lock()
value += 1
lock.unlock()
}
}
@unchecked Sendable ehtiyatlı istifadə edilməlidir. Bu, digər tərtibatçılar üçün açıq siqnaldır: “Mən yoxladım, bu təhlükəsizdir”. Tətbiqdə səhv çətin aşkar olunan yarışlara səbəb ola bilər. @unchecked tətbiq etməzdən əvvəl tipin həqiqətən də dəyər tipi kimi yenidən yazıla bilməyəcəyinə əmin olmağa dəyər.
Actor və Sendable eyni medalın iki tərəfidir. Actor öz vəziyyətini izolə edir, lakin xarici dünya ilə məlumat mübadiləsi üçün Sendable tiplərini qaytarmalıdır. Əgər actor metodu Sendable olmayan tip qaytarırsa, kompilyator xəbərdarlıq və ya xəta verir.
Actor xarici koda məlumat göndərdikdə, bu məlumatlar izolyasiya sərhədini keçir. Sendable alıcının onları actor xaricində təhlükəsiz istifadə edə biləcəyinə zəmanət verir. Actor özü izolə olaraq qalır — onun daxili vəziyyəti açıqlanmır.
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 — bu, yalnız Sendable tiplərinin let xüsusiyyətlərini ehtiva edən Sendable strukturdur. Bu yanaşma actordan məlumat çıxarmaq üçün best practice-dir. Vəziyyətin anlıq görüntüsü dəyər olaraq ötürülür və actor öz vəziyyətinə nəzarəti itirmir.
@Sendable — bu funksiyalar və bağlanmalar üçün atributdur ki, bağlanmanın Sendable olmayan məlumatları dəyişdirilə bilən formada tətbiq etmədiyinə zəmanət verir. Bağlanma Task və ya actor metoduna ötürüldükdə, o, Sendable olmalıdır.
Kompilyator yoxlayır ki, @Sendable bağlanması siniflərə dəyişdirilə bilən istinadları tətbiq etmir. Sendable tiplərinin let xüsusiyyətlərinin tətbiqinə icazə verilir. İstinad tipinin var dəyişəninin tətbiqi xətaya səbəb olacaq, çünki bağlanma mutasiya ilə eyni vaxtda yerinə yetirilə bilər.
func performAsync(operation: @Sendable () -> Void) {
Task {
await operation()
}
}
let constant = "Safe"
var counter = 0
// counter — var-in tətbiqi counter-i dəyişdirir, kompilyasiya xətası
performAsync { // ❌ Tətbiq edilmiş var-in mutasiyası
print(constant)
}
Qayda sadədir: @Sendable bağlanması yalnız Sendable olan və kənardan mutasiya edilməyəcək məlumatları tətbiq edə bilər. Siniflər üçün sinif Sendable kimi qeyd olunmayıbsa, weak self zəif istinadının tətbiqinə icazə verilir. Bu, klassik retain cycle və race condition-un qarşısını alır.
Tez-tez verilən suallar
Sendable — bu kompilyatora deyən markerdir: “Bu tip iplər arasında təhlükəsiz şəkildə ötürülə bilər”. Strukturlar və sabitlər adətən standart olaraq Sendable-dır, siniflər isə açıq şəkildə göstərilməyibsə, yox.
Dəyər tipləri (struct, enum) Sendable xüsusiyyətlərilə, dəyişməz vəziyyətə malik final siniflər, həmçinin bütün Swift əsas tipləri: Int, String, Double, Bool, Array, Dictionary, Optional — avtomatik olaraq Sendable-ə uyğundur.
@unchecked Sendable — bu, kompilyatorun statik yoxlaması olmadan sinifi Sendable elan etmək üsuludur. Tərtibatçı təhlükəsizliyi müstəqil şəkildə, çox vaxt kilidlər və ya atom əməliyyatlar vasitəsilə təmin edir.
Actor öz vəziyyətini izolə edir, lakin məlumatları xarici koda qaytaran zaman bu məlumatlar izolyasiya sərhədini keçir. Sendable alıcının bu məlumatları actor xaricində istifadə edərkən yarışlarla qarşılaşmayacağına zəmanət verir.
Bütün xüsusiyyətləri Sendable tiplərinin sabitləri olan final sinifə Sendable protokolunu əlavə edin. Sinif kilidlərdən istifadə edirsə, @unchecked Sendable tətbiq oluna bilər, lakin bu ehtiyatlılıq tələb edir.
Nəticə
Açar təslim mobil tətbiq hazırlayacağıq
IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.
Həm də oxuyun