iOS Runtime — Apple iOS operatsion tizimidagi ilovalarni bajarish muhiti bo'lib, Objective-C Runtime, Swift Runtime, Cocoa Touch freymvorklari va Automatic Reference Counting (ARC) orqali xotirani boshqarish mexanizmlarini o'z ichiga oladi. iOS Runtime metodlarning dinamik bog'lanishi (message passing), sinflarni yuklash, xotirani boshqarish va iOS freymvorklari orqali apparat bilan o'zaro aloqaga javobgardir. Apple Developer Documentation ga ko'ra, runteni tushunish unumdorlikni optimallashtirish, nosozliklarni tuzatish va barqaror iOS-ilovalarni ishlab chiqish uchun zarurdir.
Asosiy ma'lumotlar
iOS Runtime — Apple qurilmalarida iOS ostida ilovalarning bajarilishini ta'minlaydigan tizim komponentlari majmuidir. Objective-C Runtime (libobjc.A.dylib kutubxonasi), Swift Runtime (libswiftCore.dylib), Core Foundation, Cocoa Touch freymvorklari (UIKit, Foundation), dinamik yuklagich dyld va xotira, threadlar va jarayonlararo aloqani boshqarish uchun runten muhitini o'z ichiga oladi.
Arxitektura nuqtai nazaridan iOS Runtime uch darajada ishlaydi. Pastki darajada — Mach-O ikkilik formati va bajariladigan fayl va kutubxonalarni yuklaydigan dyld. O'rta darajada — metod dispetcherizatsiyasi va obyektlarni boshqarish uchun javobgar bo'lgan Objective-C Runtime va Swift Runtime. Yuqori darajada — dasturchi uchun API ta'minlaydigan Cocoa Touch freymvorklari (UIKit, Foundation, Core Data, Metal).
iOS Runtime ni tushunish dasturchiga murakkab vazifalarni hal qilishga imkon beradi: A/B test va analitika uchun metod swizzling (Method Swizzling), sinflarni dinamik yuklash, ARC ni tushunish orqali xotirani optimallashtirish, retain cycle va xotira oqishlarini bartaraf etish, dyld orqali ilovani ishga tushirish vaqtini optimallashtirish. Runteni bilmasdan tizim darajasida profillash va optimallashtirish mumkin emas.
| Komponent | Kutubxona | Vazifasi |
|---|---|---|
| Objective-C Runtime | libobjc.A.dylib | Message passing, dinamik sinflar, swizzling |
| Swift Runtime | libswiftCore.dylib | Value types, generics, protocol witnesses |
| Core Foundation | CoreFoundation.framework | CFType, toll-free bridging |
| dyld | dyld (usr/lib/dyld) | Mach-O yuklash, kutubxonalarni bog'lash |
| libSystem | libSystem.B.dylib | POSIX threads, libc, libdispatch (GCD) |
iOS uchun ilovalar Mach-O (Mach Object) formatiga kompilyatsiya qilinadi. Mach-O fayli sarlavha (header), yuklash buyruqlari (load commands) va segmentlardan (segments) iborat: __TEXT (kod, konstantalar), __DATA (global o'zgaruvchilar, Objective-C metama'lumotlari), __LINKEDIT (simvollar, joylashtirish jadvallari). dyld Mach-O ni tahlil qiladi va birinchi ko'rsatmani bajarishdan oldin bog'liqliklarni yuklaydi.
Objective-C Runtime — iOS Runtime-ning eng kuchli qismidir. Erta bog'lanish (early binding) bilan C++ dan farqli o'laroq, Objective-C message passing orqali kech bog'lanish (late binding) dan foydalanadi. [receiver message] metod chaqiruvi to'g'ridan-to'g'ri funksiya chaqiruvi sifatida emas, balki obyektning sinfida metodning bajarilishini dinamik ravishda topadigan objc_msgSend(receiver, @selector(message)) sifatida kompilyatsiya qilinadi.
Har bir Objective-C obyekti o'z sinfiga isa ko'rsatkichini saqlaydi. Sinf metodlar ro'yxati (method list), metod keshi (method cache) va super sinfga ko'rsatkichni o'z ichiga oladi. objc_msgSend meros zanjiri bo'ylab yuradi: sinf keshini tekshiradi, so'ngra method listni, keyin super sinfga o'tadi. Agar metod topilmasa, forward ishga tushadi: resolveInstanceMethod, forwardingTargetForSelector va forwardInvocation.
Method Swizzling — runte ichida IMP (implementation pointer) almashinuvi orqali metod bajarilishini uchishda o'zgartirish texnikasi. A/B test, analitika (ekranlarni avtomatik kuzatish) va monitoring uchun ishlatiladi. Operatsion tizim yangilanishlari bilan ziddiyatga kelishi mumkinligi sababli, zarurat bo'lmasa ishlab chiqarishda tavsiya etilmaydi.
// viewDidLoad ni kuzatish uchun Method Swizzling
#import
@implementation UIViewController (Tracking)
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class class = [self class];
SEL originalSelector = @selector(viewDidLoad);
SEL swizzledSelector = @selector(swizzled_viewDidLoad);
Method originalMethod = class_getInstanceMethod(
class, originalSelector);
Method swizzledMethod = class_getInstanceMethod(
class, swizzledSelector);
BOOL didAddMethod = class_addMethod(
class,
originalSelector,
method_getImplementation(swizzledMethod),
method_getTypeEncoding(swizzledMethod)
);
if (didAddMethod) {
class_replaceMethod(
class,
swizzledSelector,
method_getImplementation(originalMethod),
method_getTypeEncoding(originalMethod)
);
} else {
method_exchangeImplementations(
originalMethod, swizzledMethod);
}
});
}
- (void)swizzled_viewDidLoad {
// Hodisani kuzatish
NSLog(@"View Did Load: %@", self.class);
// Asl bajarilishni chaqirish
[self swizzled_viewDidLoad];
}
@end UIViewController (Tracking) kategoriyasi ilovadagi barcha UIViewController-larda viewDidLoad-ni swizzled_viewDidLoad bilan almashtiradi. dispatch_once bir martalik swizzlingni kafolatlaydi. class_addMethod ikki marta swizzling va super sinflar bilan ziddiyatlarning oldini oladi. Kontrollerlarning manba kodini o'zgartirmasdan analitikada ekranlarni avtomatik kuzatish uchun ishlatiladi.
Zamonaviy iOS da (arm64) Apple isa ko'rsatkichini optimallashtirgan: bu shunchaki sinf manzili emas, balki xotira boshqaruvi bayroqlari va sinf haqida ma'lumotni o'z ichiga olgan bit maydonidir (non-pointer isa). Tagged pointers — yana bir optimallashtirish: kichik o'lchamdagi NSNumber, NSDate va NSString qiymatlari yig'inda obyektlar sifatida emas, balki to'g'ridan-to'g'ri ko'rsatkichda saqlanadi, malloc va retain/release yuklarini bartaraf qiladi. tagged pointer isa ning eng kichik biti bilan taniladi.
Swift Runtime Objective-C Runtime-dan tubdan farq qiladi: Swift standart sifatida sinf metodlari uchun vtable va value types va extension methods uchun direct call orqali statik dispetcherizatsiyadan (static dispatch) foydalanadi. Dinamik dispetcherizatsiya (dynamic dispatch) faqat @objc yoki dynamic bilan belgilangan metodlar uchun ishlatiladi. Bu Objective-C bilan solishtirganda 40% gacha unumdorlikni oshirishni beradi.
Value types (struct, enum) Swift da — Objective-C dan asosiy farqdir. Ular stekda (stack) yoki boshqa obyekt ichida saqlanadi, retain/release ishlatmaydi va havola hisoblagichi uchun ARC da qatnashmaydi. Struct isa ko'rsatkichiga ega emas va objc_msgSend orqali yuborilmaydi. Protocol witnesses — existential container uchun dinamik dispetcherizatsiyani ta'minlaydigan protokollar uchun vtable analogidir.
Swift Runtime shuningdek generics (mangled symbols orqali reified generics) va string, array, dictionary, set optimallashtirish uchun COW (Copy-on-Write) ni o'z ichiga oladi. To'plam nusxalanganda haqiqiy nusxalash faqat nusxalardan biri o'zgartirilganda sodir bo'ladi. Bu to'plamlarni funksiyalar o'rtasida uzatishda yuklarni minimallashtiradi.
import Foundation
// Swift: statik dispetcherizatsiya (class uchun vtable)
class Animal {
func makeSound() { print("...") } // vtable
}
class Dog: Animal {
override func makeSound() { print("Woof") } // vtable override
}
// @objc dynamic: Objective-C Runtime dispatch
class Cat: Animal {
@objc dynamic override func makeSound() {
print("Meow")
} // objc_msgSend
}
// Struct — no runtime dispatch
struct Cow {
func makeSound() { print("Moo") } // direct call
}
// Protocol with protocol witness
protocol SoundMaker {
func makeSound()
}
struct Duck: SoundMaker {
func makeSound() { print("Quack") }
}
// Existential container dan foydalanish
let soundMakers: [SoundMaker] = [Dog(), Cow(), Duck()]
for maker in soundMakers {
maker.makeSound() // protocol witness dispatch
}
// Unumdorlik testi
func testDispatch() {
let dog = Dog()
let cat = Cat()
var cow = Cow()
let start = CFAbsoluteTimeGetCurrent()
for _ in 0..<1000000 {
dog.makeSound() // vtable: ~3ns
cat.makeSound() // objc_msgSend: ~15ns
cow.makeSound() // direct: ~1ns
}
let elapsed = CFAbsoluteTimeGetCurrent() - start
print("Elapsed: (elapsed) sec")
}Misol Swift da uch turdagi dispetcherizatsiyani namoyish etadi: class (Dog) uchun vtable, @objc dynamic (Cat) uchun objc_msgSend va struct (Cow) uchun direct call. Existential container ([SoundMaker]) ichidagi protocol witnesses qo'shimcha yuk qo'shadi. Amalda Swift imkon qadar statik dispetcherizatsiyani tanlaydi, C ga yaqin unumdorlikni ta'minlaydi.
Swift Runtime Objective-C Runtime bilan to'liq moslik uchun loyihalashtirilgan. NSObject dan meros oluvchi har qanday Swift sinfi avtomatik ravishda Objective-C Runtime da ro'yxatdan o'tadi va objc_msgSend orqali chaqirilishi mumkin. @objc atributi Swift metodini Objective-C dan foydalanish mumkin qiladi. String ko'prigi: Swift String Objective-C API ga uzatilganda avtomatik ravishda NSString ga ko'priklanadi (toll-free bridging).
ARC (Automatic Reference Counting) — kompilyatsiya bosqichida ishlaydigan iOS da xotira boshqaruvi tizimi. Kompilyator (Clang) obyektlarning hayot aylanishini tahlil qiladi va avtomatik ravishda retain/release/autorelease chaqiruvlarini joylashtiradi. Dasturchi ularni qo'lda chaqirishi shart emas — iOS 5 dan oldingi Manual Retain-Release (MRR) dan farqli o'laroq. ARC Objective-C obyektlari va Swift class darajasida ishlaydi, lekin value types (struct, enum) uchun emas.
Har bir Objective-C obyekti va Swift class non-pointer isa ichidagi extra_rc maydonida saqlanadigan havola hisoblagichiga (retain count) ega. Obyekt yaratilganda retain count = 1. Retain paytida hisoblagich ortadi, release paytida kamayadi. Hisoblagich 0 ga yetganda obyekt dealloc (Objective-C) yoki deinit (Swift) orqali realokatsiya qilinadi. ARC thread-safe: retain/release atomik operatsiyalardan (OSAtomicIncrement32/OSAtomicDecrement32) foydalanadi.
Retain cycles — ARC ning asosiy muammosi. Agar A obyekti B ga strong havolani, B esa A ga strong havolani saqlasa, ikkala obyekt hech qachon realokatsiya qilinmaydi, chunki ularning havola hisoblagichlari nolga tushmaydi. Yechim — zaif havolalar (__weak Objective-C da, weak Swift da) yoki unowned havolalar. Zaif havolalar retain count ni oshirmaydi va obyekt realokatsiyasida avtomatik ravishda nolga tushadi (nil).
import Foundation
// Retain cycle namunasi
class Parent {
var child: Child?
deinit { print("Parent deallocated") }
}
class Child {
var parent: Parent? // strong — retain cycle yaratadi!
deinit { print("Child deallocated") }
}
var parent: Parent? = Parent()
var child: Child? = Child()
parent?.child = child
child?.parent = parent // tsikl: Parent -> Child -> Parent
parent = nil
child = nil
// deinit CHAQIRILMAYDI — xotira oqishi!
// Tuzatish: weak
class WeakChild {
weak var parent: Parent? // weak — retain count ni oshirmaydi
deinit { print("WeakChild deallocated") }
}
// Tuzatish: unowned (kafolatlangan hayot davomiyligi uchun)
class UnownedChild {
unowned let parent: Parent
init(parent: Parent) { self.parent = parent }
deinit { print("UnownedChild deallocated") }
}
// Instruments orqali tekshirish
func profileMemory() {
// 1. Instruments > Leaks ni ishga tushiring
// 2. Obyektlar yaratuvchi harakatni bajaring
// 3. Leaks da oqishlarni tekshiring
// 4. Allocations da dealloc bo'lmagan obyektlarni toping
for _ in 0..<1000 {
let p = Parent()
let c = WeakChild()
p.child = c as? Child
// c.parent = p — QO'SHMAYMIZ, weak
}
}Parent va Child o'rtasidagi retain cycle misoli: ikkalasi bir-biriga strong havolalarni saqlaydi, ARC hisoblagichlarni nolga tushira olmaydi. Tuzatish — Child da weak parent. weak parent realokatsiyasida avtomatik ravishda nolga tushadi. unowned — parent ning hayot davomiyligi child nikidan uzoqroq bo'lgan holatlar uchun (masalan, viewController va view). Retain cycle larni erta bosqichda aniqlash uchun Instruments > Leaks dan foydalaning.
Autorelease pool — aniq egaliksiz yaratilgan obyektlar uchun kechiktirilgan release mexanizmi. Swift va Objective-C da @autoreleasepool { } blok oxirida tozalanadigan, hovuzdagi har bir obyektga release yuboradigan hovuz yaratadi. Tsikllarda (minglab vaqtinchalik obyektlarni yaratish) va RunLoop siz fon threadlarida muhim ahamiyatga ega. UIKit RunLoop har iteratsiyada asosiy autorelease hovuzini avtomatik tozalaydi.
dyld (dynamic link editor) — iOS ilovasini ishga tushirishda Mach-O bajariladigan fayllari va bog'liq dinamik kutubxonalarni (dylib) yuklash uchun mas'ul bo'lgan tizim yuklagichi. dyld /usr/lib/dyld yo'lida joylashgan va libSystem ning bir qismidir. Yuklash jarayoni bir necha bosqichni o'z ichiga oladi: Mach-O ni tahlil qilish, bog'liqliklarni yuklash (Library Loader, LC_LOAD_DYLIB), manzillarni joylashtirish (ASLR), Objective-C Runtime ni ishga tushirish va main() ni chaqirish.
Ilovani ishga tushirish vaqti (launch time) kritik ravishda dyld ga bog'liq: dinamik kutubxonalar va Objective-C sinflari qancha ko'p bo'lsa, pre-main time shuncha uzoq bo'ladi. Apple +load metodlari sonini minimallashtirishni tavsiya qiladi (ular main dan oldin bajariladi), ularni +initialize (dangasa ishga tushirish) bilan almashtirishni maslahat beradi. 2020 yildan boshlab Apple iOS da prebuilt dyld cache dan foydalanadi: tizim kutubxonalari oldindan yagona keshlangan, bu yuklashni tezlashtiradi.
import Foundation
// DYLD_PRINT_STATISTICS orqali ishga tushirish vaqtini o'lchash
// Xcode da: Edit Scheme > Run > Arguments > Environment Variables
// DYLD_PRINT_STATISTICS = 1
// DYLD_PRINT_STATISTICS_DETAILS = 1
// Pre-main time ni dasturiy o'lchash
@main
struct AppMain {
static func main() {
let launchStart = CFAbsoluteTimeGetCurrent()
// UIApplicationMain bu yerda sodir bo'ladi
AppDelegate.main()
let launchEnd = CFAbsoluteTimeGetCurrent()
let preMainTime = launchEnd - launchStart
print("Pre-main time: (preMainTime) sec")
}
}
// Optimallashtirish: +load ni +initialize bilan almashtirish
class OptimizedClass {
// ❌ +load main dan oldin bajariladi
// override class func load() { }
// ✅ +initialize birinchi murojaatda bajariladi
static let shared = OptimizedClass()
private init() {
// Ishga tushirish bu yerda
}
}
// dylib sonini optimallashtirish
// Statik kutubxonalarni birlashtirish LC_LOAD_DYLIB sonini kamaytiradi
// Faqat ishlatilgan Objective-C sinflarini ulash uchun -ObjC bayrog'idan foydalaning
// Xcode: Build Settings > Mach-O Type > Static LibraryPre-main time ni o'lchash uchun Xcode sxemasida DYLD_PRINT_STATISTICS dan foydalaning. Natija total time, dylib loading time, rebase/bind time, Objective-C setup time va initializer time ni ko'rsatadi. Maqsadli qiymatlar: sovuq ishga tushirish uchun total < 400ms, iliq ishga tushirish uchun < 200ms. Optimallashtirishlar: kutubxonalarni birlashtirish, +load ni +initialize bilan almashtirish, Objective-C sinflari sonini kamaytirish (Swift dan foydalaning), dinamik freymvorklarning minimal soni.
dyld shared cache — iOS da oldindan bog'langan tizim kutubxonalari keshi. Barcha tizim dyliblari (UIKit, Foundation, CoreGraphics) bitta faylda birlashtirilgan: /System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm64. Bu har bir tizim kutubxonasini alohida yuklash zaruratini bartaraf qiladi — dyld keshga murojaat qiladi, bu ishga tushirishni sezilarli darajada tezlashtiradi. 10+ dinamik freymvorkli ilovalar eng katta kechikishni boshdan kechiradi, chunki maxsus dyliblar dsc tarkibiga kirmaydi.
Tez-tez beriladigan savollar
iOS Runtime — iOS da ilovalarni bajarish muhiti, Objective-C Runtime (libobjc.dylib), Swift Runtime (libswiftCore.dylib), Cocoa Touch freymvorklari, dyld (dinamik yuklagich) va ARC (xotira boshqaruvi) ni o'z ichiga oladi. Objective-C uchun message passing, Swift uchun statik dispetcherizatsiya, Mach-O fayllarini yuklash va avtomatik xotira boshqaruvini ta'minlaydi.
Objective-C Runtime kech bog'lanish bilan objc_msgSend (message passing) orqali dinamik bog'lanishdan foydalanadi. Swift Runtime unumdorlik uchun statik dispetcherizatsiyadan (sinflar uchun vtable, struct uchun direct call) foydalanadi. @objc dynamic Swift sinflari uchun Objective-C Runtime ni faollashtiradi. Swift struct isa ko'rsatkichiga ega emas va retain/release ishlatmaydi.
ARC (Automatic Reference Counting) — kompilyatsiya bosqichida xotira boshqaruvi. Clang kompilyatori avtomatik ravishda retain/release chaqiruvlarini joylashtiradi. Har bir obyektning havola hisoblagichi bor, nolga tushganda dealloc chaqiriladi. Retain cycle lar (o'zaro strong havolalar) weak/unowned havolalar bilan oldini olinadi. Oqishlarni aniqlash uchun Instruments > Leaks dan foydalaning.
dyld — Mach-O fayllarining dinamik yuklagichi. Bajariladigan fayl va barcha bog'liq dyliblarni yuklaydi, joylashtirishni (ASLR) amalga oshiradi, Objective-C Runtime ni ishga tushiradi va main() ni chaqiradi. Pre-main time dyliblar soni va +load metodlariga bog'liq. O'lchash uchun DYLD_PRINT_STATISTICS dan foydalaning. Optimallashtirish: kutubxonalarni birlashtirish, +load ni +initialize bilan almashtirish.
Method Swizzling — Objective-C Runtime class_getInstanceMethod va method_exchangeImplementations orqali metodning IMP (implementation pointer) ni uchishda o'zgartirish texnikasi. A/B test, analitika (ekranlarni avtomatik kuzatish) va monitoring uchun ishlatiladi. Zarurat bo'lmasa ishlab chiqarishda tavsiya etilmaydi. Swift da @objc dynamic + Method Swizzling bilan almashtiriladi.
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.