iOS və Android inkişafında Method Swizzling: əsas anlayışlar, texnikalar və iş prinsipi

Müəllif: IT Sectr Dərc olunub: 2026-05-17 Oxuma vaxtı: 9 dəq

Method Swizzling — runtime texnikasıdır, bu zaman sinifin iki metodunun implementasiyaları icra zamanı yerlərini dəyişir. O, alt sinif yaratmadan və mənbə kodu dəyişdirmədən sistem metodunun davranışını ləğv etməyə və ya genişləndirməyə imkan verir. Texnika ən çox Objective-C-də iOS inkişafında tətbiq tapmışdır, lakin Kotlin/Android-də reflection vasitəsilə analoqlar mövcuddur. NSHipster Guide by Mattt, 2024-ə görə, swizzling Objective-C Runtime-ın ən güclü, lakin ən təhlükəli mexanizmlərindən biridir.

Başlıca

  • Method Swizzling — sel_registerName və method_exchangeImplementations vasitəsilə runtime-da iki Objective-C metodunun implementasiyalarının mübadiləsi.
  • Objective-C Runtime objc_msgSend və dispatch table vasitəsilə dinamik dispetçerizasiya sayəsində swizzling-i təmin edir.
  • Android-də Swizzling dex-fayllarda implementasiyanın dəyişdirilməsi ilə Java Reflection və ya Gradle Transform API vasitəsilə həyata keçirilir.
  • Swizzling riskləri — kitabxanalar arasında münaqişələr, iOS yeniləmələri ilə uyğunsuzluq, metod imzalarının dəyişməsi zamanı çöküş.
  • Təhlükəsiz swizzling dispatch_once, atomarlıq və swizzled-metod daxilində orijinal implementasiyanın çağırılmasını tələb edir.

Method Swizzling nədir?

Method Swizzling — iki Objective-C metodunun implementasiyalarını icra zamanı yerlərini dəyişdirən runtime texnikasıdır. Swizzling-dən sonra originalSelector-ın çağırılması swizzledSelector kodunun icrasına gətirib çıxarır və əksinə. Bu, hər bir selektorun (SEL) icra zamanı dəyişdirilə bilən dispatch table vasitəsilə implementasiya (IMP) ilə əlaqələndirildiyi Objective-C Runtime arxitekturası sayəsində mümkündür.

«Swizzling» termini 2000-ci illərin əvvəllərində Cocoa tərtibatçıları cəmiyyətində təqdim edilmişdir. Texnika kitabxanalar sayəsində geniş tanınma qazanmışdır: AFNetworking (yükləməni izləmək üçün UIWebView swizzling), Aspects (swizzling-ə əsaslanan AOP çərçivəsi) və FLEX (yoxlama üçün sistem metodlarını swizzle edən debug aləti). Bu gün swizzling əksər iOS tətbiqlərində gizli şəkildə — monitoring və analitika kitabxanaları vasitəsilə istifadə olunur.

Swizzling-in vacib xüsusiyyəti — qobal olması: implementasiyanın dəyişdirilməsi instansiya deyil, sinif səviyyəsində baş verir. Kitabxana UIViewController.viewDidLoad metodunu swizzle edərsə, bu, sistem olanlar da daxil olmaqla tətbiqdəki BÜTÜN UIViewController instansiyalarına təsir edir. Bu eyni zamanda swizzling-in gücüdür — bir sətr kod bütöv tətbiqin davranışını dəyişdirir — və səhvlərin əsas mənbəyidir.

Objective-C-də Method Swizzling necə işləyir

Objective-C Runtime hər sinifdə dispatch table — açarın SEL (metod identifikatoru), dəyərin IMP (implementasiya funksiyasına göstərici) olduğu lüğət saxlayır. Tətbiq obyektə mesaj göndərdikdə, objc_msgSend bu cədvəldə xətti axtarış aparır. Method Swizzling bir SEL-in IMP-sini digər SEL-in IMP-si ilə əvəz edərək çağırışları yönləndirir.

objective-c
// Təhlükəsiz method swizzling-in implementasiyası
@implementation NSObject (SafeSwizzle)

+ (void)swizzleClassMethod:(SEL)original
                  with:(SEL)swizzled {
    Class cls = [self class];
    SEL originalSel = original;
    SEL swizzledSel = swizzled;

    Method originalMethod = class_getInstanceMethod(cls, originalSel);
    Method swizzledMethod = class_getInstanceMethod(cls, swizzledSel);

    method_exchangeImplementations(originalMethod, swizzledMethod);
}

@end

əsas funksiya — method_exchangeImplementations(Method, Method). O, iki Method obyektinin IMP-sini atom şəkildə dəyişir. Çağırışdan sonra sinfin dispatch table-ı dəyişir: original-a müraciət zamanı swizzled kodu, swizzled-ə müraciət zamanı isə original kodu icra olunur. SafeSwizzle kateqoriyası bu metodu bütün NSObject-ə əlavə edərək istənilən sinfə swizzling icrasına imkan verir.

