@ScaledMetric — SwiftUI property wrapper-i, foydalanuvchining Dynamic Type sozlamalariga muvofiq raqamli qiymatni avtomatik masshtablaydi. Qiymat @ScaledMetric-ga o'raladi va tizim shrift o'lchami o'zgarganda qayta hisoblanadi, bu esa ko'rish nuqsonlari bo'lgan odamlar uchun interfeysning foydalanish imkoniyatini ta'minlaydi. Apple Developer Documentation (2026) ma'lumotlariga ko'ra, @ScaledMetric preferred content size category asosida nisbiy masshtabni hisoblash uchun UIFontMetrics shkalasidan foydalanadi. Foydalanish imkoniyati haqida batafsil SwiftUI accessibility materialida o'qing.
Asosiy fikrlar
@ScaledMetric — iOS 14 da qo'shilgan SwiftUI property wrapper-i, raqamli qiymatni (CGFloat, Int, Double) joriy Dynamic Type shrift o'lchamiga avtomatik masshtablaydi. Shriftlar uchun .font(.body) dan farqli o'laroq, @ScaledMetric har qanday raqamli parametrlarni masshtablaydi: padding, spacing, cornerRadius, iconSize — katta matnda proporsional o'sishi kerak bo'lgan hamma narsa.
@ScaledMetric ning asosiy vazifasi interfeysning matn bo'lmagan elementlarini foydalanish imkoniyati masshtablashini ta'minlashdir. Foydalanuvchi iOS sozlamalarida shriftni kattalashtirganda, tugmalar, ikonkalar va bo'shliqlar proporsional o'sishi kerak, shunda interfeys muvozanatli qoladi. @ScaledMetric bu vazifani qo'lda ko'paytuvchilarni hisoblamasdan avtomatik hal qiladi.
Asosiy sintaksis @ScaledMetric standart qiymat va ixtiyoriy relativeTo parametridan foydalanadi. Agar relativeTo ko'rsatilgan bo'lsa, masshtablash aniq matn uslubiga (UIFontTextStyle) bog'lanadi. Agar ko'rsatilmagan bo'lsa — .body shkalasi ishlatiladi.
struct AccessibleButton: View {
@ScaledMetric private var padding: CGFloat = 12
@ScaledMetric(relativeTo: .title) private var iconSize: CGFloat = 24
var body: some View {
Label("Yuborish", systemImage: "checkmark.circle.fill")
.font(.body)
.padding(padding)
.imageScale(.init(rawValue: iconSize / 24) ?? .medium)
}
}
padding .body ga nisbatan (standart), iconSize esa .title ga nisbatan masshtablanadi. Katta matnda bo'shliqlar va ikonka proporsional oshadi. @ScaledMetric bo'lmasa, bo'shliqlar har qanday shrift o'lchamida 12 pt qoladi, bu vizual muvozanatsizlikka olib keladi.
@ScaledMetric mexanizmi UIKit dan UIFontMetrics ga asoslangan. SwiftUI @ScaledMetric namunasini yaratganda, joriy preferred content size category (UIContentSizeCategory) asosida ko'paytuvchini hisoblaydi. Asosiy qiymat ko'rsatilgan matn uslubi uchun UIFontMetrics dan scaledValue ga ko'paytiriladi.
Matematik jihatdan: ScaledMetricValue = baseValue × UIFontMetrics.scaledValue(for: relativeTo). Agar relativeTo ko'rsatilmagan bo'lsa, .body ga bog'langan UIFontMetrics.default ishlatiladi. Dynamic Type o'zgarganda SwiftUI View tanasini qayta yaratadi, @ScaledMetric yangi scaledValue ni hisoblaydi va UI @State-ga o'xshash PropertyWrappers mexanizmi orqali avtomatik yangilanadi.
iOS shkalasi 11 o'lchamni o'z ichiga oladi: .extraSmall (5 pt) dan .accessibilityExtraExtraExtraLarge (77 pt .body uchun). .body uchun masshtablash koeffitsiyenti 0.85 (XS) dan 1.71 (XXXL) gacha asosiy qiymatga nisbatan o'zgaradi. @ScaledMetric aynan shu shkaladan foydalanadi, shuning uchun padding uchun 12 pt qiymati maksimal foydalanish imkoniyati o'lchamida ~20 pt bo'lishi mumkin.
| Content Size Category | Koeffitsiyent (body) | Misol @ScaledMetric(12) |
|---|---|---|
| extraSmall | 0.85 | ~10 pt |
| small | 0.93 | ~11 pt |
| medium (default) | 1.00 | 12 pt |
| large | 1.07 | ~13 pt |
| extraLarge | 1.15 | ~14 pt |
| extraExtraLarge | 1.28 | ~15 pt |
| accessibilityExtraLarge | 1.47 | ~18 pt |
| accessibilityXXXL | 1.71 | ~20 pt |
relativeTo tanlash: asosiy matn bilan bog'liq qiymatlar uchun .body (padding, spacing ro'yxatlarda), katta elementlar uchun .title (iconSize, imageSize), kichik elementlar uchun .caption (badge o'lchami) dan foydalaning. Bu elementlarning atrofdagi matn bilan uyg'un masshtablanishini ta'minlaydi.
Dynamic Type — iOS funksiyasi, foydalanuvchiga tizim shrift o'lchamini Settings → Display & Brightness → Text Size da sozlash imkonini beradi. O'zgarish barcha ilovalarga global tatbiq etiladi. @ScaledMetric bu o'zgarishga avtomatik reaksiya beradi: SwiftUI UIContentSizeCategory o'zgarganda barcha @ScaledMetric o'zgaruvchilarini yangilaydi.
Muhim: @ScaledMetric faqat raqamli qiymatlarni masshtablaydi, shriftlarni bevosita boshqarmaydi. Shriftlar uchun .font() matn uslubi bilan (.body, .title, .headline) foydalaning — SwiftUI shriftni avtomatik masshtablaydi. @ScaledMetric padding, spacing va element o'lchamlari uchun shrift masshtablashini to'ldiradi.
Canvas Preview Dynamic Type ni qo'llab-quvvatlaydi: Canvas asboblar panelida turli shrift o'lchamlarida UI ni tekshirish uchun Text Size (A–A) slayderi mavjud. @ScaledMetric bilan foydalanib, bo'shliqlar va o'lchamlarning to'g'ri masshtablanishiga ishonch hosil qiling.
struct CardView: View {
@ScaledMetric private var cornerRadius: CGFloat = 16
@ScaledMetric private var spacing: CGFloat = 8
var body: some View {
VStack(spacing: spacing) {
Text("Karta sarlavhasi")
.font(.headline)
Text("Dynamic type qo'llab-quvvatlovchi tavsif")
.font(.body)
}
.padding(spacing * 2)
.background(.regularMaterial)
.cornerRadius(cornerRadius)
}
}
struct CardView_Previews: PreviewProvider {
static var previews: some View {
CardView()
.dynamicTypeSize(.large)
.previewDisplayName("Large")
CardView()
.dynamicTypeSize(.accessibility5)
.previewDisplayName("Accessibility 5")
}
}
cornerRadius 16 pt dan maksimal foydalanish imkoniyati o'lchamida ~27 pt gacha masshtablanadi. spacing — 8 dan ~14 pt gacha. Bu kartaning har qanday shrift o'lchamida vizual muvozanatli qolishini ta'minlaydi.
Misol: Dynamic Type qo'llab-quvvatlovchi ikonka. Image(systemName:) ikonkalarining o'lchami sukut bo'yicha Dynamic Type ostida masshtablanmaydi. @ScaledMetric bu muammoni hal qiladi: joriy masshtab faktoriga asoslanib imageScale yoki frame o'lchamini o'zgartirib.
struct IconLabel: View {
let title: String
let icon: String
@ScaledMetric private var iconDimension: CGFloat = 28
@ScaledMetric(relativeTo: .body) private var spacing: CGFloat = 6
var body: some View {
HStack(spacing: spacing) {
Image(systemName: icon)
.resizable()
.frame(width: iconDimension, height: iconDimension)
Text(title)
.font(.body)
}
}
}
Misol: foydalanish mumkin bo'lgan badge-komponent. Raqamli badge matnga proporsional masshtablanishi kerak. Badge-ning minimal o'lchami uchun @ScaledMetric dumaloq badge-ning katta shriftda ko'rinadigan bo'lishini ta'minlaydi.
struct BadgeView: View {
let count: Int
@ScaledMetric(relativeTo: .caption) private var badgeSize: CGFloat = 20
@ScaledMetric(relativeTo: .caption) private var fontScale: CGFloat = 1
var body: some View {
ZStack {
Circle()
.fill(.red)
.frame(width: badgeSize, height: badgeSize)
Text("\(count)")
.font(.caption)
.foregroundColor(.white)
.scaleEffect(fontScale)
}
.fixedSize()
}
}
fontScale qo'shimcha ravishda Circle tarkibini kattalashtirilgan badgeSize ga mos masshtablaydi. fontScale bo'lmasa, badge ichidagi matn katta shriftda sig'masligi mumkin.
@ScaledMetric va @State — ikkalasi ham o'zgarishlarni kuzatuvchi property wrapper-lar, lekin turli yangilanish manbalari bilan. @State qiymatni dasturiy o'zgarishda ($stateBinding orqali) yangilaydi. @ScaledMetric qiymatni tizim Dynamic Type o'zgarganda avtomatik yangilaydi, lekin qiymatni to'g'ridan-to'g'ri koddan o'zgartirishga ruxsat bermaydi.
Asosiy farq: @ScaledMetric — dasturchi uchun read-only va tizim uchun write-only. Siz scaledValue ni setter orqali o'zgartira olmaysiz — u SwiftUI tomonidan asosiy qiymat va joriy Dynamic Type asosida hisoblanadi. @State esa, aksincha, to'liq dasturchi tomonidan boshqariladi. Agar sizga Dynamic Type ostida masshtablanadigan va dasturiy o'zgartiriladigan qiymat kerak bo'lsa — @ScaledMetric ni @State bilan birlashtiring yoki hisoblangan xususiyatdan foydalaning.
| Xususiyat | @ScaledMetric | @State |
|---|---|---|
| Yangilanish manbai | Dynamic Type (tizim) | Dasturiy (dasturchi) |
| Qiymat turi | CGFloat, Int, Double | Har qanday |
| Koddan o'zgartirish | Mumkin emas | Binding orqali mumkin |
| View-ni qayta chizish | Dynamic Type o'zgarganda | Qiymat o'zgarganda |
| iOS versiyasi | iOS 14+ | iOS 13+ |
Birlashtirilgan namuna: agar padding ni dasturiy o'zgartirish (masalan, bosish animatsiyasi) va bir vaqtning o'zida Dynamic Type ostida masshtablash kerak bo'lsa, asosiy masshtabli qiymat uchun @ScaledMetric va animatsiya ko'paytuvchisi uchun @State yarating. Yakuniy qiymat = scaledValue × animationMultiplier.
Xato 1: @ScaledMetric ni shriftlar uchun ishlatish. @ScaledMetric raqamlarni masshtablaydi, shriftlarni emas. Shriftlar uchun .font(.body) dan foydalaning — SwiftUI avtomatik Dynamic Type ni qo'llaydi. Hech qachon @ScaledMetric ni font(.system(size: scaledSize)) bilan ishlatmang — bu tizimning foydalanish imkoniyatini buzadi.
Xato 2: turli elementlar uchun relativeTo ning yo'qligi. Agar padding (.body bilan bog'liq) va iconSize (.title bilan bog'liq) bo'lsa, har biri uchun to'g'ri relativeTo ni ko'rsating. relativeTo bo'lmasa, ikkalasi ham .body bo'yicha masshtablanadi, bu ikonkaning matn kontekstiga nisbatan nomutanosib o'sishiga olib keladi.
Xato 3: ViewModel/@ObservableObject da @ScaledMetric. @ScaledMetric faqat View ichida ishlaydigan SwiftUI property wrapper-i. Uni ViewModel yoki xizmatlarda ishlatib bo'lmaydi. ViewModel da masshtablash uchun View dan masshtabli qiymatni parametr sifatida uzating yoki View da @Environment(\.sizeCategory) dan foydalaning.
@Environment(\.sizeCategory) — View da joriy Dynamic Type ni olishning muqobil usuli. Ko'proq nazorat kerak bo'lganda foydalaning: shaxsiy ko'paytuvchini hisoblash, sizeCategory ni ViewModel ga uzatish yoki moslashuvchan masshtablash uchun @ScaledMetric bilan birlashtirish.
struct CustomScaledView: View {
@Environment(\.sizeCategory) private var sizeCategory
@ScaledMetric private var basePadding: CGFloat = 12
private var extraPadding: CGFloat {
if sizeCategory >= .accessibilityLarge {
return basePadding * 0.5
}
return 0
}
var body: some View {
Text("Shaxsiy masshtabli tarkib")
.font(.body)
.padding(basePadding + extraPadding)
}
}
Qo'shimcha bo'shliq extraPadding faqat foydalanish imkoniyati o'lchamlarida qo'shiladi, asosiy @ScaledMetric mantiqini o'zgartirmasdan katta matn uchun ko'proq joy beradi.
Tez-tez beriladigan savollar
@ScaledMetric — raqamlarni masshtablash uchun rasmiy SwiftUI property wrapper-i. @ScaledFont standart API sifatida mavjud emas — bu jamiyat tomonidan amalga oshirilgan shaxsiy wrapper. Shriftlar uchun har doim o'rnatilgan .font() matn uslublari bilan (.body, .title) foydalaning, @ScaledMetric esa padding, spacing va o'lchamlar uchun.
@ScaledMetric iOS 14+, watchOS 7+, tvOS 14+ va macOS 11+ da mavjud. watchOS da Dynamic Type kichikroq diapazon bilan cheklangan — .extraSmall dan .extraLarge gacha o'lchamlar foydalanish imkoniyati o'lchamlarisiz. tvOS da Dynamic Type mavjud emas — @ScaledMetric har doim asosiy qiymatni qaytaradi.
Ha, @ScaledMetric ni sinab ko'rish uchun @ScaledMetric bilan View yarating va .environment(\.sizeCategory, .extraExtraLarge) orqali .sizeCategory environment qiymatini uzating. Keyin element o'lchamini GeometryReader yoki SwiftUI Inspector orqali oling. Shu bilan bir qatorda, alohida modulda UIFontMetrics orqali masshtablash mantiqini tekshiring.
.dynamicTypeSize — ierarxiya uchun maksimal Dynamic Type ni cheklovchi View modifier-i (masalan, .dynamicTypeSize(...large)). @ScaledMetric bu cheklovni hisobga oladi: agar .dynamicTypeSize o'rnatilgan bo'lsa, masshtabli qiymat tegishli o'lchamdan oshmaydi. Aniq nazorat uchun ikkala API ni birlashtiring.
View @ScaledMetric ni o'z ichida ishlatishiga ishonch hosil qiling (ViewModel da emas). View Dynamic Type ga obuna bo'lganligini tekshiring: @ScaledMetric avtomatik body yangilanishini chaqiradi, lekin View .equatable() yoki .id() ishlatsa, mexanizm buzilishi mumkin. Fallback sifatida @Environment(\.sizeCategory) dan foydalaning.
Xulosa
Biz kalit topshirig'i bilan mobil ilovani ishlab chiqamiz
IT Sectr 2017-yildan beri startaplar va korxonalar uchun iOS va Android ilovalarini yaratadi. Biz sizga maslahat beramiz va eng yaxshi yechimni taklif qilamiz.