Vraag Object-C's "obj performSelector" vs objc_msgSend ()?


Toen ik de broncode van Apache Cordova doorliep, kwam ik twee coderegels tegen waar ik me over verbaasde:

    //[obj performSelector:normalSelector withObject:command];
    objc_msgSend(obj,normalSelector,command);

Uit de documentatie van Apple blijkt dat er niet veel verschil is tussen deze twee methoden.

id objc_msgSend (id theReceiver, SEL theSelector, ...)  Verzendt een bericht met een eenvoudige retourwaarde naar een instantie van een klasse.

- (id) performSelector: (SEL) aSelectorwithObject: (id) anObject Stuurt een bericht naar de ontvanger met een object als het argument. (verplicht)

Wat is precies het verschil tussen deze twee methoden? In het bovenstaande geval sturen beide berichten met een object als een argument naar een ontvangend object.


10
2017-09-03 03:18


oorsprong


antwoorden:


U vraagt ​​het verschil tussen twee 'methoden', maar slechts één daarvan is eigenlijk een methode. De objc_msgSend functie is, nou ja, een functie. Geen methode.

De objc_msgSend functie is de functie die jij werkelijk aanroepen wanneer u een methode op een object in Objective C aanroept. De volgende twee zijn bijvoorbeeld in principe equivalent:

// This is what the compiler generates
objc_msgSend(obj, @selector(sel:), param);

// This is what you write
[obj sel:param];

// You can check the assembly output, they are *almost* identical!

Het grote verschil is hier objc_msgSend krijgt het type niet aangevinkt door de compiler - of tenminste, zijn argumenten krijgen geen type gecontroleerd tegen de parameter types van de selector. Dus het volgende is ongeveer hetzelfde:

[obj performSelector:normalSelector withObject:command];
objc_msgSend(obj, @selector(performSelector:withObject:),
             normalSelector, command);

Maar dat is een beetje een verspilling, want alles performSelector:withObject: doet is bellen objc_msgSend.

ECHTER: Je moet wegblijven obc_msgSend omdat het niet type-veilig is, zoals hierboven vermeld. Het enige wat de apache-ontwikkelaars doen, is het verwijderen van een enkele methode-aanroep, die je alleen erg zal maken gering prestatievoordelen in de meeste gevallen.


12
2017-09-03 03:31



De uitgetrokken regel is correct, de objc_msgSend() regel is incorrect omdat het expliciet getypt moet worden (varargs zijn soms niet compatibel met niet-varargs-functieaanroepen op sommige platforms).

In feite doen ze hetzelfde. Echt, de methodeaanroepversie is slechts een verpakking objc_msgSend().


6
2017-09-03 03:26