2015-04-03 6 views
7

एनएसएचप्टर के लेख में method swizzling पर, यह कहता है "स्विजलिंग हमेशा प्रेषण में किया जाना चाहिए।" यह आवश्यक क्यों है क्योंकि लोड प्रति वर्ग केवल एक बार होता है?विधि swizzling में dispatch_once का उपयोग

+1

महान प्रश्न: यहाँ call_load_methods() पर प्रासंगिक दस्तावेज कि सीधे संबोधित करते हैं यही कारण है कि इस तरह से सुरक्षित धागा यह है कि है। लेख में समझाया नहीं गया है और ओवरकिल की तरह लगता है। + (शून्य) लोड केवल एक बार चलाना चाहिए। मुझे कोई संसाधन नहीं मिल रहा है जिसमें काउंटर उदाहरण है। – KirkSpaziani

+0

मुझे लगता है कि यह समझाया गया है, हालांकि: * फिर से, क्योंकि तेज स्थिति वैश्विक स्थिति में बदलती है, हमें रनटाइम में हमारे लिए हर सावधानी बरतनी होगी। परमाणुता एक ऐसी सावधानी है, जैसा कि एक गारंटी है कि कोड को एक ही बार निष्पादित किया जाएगा, यहां तक ​​कि विभिन्न धागे * में भी। दौड़ की स्थितियों को रोकने के लिए यह एक और सावधानी पूर्वक कदम है क्योंकि मुझे लगता है कि 'लोड' विधि जरूरी नहीं है कि परमाणुता की गारंटी हो लेकिन 'dispatch_once' का उपयोग करके –

उत्तर

6

इसकी आवश्यकता नहीं है। +load थ्रेड-सुरक्षित और पुनर्विक्रेता होने की गारंटी है। objc-runtime-new.mm में load_images देखें:

/*********************************************************************** 
* load_images 
* Process +load in the given images which are being mapped in by dyld. 
* Calls ABI-agnostic code after taking ABI-specific locks. 
* 
* Locking: write-locks runtimeLock and loadMethodLock 
**********************************************************************/ 
const char * 
load_images(enum dyld_image_states state, uint32_t infoCount, 
      const struct dyld_image_info infoList[]) 
{ 
    BOOL found; 

    recursive_mutex_lock(&loadMethodLock); 

    // Discover load methods 
    rwlock_write(&runtimeLock); 
    found = load_images_nolock(state, infoCount, infoList); 
    rwlock_unlock_write(&runtimeLock); 

    // Call +load methods (without runtimeLock - re-entrant) 
    if (found) { 
     call_load_methods(); 
    } 

    recursive_mutex_unlock(&loadMethodLock); 

    return nil; 
} 

सूचना पुनरावर्ती म्युटेक्स, गारंटी देता है कि वह सब भार को अवरुद्ध करते हुए किया जाता है, और call_load_methods() कि यह सुनिश्चित करेंगे + लोड केवल +load के कार्यान्वयन प्रति एक बार लागू हो जाता है।

ध्यान दें कि +load कि में खास है एक प्रति वर्ग आधार है, जो कारण हैं जिनकी वजह यह swizzling के लिए पसंद किया है में से एक है पर इसके बारे में कई कार्यान्वयन नहीं हो सकता - अपने +load, साथ ही मूल +load के रूप में होने की गारंटी है बुलाया।

बोनस:

/*********************************************************************** 
* call_load_methods 
* Call all pending class and category +load methods. 
* Class +load methods are called superclass-first. 
* Category +load methods are not called until after the parent class's +load. 
* 
* This method must be RE-ENTRANT, because a +load could trigger 
* more image mapping. In addition, the superclass-first ordering 
* must be preserved in the face of re-entrant calls. Therefore, 
* only the OUTERMOST call of this function will do anything, and 
* that call will handle all loadable classes, even those generated 
* while it was running. 
* 
* The sequence below preserves +load ordering in the face of 
* image loading during a +load, and make sure that no 
* +load method is forgotten because it was added during 
* a +load call. 
* Sequence: 
* 1. Repeatedly call class +loads until there aren't any more 
* 2. Call category +loads ONCE. 
* 3. Run more +loads if: 
* (a) there are more classes to load, OR 
* (b) there are some potential category +loads that have 
*  still never been attempted. 
* Category +loads are only run once to ensure "parent class first" 
* ordering, even if a category +load triggers a new loadable class 
* and a new loadable category attached to that class. 
* 
* Locking: loadMethodLock must be held by the caller 
* All other locks must not be held. 
**********************************************************************/ 
void call_load_methods(void) 
1

मुझे लगता है कि आलेख का सुझाव है कि "स्विजलिंग + लोड में किया जाना चाहिए"। लेकिन फिर भी आप कहीं और swizzling कर सकते हैं। इस स्थिति में आपको परमाणुता के लिए एक dispatch_once में swizzling करना चाहिए। मुझे लगता है कि + लोड में भी एक dispatch_once में swizzling लपेटना अनावश्यक है।

+0

मुझे कोड दिखाएं – dengApro

संबंधित मुद्दे