iOS Runtime Apple iOS ऑपरेटिंग सिस्टम पर एप्लिकेशन रनटाइम वातावरण है, जिसमें Objective-C Runtime, Swift Runtime, Cocoa Touch फ्रेमवर्क और Automatic Reference Counting (ARC) के माध्यम से मेमोरी प्रबंधन तंत्र शामिल हैं। iOS Runtime डायनामिक मेथड बाइंडिंग (message passing), क्लास लोडिंग, मेमोरी प्रबंधन और iOS फ्रेमवर्क के माध्यम से हार्डवेयर के साथ इंटरैक्शन के लिए जिम्मेदार है। Apple Developer Documentation के अनुसार, प्रदर्शन अनुकूलन, डिबगिंग और स्थिर iOS एप्लिकेशन विकसित करने के लिए runtime को समझना आवश्यक है।
मुख्य बिंदु
iOS Runtime सिस्टम घटकों का एक समूह है जो iOS चलाने वाले Apple उपकरणों पर एप्लिकेशन निष्पादन सुनिश्चित करता है। इसमें Objective-C Runtime (libobjc.A.dylib लाइब्रेरी), Swift Runtime (libswiftCore.dylib), Core Foundation, Cocoa Touch फ्रेमवर्क (UIKit, Foundation), डायनामिक लोडर dyld और मेमोरी प्रबंधन, थ्रेड और इंटर-प्रोसेस संचार के लिए रनटाइम वातावरण शामिल है।
आर्किटेक्चरल रूप से, iOS Runtime तीन स्तरों पर काम करता है। सबसे निचले स्तर पर — Mach-O बाइनरी प्रारूप और dyld, जो निष्पादन योग्य फ़ाइल और लाइब्रेरी लोड करता है। मध्य स्तर — Objective-C Runtime और Swift Runtime, मेथड डिस्पैच और ऑब्जेक्ट प्रबंधन के लिए जिम्मेदार। ऊपरी स्तर — Cocoa Touch फ्रेमवर्क (UIKit, Foundation, Core Data, Metal), जो डेवलपर के लिए API प्रदान करते हैं।
iOS Runtime को समझना डेवलपर को जटिल समस्याओं को हल करने की अनुमति देता है: A/B परीक्षण और एनालिटिक्स के लिए मेथड स्विज़लिंग (Method Swizzling), डायनामिक क्लास लोडिंग, ARC को समझकर मेमोरी अनुकूलन, retain cycles और मेमोरी लीक की डिबगिंग, dyld के माध्यम से एप्लिकेशन लॉन्च समय अनुकूलन। Runtime ज्ञान के बिना, सिस्टम स्तर पर प्रोफाइलिंग और अनुकूलन असंभव है।
| घटक | लाइब्रेरी | उद्देश्य |
|---|---|---|
| Objective-C Runtime | libobjc.A.dylib | Message passing, डायनामिक क्लास, स्विज़लिंग |
| Swift Runtime | libswiftCore.dylib | Value types, generics, protocol witnesses |
| Core Foundation | CoreFoundation.framework | CFType, toll-free bridging |
| dyld | dyld (usr/lib/dyld) | Mach-O लोडिंग, लाइब्रेरी लिंकिंग |
| libSystem | libSystem.B.dylib | POSIX threads, libc, libdispatch (GCD) |
iOS के लिए एप्लिकेशन Mach-O प्रारूप (Mach Object) में कंपाइल किए जाते हैं। Mach-O फ़ाइल में हेडर, लोड कमांड और सेगमेंट होते हैं: __TEXT (कोड, कॉन्स्टेंट), __DATA (ग्लोबल वेरिएबल, Objective-C मेटाडेटा), __LINKEDIT (प्रतीक, रिलोकेशन टेबल)। dyld पहले निर्देश को निष्पादित करने से पहले Mach-O को पार्स करता है और निर्भरताएँ लोड करता है।
Objective-C Runtime iOS Runtime का सबसे शक्तिशाली हिस्सा है। अर्ली बाइंडिंग वाले C++ के विपरीत, Objective-C मैसेज पासिंग के माध्यम से लेट बाइंडिंग का उपयोग करता है। मेथड कॉल [receiver message] को सीधे फंक्शन कॉल में नहीं, बल्कि objc_msgSend(receiver, @selector(message)) में कंपाइल किया जाता है, जो ऑब्जेक्ट के क्लास में मेथड इम्प्लीमेंटेशन को डायनामिक रूप से ढूंढता है।
प्रत्येक Objective-C ऑब्जेक्ट अपने क्लास के लिए isa पॉइंटर संग्रहीत करता है। क्लास में मेथड लिस्ट, मेथड कैश और सुपरक्लास का पॉइंटर होता है। objc_msgSend वंशावली श्रृंखला को ट्रैवर्स करता है: क्लास कैश जाँचता है, फिर मेथड लिस्ट, फिर सुपरक्लास पर जाता है। यदि मेथड नहीं मिलता है, तो फ़ॉर्वर्डिंग ट्रिगर होती है: resolveInstanceMethod, forwardingTargetForSelector और forwardInvocation।
Method Swizzling एक तकनीक है जो runtime में IMP (इम्प्लीमेंटेशन पॉइंटर) के आदान-प्रदान के माध्यम से मेथड इम्प्लीमेंटेशन को तुरंत बदलने की अनुमति देती है। इसका उपयोग A/B परीक्षण, एनालिटिक्स (स्वचालित स्क्रीन ट्रैकिंग) और मॉनिटरिंग के लिए किया जाता है। बिना गंभीर आवश्यकता के प्रोडक्शन के लिए अनुशंसित नहीं है, क्योंकि यह OS अपडेट के साथ विरोध कर सकता है।
// viewDidLoad ट्रैकिंग के लिए 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 {
// इवेंट ट्रैकिंग
NSLog(@"View Did Load: %@", self.class);
// मूल इम्प्लीमेंटेशन कॉल करना
[self swizzled_viewDidLoad];
}
@end UIViewController (Tracking) श्रेणी एप्लिकेशन में सभी UIViewControllers में viewDidLoad को swizzled_viewDidLoad से बदल देती है। dispatch_once एक बार के स्विज़लिंग की गारंटी देता है। class_addMethod डबल स्विज़लिंग और सुपरक्लास के साथ विरोध को रोकता है। इसका उपयोग कंट्रोलर स्रोत कोड को संशोधित किए बिना एनालिटिक्स में स्वचालित स्क्रीन व्यू ट्रैकिंग के लिए किया जाता है।
आधुनिक iOS (arm64) में, Apple ने isa पॉइंटर को अनुकूलित किया: यह सिर्फ एक क्लास पता नहीं है, बल्कि एक बिट फ़ील्ड (non-pointer isa) है जिसमें मेमोरी प्रबंधन फ़्लैग और क्लास जानकारी होती है। Tagged pointers एक और अनुकूलन है: छोटे NSNumber, NSDate और NSString मान हीप पर ऑब्जेक्ट के रूप में नहीं, बल्कि सीधे पॉइंटर में संग्रहीत होते हैं, जिससे malloc और retain/release का ओवरहेड समाप्त हो जाता है। Tagged pointer को isa के सबसे कम महत्वपूर्ण बिट द्वारा पहचाना जाता है।
Swift Runtime Objective-C Runtime से मौलिक रूप से भिन्न है: Swift डिफ़ॉल्ट रूप से क्लास मेथड के लिए vtable और value types और एक्सटेंशन मेथड के लिए direct call के माध्यम से स्टैटिक डिस्पैच का उपयोग करता है। डायनामिक डिस्पैच केवल @objc या dynamic से चिह्नित मेथड के लिए उपयोग किया जाता है। यह Objective-C की तुलना में 40% तक प्रदर्शन सुधार प्रदान करता है।
Value types (struct, enum) Swift में Objective-C से एक मुख्य अंतर है। वे स्टैक पर या किसी अन्य ऑब्जेक्ट के अंदर संग्रहीत होते हैं, retain/release का उपयोग नहीं करते हैं और संदर्भ गणना के लिए ARC में भाग नहीं लेते हैं। Struct में isa पॉइंटर नहीं होता है और इसे objc_msgSend के माध्यम से नहीं भेजा जा सकता है। Protocol witnesses, existential containers के लिए डायनामिक डिस्पैच सक्षम करने वाले प्रोटोकॉल के लिए vtable का एक एनालॉग है।
Swift Runtime में रिफिकेशन के साथ generics (mangled symbols के माध्यम से reified generics) और string, array, dictionary, set को अनुकूलित करने के लिए COW (Copy-on-Write) भी शामिल है। कलेक्शन की प्रतिलिपि बनाते समय, वास्तविक प्रतिलिपि केवल तब होती है जब प्रतियों में से एक को संशोधित किया जाता है। यह फंक्शन के बीच कलेक्शन पास करते समय ओवरहेड को कम करता है।
import Foundation
// Swift: स्टैटिक डिस्पैच (क्लास के लिए vtable)
class Animal {
func makeSound() { print("...") } // vtable
}
class Dog: Animal {
override func makeSound() { print("Woof") } // vtable override
}
// @objc dynamic: Objective-C Runtime डिस्पैच
class Cat: Animal {
@objc dynamic override func makeSound() {
print("Meow")
} // objc_msgSend
}
// Struct — कोई runtime डिस्पैच नहीं
struct Cow {
func makeSound() { print("Moo") } // direct call
}
// Protocol with protocol witness
protocol SoundMaker {
func makeSound()
}
struct Duck: SoundMaker {
func makeSound() { print("Quack") }
}
// एक्ज़िस्टेंशियल कंटेनर का उपयोग
let soundMakers: [SoundMaker] = [Dog(), Cow(), Duck()]
for maker in soundMakers {
maker.makeSound() // protocol witness dispatch
}
// प्रदर्शन परीक्षण
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")
}उदाहरण Swift में तीन प्रकार के डिस्पैच प्रदर्शित करता है: क्लास (Dog) के लिए vtable, @objc dynamic (Cat) के लिए objc_msgSend और struct (Cow) के लिए direct call। एक्ज़िस्टेंशियल कंटेनर ([SoundMaker]) में प्रोटोकॉल विटनेस ओवरहेड जोड़ते हैं। व्यवहार में, Swift जहाँ भी संभव हो स्टैटिक डिस्पैच चुनता है, जो C के करीब प्रदर्शन प्रदान करता है।
Swift Runtime Objective-C Runtime के साथ पूर्ण संगतता के लिए डिज़ाइन किया गया है। NSObject से विरासत प्राप्त करने वाली कोई भी Swift क्लास स्वचालित रूप से Objective-C Runtime में पंजीकृत हो जाती है और objc_msgSend के माध्यम से कॉल की जा सकती है। @objc एट्रीब्यूट Swift मेथड को Objective-C से सुलभ बनाता है। स्ट्रिंग ब्रिज: Objective-C API (toll-free bridging) में पास करने पर Swift String स्वचालित रूप से NSString में ब्रिज हो जाती है।
ARC (Automatic Reference Counting) iOS में एक मेमोरी प्रबंधन प्रणाली है जो कंपाइल समय पर काम करती है। कंपाइलर (Clang) ऑब्जेक्ट लाइफ़टाइम का विश्लेषण करता है और स्वचालित रूप से retain/release/autorelease कॉल सम्मिलित करता है। डेवलपर को उन्हें मैन्युअल रूप से कॉल करने की आवश्यकता नहीं है — iOS 5 से पहले के Manual Retain-Release (MRR) के विपरीत। ARC Objective-C और Swift ऑब्जेक्ट के स्तर पर काम करता है, लेकिन value types (struct, enum) के लिए नहीं।
प्रत्येक Objective-C और Swift क्लास ऑब्जेक्ट में एक संदर्भ गणना (retain count) होती है, जो non-pointer isa के अंदर extra_rc फ़ील्ड में संग्रहीत होती है। जब कोई ऑब्जेक्ट बनाया जाता है, तो retain count = 1 होता है। retain पर काउंटर बढ़ता है, release पर घटता है। जब काउंटर 0 तक पहुँचता है, तो ऑब्जेक्ट dealloc (Objective-C) या deinit (Swift) के माध्यम से डीलोकेट हो जाता है। ARC थ्रेड-सुरक्षित है: retain/release परमाणु संचालन (OSAtomicIncrement32/OSAtomicDecrement32) का उपयोग करते हैं।
Retain cycles ARC की मुख्य समस्या है। यदि ऑब्जेक्ट A के पास B का strong संदर्भ है, और B के पास A का strong संदर्भ है, तो दोनों ऑब्जेक्ट कभी डीलोकेट नहीं होंगे क्योंकि उनकी संदर्भ गणना कभी शून्य तक नहीं पहुँचेगी। समाधान weak संदर्भ (Objective-C में __weak, Swift में weak) या unowned संदर्भ हैं। Weak संदर्भ retain count नहीं बढ़ाते हैं और ऑब्जेक्ट के डीलोकेट होने पर स्वचालित रूप से शून्य (nil) हो जाते हैं।
import Foundation
// Retain cycle उदाहरण
class Parent {
var child: Child?
deinit { print("Parent deallocated") }
}
class Child {
var parent: Parent? // strong — retain cycle बनाता है!
deinit { print("Child deallocated") }
}
var parent: Parent? = Parent()
var child: Child? = Child()
parent?.child = child
child?.parent = parent // चक्र: Parent -> Child -> Parent
parent = nil
child = nil
// deinit कॉल नहीं हुआ — मेमोरी लीक!
// समाधान: weak
class WeakChild {
weak var parent: Parent? // weak — retain count नहीं बढ़ाता
deinit { print("WeakChild deallocated") }
}
// समाधान: unowned (गारंटीड लाइफ़टाइम के लिए)
class UnownedChild {
unowned let parent: Parent
init(parent: Parent) { self.parent = parent }
deinit { print("UnownedChild deallocated") }
}
// Instruments के माध्यम से जाँच
func profileMemory() {
// 1. Instruments > Leaks चलाएँ
// 2. ऑब्जेक्ट बनाने वाली कार्रवाई करें
// 3. लीक के लिए Leaks जाँचें
// 4. Allocations में dealloc के बिना ऑब्जेक्ट खोजें
for _ in 0..<1000 {
let p = Parent()
let c = WeakChild()
p.child = c as? Child
// c.parent = p — नहीं जोड़ते, weak
}
}Parent और Child के बीच retain cycle उदाहरण: दोनों एक-दूसरे के strong संदर्भ रखते हैं, ARC काउंटर को शून्य नहीं कर सकता। समाधान Child में weak parent है। Parent के डीलोकेट होने पर weak स्वचालित रूप से शून्य हो जाता है। unowned उन मामलों के लिए है जब parent का जीवनकाल child से अधिक लंबा होने की गारंटी है (उदाहरण के लिए, viewController और view)। Retain cycles को जल्दी पता लगाने के लिए Instruments > Leaks का उपयोग करें।
Autorelease pool स्पष्ट स्वामित्व के बिना बनाए गए ऑब्जेक्ट के लिए विलंबित रिलीज़ तंत्र है। Swift और Objective-C में @autoreleasepool { } एक पूल बनाता है जो ब्लॉक के अंत में खाली हो जाता है, पूल में प्रत्येक ऑब्जेक्ट को release भेजता है। यह लूप (हज़ारों अस्थायी ऑब्जेक्ट बनाने) और RunLoop के बिना बैकग्राउंड थ्रेड पर अत्यंत महत्वपूर्ण है। UIKit RunLoop प्रत्येक पुनरावृत्ति पर मुख्य autorelease pool को स्वचालित रूप से खाली करता है।
dyld (dynamic link editor) सिस्टम लोडर है जो iOS एप्लिकेशन लॉन्च करते समय Mach-O निष्पादन योग्य फ़ाइलों और संबंधित डायनामिक लाइब्रेरी (dylib) को लोड करने के लिए जिम्मेदार है। dyld /usr/lib/dyld पर स्थित है और libSystem का हिस्सा है। लोडिंग प्रक्रिया में कई चरण शामिल हैं: Mach-O पार्सिंग, निर्भरता लोडिंग (Library Loader, LC_LOAD_DYLIB), पता रिलोकेशन (ASLR), Objective-C Runtime इनिशियलाइज़ेशन और main() को कॉल करना।
एप्लिकेशन लॉन्च समय महत्वपूर्ण रूप से dyld पर निर्भर करता है: जितनी अधिक डायनामिक लाइब्रेरी और Objective-C क्लास, उतना लंबा pre-main time। Apple +load मेथड की संख्या को कम करने की अनुशंसा करता है (वे main से पहले निष्पादित होते हैं), उन्हें +initialize (आलसी इनिशियलाइज़ेशन) से बदलें। 2020 से, Apple iOS पर प्रीबिल्ट dyld कैश का उपयोग करता है: सिस्टम लाइब्रेरी एकल कैश में प्री-लिंक की जाती हैं, जिससे लोडिंग तेज़ होती है।
import Foundation
// DYLD_PRINT_STATISTICS के माध्यम से लॉन्च समय मापना
// Xcode में: Edit Scheme > Run > Arguments > Environment Variables
// DYLD_PRINT_STATISTICS = 1
// DYLD_PRINT_STATISTICS_DETAILS = 1
// Pre-main time का प्रोग्रामेटिक मापन
@main
struct AppMain {
static func main() {
let launchStart = CFAbsoluteTimeGetCurrent()
// UIApplicationMain यहाँ होता है
AppDelegate.main()
let launchEnd = CFAbsoluteTimeGetCurrent()
let preMainTime = launchEnd - launchStart
print("Pre-main time: (preMainTime) sec")
}
}
// अनुकूलन: +load को +initialize से बदलना
class OptimizedClass {
// ❌ +load main से पहले निष्पादित होता है
// override class func load() { }
// ✅ +initialize पहली पहुँच पर निष्पादित होता है
static let shared = OptimizedClass()
private init() {
// यहाँ इनिशियलाइज़ेशन
}
}
// dylib संख्या का अनुकूलन
// स्टैटिक लाइब्रेरी का विलय LC_LOAD_DYLIB की संख्या कम करता है
// केवल उपयोग की गई Objective-C क्लास को लिंक करने के लिए -ObjC फ़्लैग का उपयोग करें
// Xcode: Build Settings > Mach-O Type > Static Librarypre-main time मापने के लिए, Xcode स्कीम में DYLD_PRINT_STATISTICS का उपयोग करें। आउटपुट कुल समय, dylib लोडिंग समय, rebase/bind समय, Objective-C सेटअप समय और इनिशियलाइज़र समय दिखाता है। लक्ष्य मान: कोल्ड स्टार्ट के लिए कुल < 400ms, वार्म स्टार्ट के लिए < 200ms। अनुकूलन: लाइब्रेरी मर्ज करना, +load को +initialize से बदलना, Objective-C क्लास की संख्या कम करना (Swift का उपयोग करें), डायनामिक फ्रेमवर्क की न्यूनतम संख्या।
dyld shared cache iOS पर प्री-लिंक्ड सिस्टम लाइब्रेरी का कैश है। सभी सिस्टम dylib (UIKit, Foundation, CoreGraphics) एक फ़ाइल में संयुक्त हैं: /System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm64। यह प्रत्येक सिस्टम लाइब्रेरी को अलग-अलग लोड करने की आवश्यकता को समाप्त करता है — dyld कैश तक पहुँचता है, जो स्टार्टअप को काफी तेज़ करता है। 10+ डायनामिक फ्रेमवर्क वाले एप्लिकेशन सबसे अधिक विलंब का अनुभव करते हैं, क्योंकि कस्टम dylib dsc में शामिल नहीं हैं।
अक्सर पूछे जाने वाले प्रश्न
iOS Runtime iOS पर एप्लिकेशन रनटाइम वातावरण है, जिसमें Objective-C Runtime (libobjc.dylib), Swift Runtime (libswiftCore.dylib), Cocoa Touch फ्रेमवर्क, dyld (डायनामिक लोडर) और ARC (मेमोरी प्रबंधन) शामिल हैं। यह Objective-C के लिए message passing, Swift के लिए स्टैटिक डिस्पैच, Mach-O फ़ाइल लोडिंग और स्वचालित मेमोरी प्रबंधन प्रदान करता है।
Objective-C Runtime लेट बाइंडिंग के साथ objc_msgSend (message passing) के माध्यम से डायनामिक बाइंडिंग का उपयोग करता है। Swift Runtime प्रदर्शन के लिए स्टैटिक डिस्पैच (क्लास के लिए vtable, struct के लिए direct call) का उपयोग करता है। @objc dynamic Swift क्लास के लिए Objective-C Runtime को सक्षम करता है। Swift struct में isa पॉइंटर नहीं है और यह retain/release का उपयोग नहीं करता है।
ARC (Automatic Reference Counting) कंपाइल-टाइम मेमोरी प्रबंधन है। Clang कंपाइलर स्वचालित रूप से retain/release कॉल सम्मिलित करता है। प्रत्येक ऑब्जेक्ट में एक संदर्भ गणना होती है; जब यह शून्य तक पहुँचती है, तो dealloc कॉल किया जाता है। Retain cycles (पारस्परिक strong संदर्भ) weak/unowned संदर्भों द्वारा रोके जाते हैं। लीक का पता लगाने के लिए Instruments > Leaks का उपयोग करें।
dyld Mach-O फ़ाइलों के लिए डायनामिक लोडर है। यह निष्पादन योग्य फ़ाइल और सभी आश्रित dylib लोड करता है, रिलोकेशन (ASLR) करता है, Objective-C Runtime को इनिशियलाइज़ करता है और main() को कॉल करता है। Pre-main time dylib और +load मेथड की संख्या पर निर्भर करता है। मापने के लिए DYLD_PRINT_STATISTICS का उपयोग करें। अनुकूलन: लाइब्रेरी मर्ज करना, +load को +initialize से बदलना।
Method Swizzling Objective-C Runtime class_getInstanceMethod और method_exchangeImplementations के माध्यम से मेथड के IMP (इम्प्लीमेंटेशन पॉइंटर) को तुरंत बदलने की तकनीक है। इसका उपयोग A/B परीक्षण, एनालिटिक्स (स्वचालित स्क्रीन ट्रैकिंग) और मॉनिटरिंग के लिए किया जाता है। बिना गंभीर आवश्यकता के प्रोडक्शन में अनुशंसित नहीं है। Swift में इसे @objc dynamic + Method Swizzling से बदला जाता है।
सारांश
हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे
IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।
यह भी पढ़ें