__bridge wird nicht für Methodenargumente benötigt?

8

Wie wir wissen, benötigen wir mit ARC ein __bridge , um eine ID in ein void * zu konvertieren:

%Vor%

So sind C-Funktionsaufrufe:

%Vor%

Ich denke, das sollte auch für die Methoden gelten, und zwar für diesen ARC in iOS 5-Lernprogramm starten gibt das folgende Beispiel an und sagt, dass __bridge benötigt wird:

%Vor%

Heute jedoch habe ich versehentlich einen __bridge bei einem Methodenaufruf in einem meiner Programme gelöscht, und der Code wurde kompiliert und ohne Probleme ausgeführt. Die __bridge im obigen Beispiel scheint unnötig zu sein:

%Vor%

Stimmt das? Ist die __bridge in diesem Fall wirklich unnötig? Oder das Entfernen ändert sich, was der Code bedeutet?

    
Terry Chang 26.01.2014, 09:07
quelle

2 Antworten

6

Dies wird in ARC-Dokumenten behandelt Abschnitt 3.3.3 (Hervorhebung von mir):

  

3.3.3 Konvertierung von beibehaltenen Objektzeigertypen in bestimmten Kontexten

     

[Anfang Apple 4.0, LLVM 3.1]

     

Wenn ein Ausdruck des beibehaltenen Objekt-Zeigertyps explizit umgewandelt wird   zu einem C-haltbaren Zeigertyp ist das Programm wie besprochen schlecht ausgebildet   oben, wenn das Ergebnis nicht sofort verwendet wird:

     
  • zum Initialisieren eines Parameters in einer Objective-C-Nachricht senden, wobei der   Der Parameter ist nicht mit dem Attribut cf_consumed oder
  • gekennzeichnet   
  • initialisiert einen Parameter in einem direkten Aufruf einer geprüften Funktion wo   Der Parameter ist nicht mit dem Attribut cf_consumed gekennzeichnet.
  •   

In Ihrem Code ist myObject ein "beibehaltener Objektzeiger". Ein "C beibehaltener Zeigertyp" enthält void* (dies ist eine etwas schlampige Definition, die sie als Platzhalter verwenden, da Core Foundation "Objekte" oft void* sind).

So kann ein ObjC-Objekt implizit in ein void* konvertiert werden, wenn es als Methodenparameter verwendet wird. In diesem Fall gibt es keine zusätzliche Speicherverwaltungssemantik (d. H. Es ist das Äquivalent von __bridge cast). Abschnitt 7.8 warnt uns, dass void* möglicherweise nicht so behandelt wird Zukunft, aber ich würde mir darüber keine Sorgen machen. Wenn es passiert, wird das Hinzufügen von __bridge trivial.

Beachten Sie, dass myObject hier nicht geschützt ist. Es liegt an Ihnen, sicherzustellen, dass es auf andere Weise beibehalten wird, bis die Animationen abgeschlossen sind, oder Sie können abstürzen.

    
Rob Napier 26.01.2014, 17:21
quelle
2

__bridge wird verwendet, um das Eigentumsrecht an Variablen / Referenzen (wie Retain-Anzahl) zu übergeben, das C-API für Ziel-C oder Ziel-C für API ist.

Gehen Sie durch Clangs Dokument :

  

Überbrückte Güsse

     

Ein überbrückter Cast ist ein Cast im C-Stil, der mit einem von drei Schlüsselwörtern versehen ist:

%Vor%      

nicht-behebbarer Zeigertyp Wenn T ein nicht zurückhaltbarer Zeigertyp ist,   Dann muss op einen beibehaltenen Objekt-Zeigertyp haben. Sonst die Besetzung   ist schlecht gebildet. Es gibt keine Eigentumsübertragung, und ARC fügt keine ein   Operationen beibehalten.       (__bridge_retained T) opt den Operanden, der den Objektzeiger-Typ beibehalten haben muss, in den Zieltyp, der sein muss   ein nicht-retainable Zeigertyp. ARC behält den Wert, vorbehaltlich der   übliche Optimierungen für lokale Werte, und der Empfänger ist verantwortlich   zum Ausbalancieren dieses +1.       (__bridge_transfer T) opt den Operanden, der einen nicht-behaltbaren Zeigertyp haben muss, auf den Zieltyp, der a sein muss   beibehaltener Objekt-Zeigertyp ARC wird den Wert am Ende freigeben   des einschließenden vollen Ausdrucks, vorbehaltlich der üblichen Optimierungen   auf lokale Werte.

     

Diese Umwandlungen werden benötigt, um Objekte in und aus zu übertragen   ARC-Kontrolle; Siehe die Begründung im Abschnitt über die Umwandlung von   zurückhaltbare Objektzeiger.

     

Verwenden Sie einen __bridge_retained oder __bridge_transfer, um nur zu überzeugen   ARC, um ein unausgeglichenes Zurückhalten bzw. Freigeben zu emittieren, ist schlecht   form.

Jetzt,

void * t = (void *) self; // FEHLER: Besetzung von ... erfordert eine überbrückte Besetzung Warum es falsch ist, weil Sie versuchen, die Referenz von Objective-C auf C zu übertragen. Es ist nicht gelungen, die Referenz zu übernehmen.

void * t = (__bridge void *) selbst; // RICHTIG Warum es richtig ist, weil Sie Ihre Ziel-C-Referenz auf C übertragen haben. Nach dem Dokument von LLVM. Siehe oben angegebene Regeln.

%Vor%

Die obigen Zeilen sind noch immer in Ordnung, weil Sie den C-Referenztypkontext anstelle von NULL

übergeben     
Tirth 26.01.2014 11:42
quelle