SORU
17 Mart 2011, PERŞEMBE


Objective C Yöntemi Swizzling Tehlikeleri nelerdir?

İnsanlara yöntem swizzling tehlikeli bir uygulama olduğunu belirtiyorlar duydum. İsmi bile bir bit olduğunu sugests swizzling hile.

Method Swizzling aslında bu uygulama B. kullanın çağıracağı seçici arama kapalı kaynak sınıfların davranış genişletmek için, böylece eşleme değiştirme.

Swizzling kullanmak için karar verirken herkes yapmaya çalıştıklarını, ne için buna değer olup olmadığını bilinçli bir karar böylece riskleri resmileştirmek.

E. g.

  • Adlandırma Çarpışmalar: Eğer sınıf daha sonra eklediğiniz yöntem adını eklemek için işlevselliğini genişletir, sorunların büyük bir şekilde neden olacaktır. Makul swizzled yöntemleri belirtilerek riskini azaltmak.

CEVAP
26 Aralık 2011, PAZARTESİ


Bu gerçekten harika bir soru olduğunu düşünüyorum, ve gerçek soru ile mücadele yerine, en cevaplar sorunu etekli ve sadece swizzling kullanmayın diyor bu bir utanç.

Yöntem cızırtılı kullanarak mutfakta keskin bıçak kullanmaya benzer. Bazı insanlar kendilerini kötü kesilmiş sanırlar, çünkü keskin bıçak korkuyor, ama gerçek şu ki sharp knives are safer.

Yöntem swizzling, daha verimli, daha sürdürülebilir, daha iyi kod yazmak için kullanılabilir. Ayrıca korkunç hatalar için istismar neden olabilir.

Arka plan

Eğer desen sonuçlarının bilincinde olursak, tasarım desenleri gibi, ya kullan ya da kullanma konusunda daha bilinçli kararlar edebiliyoruz. Tekiz oldukça tartışmalı, ve iyi bir nedenle-için iyi bir örnektir; düzgün uygulamak çok zor. Birçok insan hala tekiz ama kullanmak için seçin. Aynı swizzling hakkında söylenebilir. Tam olarak her ikisi de iyi ve kötü anladıktan sonra kendi görüş oluşturmak gerekir.

Tartışma

Burada yöntem swizzling tuzaklar bazıları:

  • Yöntem swizzling atom değildir
  • Değişiklikler BM ait kod davranış
  • Olası adlandırma çatışmalar
  • Swizzling yöntemin değişkenleri değiştirir
  • Swizzles sırası önemli
  • Anlamak zor (görünüyor özyinelemeli)
  • Zor hata ayıklama için

Bu puan geçerli ve onlara yönelik yöntem swizzling anlayışımızın yanı sıra, metodoloji sonucu elde etmek için kullanılan her ikisi de geliştirebiliriz. Bir anda her birini alacağım.

Yöntem swizzling atom değildir

Yine aynı anda kullanmak için güvenli bir yöntem swizzling bir uygulama görmek istiyorum1. Aslında bu yöntem swizzling kullanmalısın olan hastaların 'inde bir sorun değildir. Genellikle, sadece bir yöntemin uygulanması değiştirmek istiyor, ve bu uygulama programın kullanım süresi boyunca kullanılacak istiyorum. Bu (void)load swizzling yöntemi yapmak gerektiği anlamına gelir. load sınıf yöntemi uygulamanız başında seri olarak yürütülür. Eğer swizzling burada yaparsanız eşzamanlılık ile herhangi bir sorun olmayacak. Eğer (void)initialize, ancak karıştırma, swizzling uygulamanızda bir yarış durumu ile bitebileceğini ve çalışma zamanı, tuhaf bir durumda olabilir.

Değişiklikler BM ait kod davranış

Bu swizzling, ama asıl önemli olan bu tür bir konudur. Amaç o kodu değiştirmek mümkün olacak. Neden bu insanlar nokta bu gibi olmak önemli bir şey, çünkü değilsin sadece bazı şeyleri değiştirmek için bir örnek NSButton değiştirmek istediğiniz şeyler için, ama bunun yerine tüm NSButton durumda uygulamanız. Bu nedenle, karıştırma dikkatli olmalı, ama tamamen önlemek için gerek yok.

