Nell'articolo di NSHipter su method swizzling, si dice "Swizzling dovrebbe sempre essere fatto in un dispatch_once". Perché è necessario poiché + il caricamento avviene solo una volta per classe?Utilizzo di dispatch_once nel metodo swizzling
risposta
Non è necessario. +load
è garantito per essere thread-safe e rientranti. Vedere load_images
in objc-runtime-new.mm
:
/***********************************************************************
* 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;
}
Avviso il mutex ricorsiva, che garantisce che tutti i carichi sono fatte durante il blocco, e farà in modo che call_load_methods()
+ carico solo ottiene invocato una volta per ogni implementazione di +load
.
noti che +load
è speciale in quanto ci possono essere più implementazioni di esso su una base per classe, che è uno dei motivi per cui è preferito per swizzling - la vostra +load
, così come l'originale +load
è garantito per essere chiamato.
Bonus: Ecco la relativa documentazione sul call_load_methods()
che si rivolge direttamente perché questo è thread-safe in modo che sia:
/***********************************************************************
* 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)
Penso che l'articolo sia suggerendo che "Swizzling dovrebbe essere fatto in + carico". Ma tu puoi ancora fare swizzling da qualche altra parte. In questa situazione dovresti fare un salto in un dispatch_once per atomicità. Penso che non sia necessario avvolgere lo swizzling anche in un dispatch_once in + load.
Mostrami il codice – dengApro
- 1. Metodo swizzling in Swift
- 2. Metodo di swizzling per "alloc"?
- 3. App Store - Metodo Swizzling Legality
- 4. Prestazioni di swizzling del metodo Objective-C
- 5. Metodo Swizzling in Android usando java
- 6. EJB: utilizzo di EntityManager nel metodo PostConstruct
- 7. Swift isa puntatore remapping o altro metodo supportato swizzling
- 8. Il mio isa-swizzling si interrompe KVO
- 9. È possibile reimpostare lo stato di dispatch_once nel test dell'unità, per farli funzionare di nuovo
- 10. Utilizzo di [metodo automatico] o @selector (metodo)?
- 11. Dispatch una volta (dispatch_once) singleton si blocca/blocca nell'obiettivo c
- 12. Utilizzo del metodo tratto nel costruttore della classe
- 13. metodo non [carico] bisogno di chiamare [carico eccellente]
- 14. Swizzling un metodo con argomenti variabili e inoltrare il messaggio - Bad Accesso
- 15. Utilizzo del metodo sys.stdout.flush()
- 16. Utilizzo di SQLite nel codeigniter
- 17. Utilizzo di FXCop nel progetto
- 18. Utilizzo di easymock nel multithreading
- 19. Utilizzo di ScriptManager nel rasoio?
- 20. Utilizzo di var all'esterno di un metodo
- 21. dispatch_once dopo la modifica dell'API Swift 3 GCD
- 22. Utilizzo di form_for tag con metodo get
- 23. Utilizzo del metodo _.debounce() di Underscore
- 24. Utilizzo di NotNull Annotation nell'argomento metodo
- 25. Utilizzo di un metodo tratto predefinito
- 26. Utilizzo di scintilla DataFrame metodo "come"
- 27. Utilizzo del metodo self-class
- 28. Utilizzo di variabili nel GPath di XmlSlurper
- 29. Utilizzo del metodo statico rispetto al metodo dell'oggetto
- 30. metodo setter nel costruttore
grande domanda. Non è spiegato nell'articolo e sembra eccessivo. Il carico + (vuoto) dovrebbe essere eseguito una sola volta. Non riesco a trovare alcuna risorsa che abbia un controesempio. – KirkSpaziani
Penso che sia spiegato, tuttavia: * Ancora una volta, poiché lo swizzling cambia stato globale, dobbiamo prendere tutte le precauzioni a nostra disposizione nel runtime. L'atomicità è una di queste precauzioni, in quanto garantisce che il codice verrà eseguito esattamente una volta, anche attraverso diversi thread *. È un altro passo precauzionale per prevenire le condizioni di gara poiché suppongo che il metodo 'load' non garantisca necessariamente l'atomicità ma usando' dispatch_once' fa –