Təhlükəsiz swizzling implementasiyası swizzled versiyası daxilində orijinal implementasiyanın çağırılmasını tələb edir. Əks halda metodun orijinal davranışı geri qaytarılmaz şəkildə itir. Doğru nümunə — mübadilədən əvvəl orijinal IMP-ni saxlamaq və onu swizzled-metodda çağırmaqdır:

objective-c
// Orijinal implementasiyanın çağırılması ilə swizzling
- (void)swizzled_viewDidLoad {
    // 1. Orijinal implementasiyanın çağırılması
    [self swizzled_viewDidLoad];

    // 2. Orijinal çağırışdan sonra əlavə məntiq
    NSLog("viewDidLoad yerinə yetirildi, swizzling aktivdir");
}

+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        [self swizzleClassMethod:@selector(viewDidLoad)
                            with:@selector(swizzled_viewDidLoad)];
    });
}

dispatch_once swizzling-in tətbiqin ömrü boyu dəqiq bir dəfə yerinə yetirilməsini təmin edir. Eyni metodun təkrari swizzling-i sonsuz rekursiyaya gətirib çıxaracaq: swizzled metod özünü çağıracaqlır. +load sinif runtime-a yüklənərkən çağırılır — bu, tətbiqin əsas kodundan əvvəl icra olunan swizzling üçün təhlükəsiz nöqtədir.

Dispatch table anatomiyası

Objective-C dispatch table — SEL, IMP və qaytarılan dəyər tipini ehtiva edən method_t strukturları massividir. method_exchangeImplementations sadəcə olaraq bu cədvəldə iki IMP göstəricisini dəyişir. Vacib: swizzling yalnız sinif səviyyəsində işləyir, protokol səviyyəsində yox. Metod protokolda müəyyən edilib, lakin implementasiya edilməyibsə — dispatch table swizzling üçün giriş ehtiva etmir.

Swizzling-in performansa təsiri

Swizzling-in yükü minimaldır — dispatch table-da iki IMP göstəricisinin dəyişdirilməsi bir neçə nanosaniyə çəkir. Swizzling-dən sonra metod çağırışı yavaş mır: objc_msgSend IMP-ni swizzling-dən əvvəlki kimi eyni O(1) vaxtında tapır. Yeganə əlavə əməliyyat — mübadilədən sonra ilk çağırışda method cache yoxlanılmasıdır. Apple Performance Team məlumatlarına görə, swizzling tətbiqin performansına təsir göstərmir.

iOS-da Method Swizzling tətbiqi

Method Swizzling üç əsas ssenaridə istifadə olunur: monitoring və analitika (avtomatik hadisə göndərilməsi üçün viewDidLoad, viewDidAppear-ın izlənməsi), AOP yaxalaması (metodun bütün çağırışlarının parametrlərinin qeydə alınması) və hotfix (JSPatch kimi kitabxanalar vasitəsilə App Store Review olmadan production-da xətanın düzəldilməsi).

  • Avtomatik analitika — hər bir kontrollerdə kod təkrarlanmadan screen view hadisəsi göndərmək üçün UIViewController.viewDidAppear swizzling.
  • Şəbək sorğularının qeydə alınması — üçüncü tərəf kitabxanaları da daxil olmaqla bütün HTTP sorğularını izləmək üçün NSURLSession.resume swizzling.
  • AOP (Aspect-Oriented Programming) — Aspects kitabxanası metodları swizzle edir və orijinal çağırışdan əvvəl/sonra/əvəzinə kod bloku icra edir.
  • Hotfix — tətbiqi yenidən qurmadan xətalı metodun implementasiyasının düzəldilmiş versiya ilə əvəz edilməsi (2020-dən App Review tərəfindən qadağan edilib).
  • Test və mock-lar — OCMock unit testlərdə metodları mock-implementasiyalarla əvəz etmək üçün swizzling-dən istifadə edir.

Bu ssenarilərin hər biri swizzling-in mərkəzləşdirilmiş tətbiqi sayəsində işləyir. Analitika kitabxanası +load-da bir dəfə swizzling yerinə yetirir və tətbiqdəki bütün UIViewController hadisələr göndərməyə başlayır. Tərtibatçı hər kontrollerə kod əlavə etməlidir — bu, təkrarlanmanı və səhv riskini azaldır.

Android-də Method Swizzling: reflection və bytecode manipulation