Şöyle düşün... bir sınıfta bir yöntemi geçersiz kılmak ve süper sınıf yöntemini çağırmak istemiyorsanız, sorunların ortaya çıkmasına neden olabilir. Çoğu durumda, bir süper sınıf olarak adlandırılan bu yöntem, aksi belirtildiği sürece) bekliyor. Eğer swizzling bu aynı düşünce uygularsanız, en sorunları halletmişsiniz. Her zaman orijinal uygulamayı çağırabilir. Eğer varsa, muhtemelen çok fazla güvenli olması için değiştiriyorsun.

Olası adlandırma çatışmalar

Çatışmalar adlandırma olan Kakao boyunca bir sorun. Biz sık sık kategoride sınıf adları ve Yöntem adlarını önek. Ne yazık ki, adlandırma çatışmalar dilimizde veba gibi. Swizzling durumunda, rağmen, olmak zorunda değiller. Biz sadece yöntem hakkında düşünme şeklini değiştirmek için biraz swizzling gerekiyor. En swizzling gibi yapılır bu

@interface NSView : NSObject
- (void)setFrame:(NSRect)frame;
@end

@implementation NSView (MyViewAdditions)

- (void)my_setFrame:(NSRect)frame {
    // do custom work
    [self my_setFrame:frame];
}

  (void)load {
    [self swizzle:@selector(setFrame:) with:@selector(my_setFrame:)];
}

@end

Bu işleri iyi gidiyor, ama eğer my_setFrame: başka bir yerde tanımlanmış olsaydı ne olurdu? Bu sorun swizzling özgü değildir, ama yine de çalışabiliriz. Geçici olarak başka tuzaklar ele bir yararı vardır. Biz bunun yerine:

@implementation NSView (MyViewAdditions)

static void MySetFrame(id self, SEL _cmd, NSRect frame);
static void (*SetFrameIMP)(id self, SEL _cmd, NSRect frame);

static void MySetFrame(id self, SEL _cmd, NSRect frame) {
    // do custom work
    SetFrameIMP(self, _cmd, frame);
}

  (void)load {
    [self swizzle:@selector(setFrame:) with:(IMP)MySetFrame store:(IMP *)&SetFrameIMP];
}

@end

Bu biraz daha az Objective-C gibi işlev işaretçileri kullanarak beri) görünüyor olsa da, herhangi bir adlandırma çakışmalarını önler. Prensip olarak, standart swizzling olarak aynı şeyi yapıyor. Bu bir süre için tanımlanmış olan swizzling kullanan insanlar için ufak bir değişiklik olabilir, ama sonunda, daha iyi olur diye düşünüyorum. Swizzling yöntemi bu şekilde tanımlanır:

typedef IMP *IMPPointer;

BOOL class_swizzleMethodAndStore(Class class, SEL original, IMP replacement, IMPPointer store) {
    IMP imp = NULL;
    Method method = class_getInstanceMethod(class, original);
    if (method) {
        const char *type = method_getTypeEncoding(method);
        imp = class_replaceMethod(class, original, replacement, type);
        if (!imp) {
            imp = method_getImplementation(method);
        }
    }
    if (imp && store) { *store = imp; }
    return (imp != NULL);
}

@implementation NSObject (FRRuntimeAdditions)
  (BOOL)swizzle:(SEL)original with:(IMP)replacement store:(IMPPointer)store {
    return class_swizzleMethodAndStore(self, original, replacement, store);
}
@end

Swizzling yöntemin değişkenleri değiştirir

Bu benim kafamda büyük olanıdır. Bu standart yöntem swizzling yapılması gerektiğini nedeni budur. Bağımsız özgün bir yöntem uygulamaya geçti değiştiriyorsunuz. Bu gerçekleştiği yer:

[self my_setFrame:frame];

Bu hat ne yapar:

objc_msgSend(self, @selector(my_setFrame:), frame);

my_setFrame: uygulanması için çalışma zamanı kullanır. Uygulama bulunduğunda, verilen aynı argümanlarla uygulama çağırır. Bulduğu uygulama devam ediyor setFrame:, özgün uygulama ve bu aramaları, ama _cmd argüman 21* *gibi olmalıdır değil. Şimdi my_setFrame:. Orijinal uygulama hiç bir zaman alması beklenen bir argüman ile çağrıldığını. Bu hiç iyi değil.

Basit bir çözüm ve alternatif swizzling tekniği yukarıda tanımlanan-kullanın. Bağımsız değişmeden kalır!

Swizzles sırası önemli

Swizzled önemli olan sırası. setFrame: varsayarsak sadece NSView, olayların bu sırada düşünün:) tanımlanmıştır

