2016-02-18 4 views
5

के तहत एक बनाए रखा ऑब्जेक्ट प्रदान उदाहरण के लिए, की सुविधा देता है एआरसी के अंतर्गत निम्नलिखित कोड पर विचार करें:Swizzling तरीकों, कि परोक्ष एआरसी

#import <Foundation/Foundation.h> 
#import <objc/runtime.h> 

@implementation NSDate (MyEvilHack) 

+ (void)load { 
    Method originalMethod = class_getInstanceMethod(self, @selector(copyWithZone:)); 
    Method newMethod = class_getInstanceMethod(self, @selector(myCopyWithZone:)); 
    method_exchangeImplementations(originalMethod, newMethod); 
} 

- (id)myCopyWithZone:(NSZone *)zone { 
    id result = [self myCopyWithZone:zone]; 
    // do customization 
    return result; 
} 

@end 

इस कोड में, मूल copyWithZone: विधि परोक्ष है एक बनाए रखा वस्तु देता है, क्योंकि यह copy के अंतर्गत आता है विधि परिवार लेकिन मेरा myCopyWithZone: नहीं है।

मुझे दुर्घटना की उम्मीद है, लेकिन ऐसा लगता है कि यह कोड सामान्य रूप से काम करता है। बेशक, मैं भ्रम से बचने के लिए अपनी विधि का नाम बदल सकता हूं। लेकिन मैं उत्सुक हूं कि हुड के नीचे वास्तव में क्या होता है?

उत्तर

4

जैसा कि आप जानते हैं, एआरसी विधि नाम की जांच करता है, कोको स्मृति प्रबंधन नामकरण सम्मेलनों को लागू करता है, और यह निर्धारित करता है कि एक विधि का व्यवहार कैसे किया जाना चाहिए। एक विधि के लिए जो संकलन कर रहा है, यह विधि उन सम्मेलनों का पालन करता है। एक विधि के लिए जो इसे कॉल कर रहा है, यह मानता है कि विधि उन सम्मेलनों का पालन करती है।

(एक सम्मेलनों समारोह विशेषताओं का उपयोग कर ओवरराइड कर सकते हैं, लेकिन उपेक्षा है कि अब के लिए।)

जब एआरसी अपने -myCopyWithZone: संकलन है, यह निर्धारित करता है कि इस तरह के एक विधि एक +0 संदर्भ लौटना चाहिए। जब यह कॉल (स्पष्ट रूप से) -myCopyWithZone: पर कॉल करता है, तो यह मानता है कि विधि एक +0 संदर्भ देता है। उन मैच के बाद से, इसे न तो बनाए रखना चाहिए या कुछ भी जारी करना चाहिए। (ठीक है, यह अस्थायी रूप से परिणाम को बरकरार रख सकता है, लेकिन इसे एक ऑटोरेलीज के साथ संतुलित करना होगा।) परिणामस्वरूप, वास्तविक मूल संदर्भ -copyWithZone: द्वारा लौटाया गया +1 संदर्भ कॉलर तक रहता है और कॉलर +1 संदर्भ की अपेक्षा कर रहा था, तो यह सब अच्छा है।

आप शायद एआरसी को एक अलग विधि (जिसे प्रभावी ढंग से बदलकर नहीं बदला जाएगा) को कॉल करके स्क्रू कर सकता है जो +1 संदर्भ देता है। अगर इसे वापस करना था और चूंकि वर्तमान विधि से +0 संदर्भ वापस करने की उम्मीद है, तो यह इसे स्वतः ही लागू कर देगा। कॉलर इसे बनाए रखेगा क्योंकि यह +1 संदर्भ की अपेक्षा कर रहा था। तो ऑब्जेक्ट को समय-समय पर हटा दिया जाएगा, संभवतः एक दुर्घटना हो सकती है।