Android-də klassik Objective-C mənasında method swizzling mümkün deyil — Java/Kotlin vtable vasitəsilə statik dispetçerizasiyadan istifadə edir. Bununla belə, oxşar effekt əldə edən mexanizmlər mövcuddur: runtime-da implementasiyanı dəyişmək üçün Java Reflection və qurma mərhələsində baytkodu dəyişdirmək üçün Gradle Transform API / ASM.

kotlin
// Android-də reflection + companion object vasitəsilə swizzling
class Logger {
    companion object {
        var originalImpl: (() -> Unit)? = null
    }

    fun log() {
        println("orijinal log")
    }
}

// Runtime-da reflection ilə implementasiyanın dəyişdirilməsi
fun swizzleLog() {
    val originalMethod = Logger::class.java
        .getDeclaredMethod("log")
    originalMethod.isAccessible = true

    Logger.originalImpl = {
        originalMethod.invoke(Logger())
    }

    // Inline funksiya vasitəsilə əvəzetmə
    println("swizzled: log yaxalandı")
}

Bu kod Java Reflection vasitəsilə log() metodunun davranışını dəyişir: getDeclaredMethod özəl implementasiyaya giriş əldə edir, isAccessible giriş yoxlanılmasını söndürür. Birbaşa log() çağırışı əvəzinə əlavə məntiq yerinə yetirən sarıcı çağırılır. Lakin Android isti metodları JIT vasitəsilə optimallaşdırır — reflection artıq kompilyasiya edilmiş AOT hissələrində işləməyə bilər.

Daha etibarlı yanaşma — ASM kitabxanası ilə Gradle Transform API və ya AGP (Android Gradle Plugin) vasitəsilə bytecode manipulation. Baytkodun dəyişdirilməsi kompilyasiya mərhələsində yerinə yetirilir: ASM sinifin hər metoduna çağırışlar əlavə edir. Kod əhatə alətləri (JaCoCo) və performans monitorinqi (Firebase Performance Monitoring) belə işləyir.

Method Swizzling riskləri və best practices

Method Swizzling — yüksək riskli texnikadır. Kitabxanalar arasında münaqişələr: iki kitabxana eyni metodu swizzle edərsə, icra sırası təminat vermir. iOS yeniləmələri ilə uyğunsuzluq: Apple yeni iOS versiyasında imzanı dəyişir və ya metodu silirsə, swizzling çöküşə gətirib çıxarır. Kodda görünməmə: swizzling sinif implementasiyasında görünmür, bu da debug prosesini çətinləşdirir.

RiskTəsvirAzaldılması
Kitabxana münaqişəsiİki kitabxana viewDidAppear-ı swizzle edir — biri digərini pozurMetodun artıq swizzle olunub-olunmadığını class_getInstanceMethod ilə yoxlayın
RekursiyaEyni metodun təkrari swizzling-i sonsuz dövrə yaradırHəmişə dispatch_once istifadə edin
İmza dəyişikliyiApple yeni iOS-da metodun imzasını dəyişir — IMP uyğunsuz gəlirBütün dəstəklənən iOS versiyalarında test edin
GörünməməSwizzling Xcode çağırış stack-ində göstərilmirBütün swizzling əməliyyatlarını kodda sənədləşdirin
App ReviewApple sənədləşdirilməmiş swizzling ilə tətbiqləri rədd edirYalnız public API-lərdən istifadə edin və məqsədi sənədləşdirin

Best practices təhlükəsiz swizzling üçün aşağıdakıları əhatə edir: həmişə orijinal implementasiyanı çağırmaq, swizzling-i ciddi şəkildə +load-da dispatch_once vasitəsilə yerinə yetirmək, swizzled-metodları prefiks ilə adlandırmaq (məs. s_originalMethodName), hər swizzling əməliyyatını məqsədi göstərərək sənədləşdirmək. Aspects kitabxanası münaqişələr problemini orijinal metoddan əvvəl/sonra blokların zəncirli icrası ilə həll edir.

Müasir inkişafda Method Swizzling-ə alternativlər

Method swizzling-ə alternativlər proqnozlaşdırıla bilmə və təhlükəsizlik səbəbindən production kodu üçün üstünlük təşkil edir. Deleqatlar və protokollar (UIApplicationDelegate, UITableViewDelegate) runtime dəyişdirilmədən açıq genişlənmə nöqtələri təmin edir. Alt siniflər — viewDidAppear-ı ləğv etməklə UIViewController alt sinfinin yaradılması — proqnozlaşdırıla bilən şəkildə işləyir və münaqişələr yaratmır.

SwiftUI və Combine swizzling ehtiyacını aradan qaldırır: modifikatorlar (onAppear, onChange) metodları ləğv etmədən deklarativ şəkildə davranış əlavə edir. Android Jetpack Compose-da eyni effektə effektlər (LaunchedEffect, SideEffect) və modifikatorlar vasitəsilə nail olunur. AOP çərçivələri (Android üçün AspectJ, iOS üçün InterposeKit) compile-time weaving ilə təhlükəsiz alternativ təmin edir.