[NSButton swizzle:@selector(setFrame:) with:@selector(my_buttonSetFrame:)];
[NSControl swizzle:@selector(setFrame:) with:@selector(my_controlSetFrame:)];
[NSView swizzle:@selector(setFrame:) with:@selector(my_viewSetFrame:)];

NSButton yöntemi swizzled olduğunda ne olur? En swizzling yerine değil emin olun. tüm görünümler için setFrame: uygulanması olacaktıryukarı çekinörnek yöntemi. Bu alışverişi uygulamaları tüm görüşlerini etkilemez böylece NSButton sınıfta yeniden tanımlamak setFrame: mevcut uygulama kullanır. Mevcut uygulama NSView tanımlanır. Aynı şeyi NSControl (NSView uygulama kullanarak) swizzling zaman ne olacak.

Bir düğmeye setFrame: çağırdığınızda, bu nedenle swizzled senin yöntemini çağırın, ve düz setFrame: yöntem aslında NSView tanımlanmış atlayın. NSControl NSView swizzled uygulamaları adlı olmayacaktır.

Ama eğer emir olsaydı ne:

[NSView swizzle:@selector(setFrame:) with:@selector(my_viewSetFrame:)];
[NSControl swizzle:@selector(setFrame:) with:@selector(my_controlSetFrame:)];
[NSButton swizzle:@selector(setFrame:) with:@selector(my_buttonSetFrame:)];

Görünüm swizzling ilk gerçekleşmediği kontrol swizzling mümkün olacakyukarı çekindoğru yöntem. Kontrol swizzling düğme swizzling önce oldu beri aynı şekilde, düğmeyukarı çekinkontrolü setFrame: swizzled uygulanması. Bu biraz kafa karıştırıcı, ama bu doğru sipariş. Nasıl şeyler bu düzeni sağlamak miyiz?

Yine, sadece 40* *şeyler karıştırma. load sen karıştırma ve yalnızca sınıf yüklenen bir değişiklik yaptığınızda, güvende olacaksın. load yöntem süper sınıf yük yöntemi alt sınıfları önce aradı olacağını garanti eder. Tam da sipariş alacağız!

Anlamak zor (görünüyor özyinelemeli)

Geleneksel olarak tanımlanan swizzled bir yöntem bakarak, gerçekten zor olanları anlat bence. Ama yukarıda swizzling yaptığımız alternatif, anlaması çok kolay. Bu, çoktan çözülmüş!

Zor hata ayıklama için

Hata ayıklama sırasında karışıklıklar bir swizzled isimleri birbirine karışmış ve her şey kafanda karmakarışık olur garip bir geri iz görmektir. Yine, alternatif uygulama bu adresleri. Açıkça backtraces işlevleri adlı görürsünüz. Hala, swizzling sabit swizzling sahip olduğunu da unutmayın çünkü hata ayıklamak için zor olabilir. Sizin kod iyi ise bunu görebilecek tek kişi olduğunu düşünüyorsan bile) belge. İyi uygulamaları takip eder ve iyi olacaksın. Çok iş parçacıklı kod hata ayıklamak için zor değil.

Sonuç

Yöntem swizzling eğer düzgün kullanılırsa güvenlidir. Yapabileceğiniz basit bir güvenlik önlemi load karıştırma sadece. Programlama konusunda pek çok tehlikeli olabilir, ama sonuçlarını anlamak, doğru bir şekilde kullanmak için izin verir.


1Yukarıda tanımlanan swizzling yöntemi kullanarak, bir şeyler eğer trambolin kullanmak olsaydı, iş parçacığı güvenli yapabilirsiniz. İki trambolin gerekir. Yöntem başlangıcında, işlev işaretçisi, store, store değişik işaret adresine kadar bükülmüş bir işlev atamak zorunda kalacak. Bu store işlev işaretçisi ayarlamak için başardık önce hangi swizzled yöntemi çağrıldı herhangi bir yarış durumu önlemek. Sonra uygulama zaten sınıfında tanımlı olmadığı durumda bir trambolin kullanın ve trambolin arama ve süper sınıf yöntemi hitap etmen gerekir. Süper uygulama swizzling arama sırası önemli değildir emin olacak kadar çok yöntemi dinamik olarak tanımlayan görünüyor.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • 3dmmfavs

    3dmmfavs

    29 Kasım 2009
  • GOTO Conferences

    GOTO Confere

    3 EKİM 2011
  • Michael Neal

    Michael Neal

    2 Mayıs 2009