Apple WWDC 2024 məlumatlarına görə, Swift runtime dil səviyyəsində method swizzling-i dəstəkləmir — @objc dynamic metodlar yalnız Objective-C Runtime vasitəsilə swizzle edilə bilər. @objc istifadə etməyən Swift tətbiqləri üçüncü tərəf kitabxanalar tərəfindən təsadüfi swizzling-dən tam qorunur. Bu, Swift-i daha təhlükəsiz edir, lakin runtime instrumentasiya imkanlarını məhdudlaşdırır.

SwiftUI və Compose-da deklarativ alternativlər

SwiftUI modifikatorları (onAppear, onChange, onReceive) və Jetpack Compose effektləri (LaunchedEffect, SideEffect, DisposableEffect) UI tapşırıqları üçün swizzling-i tamamilə əvəz edir. Onlar dispatch table dəyişdirilmədən kəsişən davranış əlavə etmək üçün deklarativ, proqnozlaşdırıla bilən və yoxlanıla bilən üsul təmin edir. Yeni layihələrdə Apple və Google runtime yaxalaması əvəzinə məhz bu yanaşmanı tövsiyə edir.

Tez-tez verilən suallar

Method Swizzling production üçün təhlükəsizdirmi?

Method Swizzling qaydalara əməl edildikdə production üçün məqbuldur: birdəfəlik icra üçün dispatch_once, orijinal implementasiyanın çağırılması, bütün iOS versiyalarında test və sənədləşdirmə. Sadə tapşırıqlar üçün deleqatlar və ya alt siniflərdən istifadə etmək daha yaxşıdır. Production-da Swizzling monitoring və analitika kitabxanaları üçün əsaslandırılır.

Swizzling AOP-dən nə ilə fərqlənir?

Method Swizzling — dispatch table-da IMP-nin dəyişdirilməsinin konkret texnikasıdır. AOP (Aspect-Oriented Programming) — swizzling-in mexanizmlərdən biri kimi istifadə oluna biləcəyi paradiqmadır. AOP həmçinin compile-time weaving (AspectJ), proxy-əsaslı yaxalama (Spring AOP) və code generation-ı əhatə edir.

Swizzling-in yaratdığı problemləri necə debug etməli?

Bütün mesajları izləmək üçün objc_msgSend-də breakpoint istifadə edin. Sinif adı şərti ilə method_exchangeImplementations üzrə simvolik breakpoint əlavə edin. FLEX aləti sinfin hansı metodlarının swizzle edildiyini göstərir. Sistematik yoxlama üçün sinfin dispatch table-ını göstərən lldb skriptindən istifadə edin.

Swizzling Swift-də işləyirmi?

Swift dil səviyyəsində swizzling-i dəstəkləmir. Method Swizzling yalnız Objective-C Runtime vasitəsilə kompilyasiya olunan @objc dynamic ilə qeyd edilmiş metodlar üçün işləyir. Təmiz Swift metodları (@objc olmadan) statik dispetçerizasiyadan istifadə edir və swizzle edilə bilməz — onların dispatch table-ı dəyişdirilmə üçün əlçatan deyil.

Hansı iOS kitabxanaları Swizzling-dən istifadə edir?

Firebase Analytics (avtomatik ekran izlənməsi üçün viewDidAppear swizzling), Amplitude, Mixpanel, FLEX (UI yoxlaması), OHHTTPStubs (şəbək sorğularının mock edilməsi), Aspects (AOP çərçivəsi). Hamısı orijinal implementasiyanın çağırılması ilə dispatch_once vasitəsilə +load-da swizzling yerinə yetirir.

Nəticələr

  • Method Swizzling — method_exchangeImplementations vasitəsilə Objective-C Runtime dispatch table-ında iki metodun IMP-nin mübadiləsi.
  • dispatch_once təkrari swizzling və rekursiyanın qarşısını almaq üçün məcburidir.
  • Orijinal implementasiyanın çağırılması swizzled-metod daxilində — məcburi təhlükəsizlik qaydası.
  • Android-də swizzling reflection və ya Gradle Transform / ASM vasitəsilə bytecode manipulation ilə əvəz edilir.
  • Riskler — kitabxana münaqişələri, iOS versiyaları ilə uyğunsuzluq, debuggerdə görünməmə və hotfix üçün App Review qadağası.
  • Alternativlər — deleqatlar, alt siniflər, SwiftUI modifikatorları, Jetpack Compose effektləri.
  • @objc dynamic olmadan Swift metodları swizzling-dən qorunur, bu sabitliyi artırır, lakin runtime instrumentasiyanı məhdudlaşdırır.

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.

Layihəni müzakirə et

Həm də oxuyun