In diesem Kapitel werden die Objective-C-Methoden viel detaillierter beschrieben als in den vorherigen Kapiteln. Dies beinhaltet eine ausführliche Erläuterung von Instanzmethoden, Klassenmethoden, wichtigen integrierten Methoden, Vererbung, Namenskonventionen und gängigen Entwurfsmustern.
Wir haben in diesem Buch sowohl mit Instanz- als auch mit Klassenmethoden gearbeitet, aber nehmen wir uns einen Moment Zeit, um die zwei Hauptkategorien von Methoden in Objective-C zu formalisieren:
Wie wir oft gesehen haben, werden Instanzmethoden vor dem Methodennamen durch einen Bindestrich gekennzeichnet, während Klassenmethoden ein Pluszeichen vorangestellt ist. Nehmen wir zum Beispiel eine vereinfachte Version von unserem Person.h
Datei:
@Interface Person: NSObject @Eigenschaft (Kopie) NSString * Name; - (nichtig) sagen hallo; + (Person *) personWithName: (NSString *) name; @Ende
Den entsprechenden Implementierungsmethoden muss ebenfalls ein Bindestrich oder ein Pluszeichen vorangestellt werden. Also ein Minimum Person.m
könnte ungefähr so aussehen:
#import "Person.h" @implementation Person @synthesize name = _name; - (void) sayHello NSLog (@ "HELLO"); + (Person *) personWithName: (NSString *) name person * person = [[Personenzuweisung] init]; person.name = name; Rückkehr Person; @Ende
Das sag Hallo
Methode kann mit aufgerufen werden Instanzen des Person
Klasse, während die personWithName
Methode kann nur von der Klasse selbst aufgerufen werden:
Person * p1 = [person personWithName: @ "Frank"]; // Klassenmethode. [p1 sayHello]; // Instanzmethode.
Das meiste davon sollte Ihnen inzwischen bekannt sein, aber jetzt haben wir die Gelegenheit, über einige der einzigartigen Konventionen in Objective-C zu sprechen.
In jeder objektorientierten Umgebung ist es wichtig, auf Methoden der übergeordneten Klasse zugreifen zu können. Objective-C verwendet ein sehr ähnliches Schema wie C #, mit Ausnahme von Base
, es verwendet das Super
Stichwort. Zum Beispiel die folgende Implementierung von sag Hallo
würde anzeigen HALLO
im Ausgabebereich und rufen Sie die Version der übergeordneten Klasse von auf sag Hallo
:
- (void) sayHello NSLog (@ "HELLO"); [super sayHello];
Im Gegensatz zu C # müssen Überschreibungsmethoden nicht explizit als solche markiert werden. Sie werden das mit beiden sehen drin
und Dealloc
Methoden, die im folgenden Abschnitt erläutert werden. Obwohl diese auf der definiert sind NSObject
Klasse, beschwert sich der Compiler nicht, wenn Sie Ihre eigene erstellen drin
und Dealloc
Methoden in Unterklassen.
Initialisierungsmethoden sind für alle Objekte erforderlich. Ein neu zugewiesenes Objekt wird erst dann als "einsatzbereit" betrachtet, wenn eine seiner Initialisierungsmethoden aufgerufen wurde. Hier können Standardwerte für Instanzvariablen festgelegt und der Status des Objekts festgelegt werden. Das NSObject
Klasse definiert einen Standard drin
Eine Methode, die nichts tut, aber es ist oft nützlich, eine eigene zu erstellen. Zum Beispiel ein Brauch drin
Implementierung für unsere Schiff
class kann einer aufgerufenen Instanzvariablen Standardwerte zuweisen _Munition
:
- (id) init self = [super init]; if (selbst) _ammo = 1000; return self;
Dies ist der kanonische Weg, um einen Brauch zu definieren drin
Methode. Das selbst
Schlüsselwort ist das Äquivalent von C # diese
-es wird verwendet, um auf die Instanz zu verweisen, die die Methode aufruft, wodurch ein Objekt Nachrichten an sich selbst senden kann. Wie du siehst, alles drin
Methoden sind erforderlich, um die Instanz zurückzugeben. Dies macht es möglich, die [[Schiffszuteilung] init]
Syntax, um die Instanz einer Variablen zuzuweisen. Beachten Sie auch, dass die NSObject
Schnittstelle erklärt die drin
Methode ist es nicht erforderlich, eine drin
Erklärung an Ship.h
.
Während einfach drin
Methoden wie die im vorherigen Beispiel gezeigte sind zum Festlegen von Werten für Standardinstanzvariablen nützlich. Es ist oft praktischer, Parameter an eine Initialisierungsmethode zu übergeben:
- (id) initWithAmmo: (unsigned int) theAmmo self = [super init]; if (selbst) _ammo = theAmmo; return self;
Wenn Sie aus einem C # -Hintergrund kommen, können Sie sich mit dem initWithAmmo
Methodenname. Sie würden wahrscheinlich erwarten, das zu sehen Munition
Parameter getrennt vom tatsächlichen Methodennamen wie void init (uint ammo)
; Die Benennung von Objective-C-Methoden basiert jedoch auf einer völlig anderen Philosophie.
Es sei daran erinnert, dass Objective-C das Ziel hat, eine API so beschreibend wie möglich zu machen, um sicherzustellen, dass absolut keine Verwirrung darüber besteht, was ein Methodenaufruf tun soll. Man kann sich eine Methode nicht als eine von ihren Parametern getrennte Einheit vorstellen - sie ist eine einzelne Einheit. Diese Entwurfsentscheidung spiegelt sich tatsächlich in der Implementierung von Objective-C wider, wobei zwischen einer Methode und ihren Parametern nicht unterschieden wird. Intern ist ein Methodenname eigentlich der verkettete Parameterliste.
Betrachten Sie zum Beispiel die folgenden drei Methodendeklarationen. Beachten Sie, dass die zweite und dritte Methode keine integrierten Methoden von sind NSObject
, so du tun Sie müssen sie der Klassenschnittstelle hinzufügen, bevor Sie sie implementieren.
- (id) init; - (id) initWithAmmo: (unsigned int) theAmmo; - (id) initWithAmmo: (unsigned int) theAmmo-Kapitän: (Person *) theCaptain;
Das sieht zwar nach Methodenüberladung aus, technisch gesehen jedoch nicht. Dies sind keine Variationen der drin
method - Sie sind alle völlig unabhängige Methoden mit unterschiedlichen Methodennamen. Die Namen dieser Methoden lauten wie folgt:
init initWithAmmo: initWithAmmo: Kapitän:
Dies ist der Grund, warum Sie Notationen sehen indexOfObjectWithOptions: durchlassenTest:
und indexOfObjectAtIndexes: Optionen: ÜbergebenTest:
für den Verweis auf Methoden in der offiziellen Objective-C-Dokumentation (entnommen aus NSArray).
Aus praktischer Sicht bedeutet dies, dass der erste Parameter Ihrer Methoden immer durch den "primären" Methodennamen beschrieben werden sollte. Mehrdeutige Methoden wie die folgenden werden von Objective-C-Programmierern im Allgemeinen missbilligt:
- (id) shoot: (Schiff *) aShip;
Verwenden Sie stattdessen eine Präposition, um den ersten Parameter wie folgt in den Methodennamen aufzunehmen:
- (id) shootOtherShip: (Ship *) aShip;
Beides eingeschlossen OtherShip
und ein Schiff
in der Methodendefinition mag überflüssig erscheinen, bedenken Sie jedoch, dass die ein Schiff
Argument wird nur intern verwendet. Jemand, der die Methode aufruft, wird so etwas schreiben shootOtherShip: discoveryOne
, woher discoveryOne
ist die Variable, die das Schiff enthält, das Sie abschießen möchten. Dies ist genau die Art von Ausführlichkeit, die die Entwickler von Objective-C anstreben.
In Ergänzung zu drin
Methode zur Initialisierung Instanzen, Objective-C bietet auch eine Möglichkeit zum Einrichten Klassen. Bevor Klassenmethoden aufgerufen oder Objekte instanziiert werden, ruft die Objective-C-Laufzeitumgebung die initialisieren
Klassenmethode der betreffenden Klasse. Dadurch haben Sie die Möglichkeit, statische Variablen zu definieren, bevor die Klasse verwendet wird. Einer der häufigsten Anwendungsfälle hierfür ist das Einrichten von Singletons:
statisches Schiff * _sharedShip; + (void) initialize if (self == [Schiffsklasse]) _sharedShip = [[selbstzuteilen] init]; + (Schiff *) sharedShip return _sharedShip;
Vor dem ersten mal [Schiff sharedShip]
aufgerufen wird, wird die Laufzeit aufgerufen [Schiff initialisieren]
, Dadurch wird sichergestellt, dass das Singleton definiert ist. Der statische Variablenmodifizierer erfüllt den gleichen Zweck wie in C # - er erstellt statt einer Instanzvariablen eine Variable auf Klassenebene. Das initialisieren
Die Methode wird nur einmal aufgerufen. Sie wird jedoch für alle übergeordneten Klassen aufgerufen. Daher müssen Sie darauf achten, Variablen auf Klassenebene nicht mehrmals zu initialisieren. Deshalb haben wir die aufgenommen self == [Schiffsklasse]
bedingt, um sicherzustellen, _shareShip
wird nur im vergeben Schiff
Klasse.
Beachten Sie auch, dass innerhalb einer Klassenmethode die selbst
Schlüsselwort bezieht sich auf die Klasse selbst, nicht auf eine Instanz. So, [selbstzuteilen]
im letzten Beispiel ist das Äquivalent von [Schiffszuteilung]
.
Das logische Gegenstück zur Initialisierungsmethode einer Instanz ist das Dealloc
Methode. Diese Methode wird für ein Objekt aufgerufen, wenn der Referenzzähler null erreicht und der zugrunde liegende Speicher freigegeben wird.
Wenn Sie die manuelle Speicherverwaltung verwenden (nicht empfohlen), müssen Sie alle Instanzvariablen freigeben, die Ihr Objekt in der Datenbank zugewiesen hat Dealloc
Methode. Wenn Sie keine Instanzvariablen freigeben, bevor Ihr Objekt den Gültigkeitsbereich verlässt, hängen Zeiger auf Ihre Instanzvariablen, was bedeutet, dass Speicherplatz verloren geht, wenn eine Instanz der Klasse freigegeben wird. Zum Beispiel, wenn unser Schiff
Klasse hat eine aufgerufene Variable zugewiesen _Gewehr
in seinem drin
Methode, müssten Sie es in freigeben Dealloc
. Dies wird im folgenden Beispiel gezeigt (Gun.h
enthält eine leere Schnittstelle, die einfach das definiert Gewehr
Klasse):
#import "Ship.h" #import "Gun.h" @implementation Ship BOOL _gunIsReady; Gun * _gun; - (id) init self = [super init]; if (selbst) _gun = [[Gun all] init]; return self; - (void) dealloc NSLog (@ "Ein Schiff ausloten"); [_gun release]; [Super Dealloc]; @Ende
Du kannst das ... sehen Dealloc
Methode in Aktion durch Erstellen eines Schiff
und freigeben, wie so:
int main (int argc, const char * argv []) @autoreleasepool ship * ship = [[Schiffszuteilung] init]; [Schiffsautorelease]; NSLog (@ "Schiff sollte noch in Autoreleasepool vorhanden sein"); NSLog (@ "Schiff sollte jetzt freigegeben werden"); 0 zurückgeben;
Dies zeigt auch, wie automatisch freigegebene Objekte funktionieren. Das Dealloc
Methode wird nicht bis zum Ende der aufgerufen @ autoreleasepool
blockieren, so dass der vorherige Code Folgendes ausgeben sollte:
Schiff sollte noch in autoreleasepool vorhanden sein. Die Aufhebung der Zuweisung eines Schiffs sollte bereits aufgehoben werden
Beachten Sie, dass der erste NSLog ()
Nachricht in Main()
wird angezeigt Vor der in der Dealloc
Methode, obwohl es aufgerufen wurde nach dem das Autorelease
Anruf.
Wenn Sie jedoch die automatische Referenzzählung verwenden, werden alle Ihre Instanzvariablen automatisch freigegeben und [super dealloc]
wird auch für Sie angerufen (Sie sollten es niemals explizit nennen). Das einzige, worüber Sie sich Sorgen machen müssen, sind Nicht-Objekt-Variablen wie Puffer, die mit C erstellt wurden Malloc ()
.
Mögen drin
, Sie müssen nicht ein implementieren Dealloc
Methode, wenn Ihr Objekt vor der Freigabe keine besondere Behandlung benötigt. Dies ist häufig der Fall für automatische Referenzzählungsumgebungen.
Eine große Hürde für C # -Entwickler, die zu Objective-C wechseln, ist der offensichtliche Mangel an privaten Methoden. Im Gegensatz zu C # sind alle Methoden in einer Objective-C-Klasse für Dritte zugänglich. es ist jedoch möglich emulieren, nacheifern das Verhalten privater Methoden.
Denken Sie daran, dass Clients nur die Schnittstelle einer Klasse (d. H. Der Header-Dateien) importieren. Sie sollten niemals die zugrunde liegende Implementierung sehen. Also, indem Sie neue Methoden in die Implementierung Datei ohne sie in die Schnittstelle, Wir können Methoden effektiv vor anderen Objekten verbergen. Dies ist zwar eher konventionell als "echte" private Methoden, aber im Wesentlichen die gleiche Funktionalität: Der Aufruf einer Methode, die nicht in einer Schnittstelle deklariert ist, führt zu einem Compiler-Fehler.
Versuch, eine "private" Methode aufzurufenAngenommen, Sie mussten ein privates hinzufügen prepareToShoot
Methode zum Schiff
Klasse. Alles was Sie tun müssen, ist es wegzulassen Ship.h
beim Hinzufügen zu Ship.m
:
// Ship.h @Interface Ship: NSObject @property (schwach) Person * Kapitän; - (nichtig) schießen; @Ende
Dies deklariert eine aufgerufene öffentliche Methode schießen
, die das private nutzen wird prepareToShoot
Methode. Die entsprechende Implementierung könnte ungefähr so aussehen:
// Ship.m #import "Ship.h" @implementation Ship BOOL _gunIsReady; @synthesize captain = _captain; - (void) schießen if (! _gunIsReady) [self preparToShoot]; _gunIsReady = YES; NSLog (@ "Abfeuern!"); - (void) preparToShoot // Einige private Funktionen ausführen. NSLog (@ "Hauptwaffe vorbereiten ..."); @Ende
Ab Xcode 4.3 können Sie private Methoden definieren irgendwo in der Umsetzung. Wenn Sie die private Methode verwenden, bevor der Compiler sie gesehen hat (wie im vorherigen Beispiel), überprüft der Compiler den Rest des Implementierungsblocks für die Methodendefinition. Vor Xcode 4.3 mussten Sie entweder eine private Methode definieren Vor es wurde an anderer Stelle in der Datei verwendet oder mit einem Weiterleiten deklariert Klassenerweiterung.
Klassenerweiterungen sind ein Spezialfall von Kategorien, welche im nächsten Kapitel vorgestellt werden. So wie es nicht möglich ist, eine Methode als privat zu kennzeichnen, gibt es keine Möglichkeit, eine Methode als geschützt zu kennzeichnen. Wie wir im nächsten Kapitel sehen werden, bieten Kategorien jedoch eine leistungsstarke Alternative zu geschützten Methoden.
Selektoren sind die Methode von Objective-C, Methoden darzustellen. Mit ihnen können Sie dynamisch eine der Methoden eines Objekts auswählen, um zur Laufzeit auf eine Methode zu verweisen, eine Methode an eine andere Funktion zu übergeben und herauszufinden, ob ein Objekt über eine bestimmte Methode verfügt. Aus praktischen Gründen können Sie sich einen Selektor als alternativen Namen für eine Methode vorstellen.
Darstellung einer Methode durch Entwickler und Darstellung von Objective-CIntern verwendet Objective-C eine eindeutige Nummer, um jeden Methodennamen zu identifizieren, den Ihr Programm verwendet. Zum Beispiel eine Methode aufgerufen sag Hallo
könnte übersetzen in 4984331082
. Diese Kennung heißt a Wähler, Dies ist eine wesentlich effizientere Methode für den Compiler, um auf Methoden zu verweisen als auf die vollständige Darstellung von Strings. Es ist wichtig zu verstehen, dass ein Selektor nur die Methode darstellt Name-keine spezifische Methodenimplementierung. Mit anderen Worten, a sag Hallo
Methode definiert durch die Person
Klasse hat den gleichen Selektor wie a sag Hallo
Methode definiert durch die Schiff
Klasse.
Die drei wichtigsten Werkzeuge für die Arbeit mit Selektoren sind:
@Wähler()
- Gibt den mit einem Quellcode-Methodennamen verknüpften Selektor zurück.NSSelectorFromString ()
- Gibt den Selektor zurück, der der Zeichenfolgendarstellung eines Methodennamens zugeordnet ist. Diese Funktion ermöglicht die Definition des Methodennamens zur Laufzeit, ist jedoch weniger effizient als @Wähler()
.NSStringFromSelector ()
- Gibt die Zeichenfolgendarstellung eines Methodennamens aus einem Selektor zurück.Wie Sie sehen, gibt es drei Möglichkeiten, um einen Methodennamen in Objective-C darzustellen: als Quellcode, als String oder als Selektor. Diese Konvertierungsfunktionen werden in der folgenden Abbildung grafisch dargestellt:
Konvertierung zwischen Quellcode, Strings und SelektorenSelektoren werden in einem speziellen Datentyp gespeichert SEL
. Das folgende Snippet veranschaulicht die grundlegende Verwendung der drei in der vorherigen Abbildung dargestellten Konvertierungsfunktionen:
int main (int argc, const char * argv []) @autoreleasepool SEL selector = @selector (sayHello); NSLog (@ "% @", NSStringFromSelector (Selektor)); if (Selektor == NSSelectorFromString (@ "sayHello")) NSLog (@ "Die Selektoren sind gleich!"); return 0;
Zuerst benutzen wir die @Wähler()
Direktive, um den Selektor für eine aufgerufene Methode herauszufinden sag Hallo
, Dies ist eine Quellcode-Darstellung eines Methodennamens. Beachten Sie, dass Sie passieren können irgendein Methodenname bis @Wähler()
-Es muss nicht anderswo in Ihrem Programm existieren. Als nächstes benutzen wir die NSStringFromSelector ()
Funktion, um den Selektor wieder in einen String umzuwandeln, damit wir ihn im Ausgabefeld anzeigen können. Schließlich zeigt die Bedingung, dass Selektoren eine Eins-zu-Eins-Entsprechung mit Methodennamen haben, unabhängig davon, ob sie durch hart codierte Methodennamen oder -strings gefunden werden.
Im vorherigen Beispiel wird eine einfache Methode verwendet, für die keine Parameter erforderlich sind. Es ist jedoch wichtig, dass Methoden weitergegeben werden können tun Parameter akzeptieren. Denken Sie daran, dass ein Methodenname aus dem primären Methodennamen besteht, der mit allen Parameternamen verkettet ist. Zum Beispiel eine Methode mit der Unterschrift
- (void) sayHelloToPerson: (Person *) aPerson withGreeting: (NSString *) aGreeting;
hätte eine Methode Name von:
sayHelloToPerson: withGreeting:
Dies ist, worauf Sie gehen würden @Wähler()
oder NSSelectorFromString ()
um den Bezeichner für diese Methode zurückzugeben. Selektoren arbeiten nur mit der Methode Namen (keine Unterschriften), so gibt es nicht eine Eins-zu-Eins-Entsprechung zwischen Selektoren und Signaturen. Als Ergebnis die Methode Name Im letzten Beispiel wird auch eine Signatur mit verschiedenen Datentypen abgeglichen, einschließlich der folgenden:
- (void) sayHelloToPerson: (NSString *) aName withGreeting: (BOOL) useGreeting;
Die Ausführlichkeit der Namenskonventionen von Objective-C vermeidet verwirrende Situationen. Selektoren für Ein-Parameter-Methoden können jedoch immer noch schwierig sein, da ein Doppelpunkt an den Methodennamen angehängt wird komplett anders Methode. In dem folgenden Beispiel nimmt der erste Methodenname beispielsweise keinen Parameter an, während der zweite Methodenname:
sayHello sayHello:
Benennungskonventionen helfen dabei, Verwirrung zu vermeiden, Sie müssen jedoch immer wissen, wann Sie einen Doppelpunkt am Ende des Methodennamens hinzufügen müssen. Dies ist ein häufiges Problem, wenn Sie mit Selektoren noch nicht vertraut sind, und das Debuggen kann schwierig sein, da ein nachfolgender Doppelpunkt immer noch einen vollständig gültigen Methodennamen erstellt.
Natürlich, Aufnahme eines Selektors in einem SEL
Variable ist relativ nutzlos ohne die Fähigkeit, sie später auszuführen. Da ist ein Selektor nur eine Methode Name (keine Implementierung), es muss immer mit einem Objekt gekoppelt werden, bevor Sie es aufrufen können. Das NSObject
Klasse definiert a performSelector:
Methode zu diesem Zweck.
[Joe PerformSelector: @ Selector (sayHello)];
Dies ist das Äquivalent von Anrufen sag Hallo
direkt auf Joe
:
[Joe sayHello];
Für Methoden mit einem oder zwei Parametern können Sie die zugehörigen verwenden performSelector: withObject:
und performSelector: withObject: withObject:
Methoden. Die folgende Methodenimplementierung:
- (void) sayHelloToPerson: (Person *) aPerson NSLog (@ "Hallo,% @", [aPerson-Name]);
könnte dynamisch durch Übergeben der aufgerufen werden eine Person
Argument an die performSelector: withObject:
Methode, wie hier gezeigt:
[joe performSelector: @selector (sayHelloToPerson :) withObject: bill];
Dies entspricht der Übergabe des Parameters direkt an die Methode:
[joe sayHelloToPerson: bill];
Ebenso die performSelector: withObject: withObject:
Mit dieser Methode können Sie zwei Parameter an die Zielmethode übergeben. Der einzige Nachteil bei diesen ist, dass alle Parameter und der Rückgabewert der Methode Objekte sein müssen - sie funktionieren nicht mit primitiven C-Datentypen wie int
, schweben
, usw. Wenn Sie diese Funktionalität benötigen, können Sie entweder den primitiven Typ in eine der vielen Wrapper-Klassen von Objective-C (z., NSNumber
) oder verwenden Sie das NSInvocation-Objekt, um einen vollständigen Methodenaufruf zu kapseln.
Es ist nicht möglich, einen Selektor für ein Objekt auszuführen, das die zugehörige Methode nicht definiert hat. Im Gegensatz zu statischen Methodenaufrufen kann jedoch nicht festgestellt werden, ob performSelector:
wird einen Fehler auslösen. Stattdessen müssen Sie prüfen, ob ein Objekt zur Laufzeit auf einen Selektor reagieren kann, indem er den Namen "treffend" verwendet antwortetToSelector:
Methode. Es kehrt einfach zurück JA
oder NEIN
abhängig davon, ob das Objekt den Selektor ausführen kann:
SEL methodToCall = @selector (sayHello); if ([joe antwortetToSelector: methodToCall]) [joe performSelector: methodToCall]; else NSLog (@ "Joe kann% @ nicht ausführen.", NSStringFromSelector (methodToCall));
Wenn Ihre Selektoren dynamisch generiert werden (z. B. if methodToCall
aus einer Liste von Optionen ausgewählt wird) oder Sie haben keine Kontrolle über das Zielobjekt (z., Joe
kann eine von verschiedenen Objekttypen sein), es ist wichtig, diese Prüfung durchzuführen, bevor Sie versuchen, aufzurufen performSelector:
.
Die ganze Idee hinter Selektoren besteht darin, Methoden weitergeben zu können, genau wie Objekte. Dies kann zum Beispiel verwendet werden, um dynamisch eine "Aktion" für a zu definieren Person
Objekt, das später im Programm ausgeführt werden soll. Betrachten Sie zum Beispiel die folgende Schnittstelle:
Enthaltenes Codebeispiel: Selectors
@Interface Person: NSObject @Eigenschaft (Kopie) NSString * Name; @ Eigenschaft (schwach) Person * Freund; @ property SEL Aktion; - (nichtig) sagen hallo; - (nichtig) sagen, auf Wiedersehen; - (nichtig) zwingender Freund; @Ende
Zusammen mit der entsprechenden Implementierung:
#import "Person.h" @implementation Person @synthesize name = _name; @synthesize friend = _friend; @synthesize action = _action; - (void) sayHello NSLog (@ "Hallo, sagt% @.", _name); - (void) sayGoodbye NSLog (@ "Auf Wiedersehen sagt% @.", _name); - (void) coerceFriend NSLog (@ "% @ soll% @ dazu bringen, etwas zu tun.", _name, [_freundname]); [_friend performSelector: _action]; @Ende
Wie Sie sehen, rufen Sie die coerceFreund
Methode wird ein erzwingen anders Objekt, um eine beliebige Aktion auszuführen. Auf diese Weise können Sie eine Freundschaft und ein Verhalten frühzeitig in Ihrem Programm konfigurieren und auf das Eintreten eines bestimmten Ereignisses warten, bevor Sie die Aktion auslösen:
#einführen#import "Person.h" NSString * askUserForAction () // In der realen Welt wäre dies eine // // Benutzereingabe, um zu bestimmen, welche Methode aufgerufen werden soll. NSString * theMethod = @ "sayGoodbye"; Gib die Methode zurück. int main (int argc, const char * argv []) @autoreleasepool // Eine Person erstellen und eine durchzuführende Aktion festlegen. Person * Joe = [[Personenzuweisung] Init]; joe.name = @ "Joe"; Person * Rechnung = [[Personenzuordnung] init]; bill.name = @ "bill"; joe.friend = rechnung; joe.action = NSSelectorFromString (askUserForAction ()); // Warten auf ein Ereignis… // Führen Sie die Aktion aus. [Joe CoerceFriend]; return 0;
Dies ist fast genau so, wie Benutzeroberflächenkomponenten in iOS implementiert werden. Wenn Sie beispielsweise eine Schaltfläche hätten, würden Sie diese mit einem Zielobjekt konfigurieren (z., Freund
) und eine Aktion (z., Aktion
). Wenn der Benutzer die Taste schließlich drückt, kann er sie verwenden performSelector:
um die gewünschte Methode für das entsprechende Objekt auszuführen. Erlaube sowohl das Objekt und Die Methode, unabhängig zu variieren, bietet beträchtliche Flexibilität - die Schaltfläche könnte buchstäblich jede Aktion mit einem Objekt ausführen, ohne die Klasse der Schaltfläche in irgendeiner Weise zu verändern. Dies bildet auch die Grundlage für das Target-Action-Entwurfsmuster, auf das im Internet sehr viel Wert gelegt wird iOS Prägnant Begleitbuch.
In diesem Kapitel wurden Instanzen- und Klassenmethoden sowie einige der wichtigsten integrierten Methoden behandelt. Wir haben eng mit Selektoren zusammengearbeitet, mit denen Methodennamen entweder als Quellcode oder als Strings bezeichnet werden können. Das Target-Action-Entwurfsmuster, ein wesentlicher Aspekt der iOS- und OS X-Programmierung, wurde ebenfalls kurz vorgestellt.
Im nächsten Kapitel wird eine alternative Methode zum Erstellen privater und geschützter Methoden in Objective-C beschrieben.
Diese Lektion stellt ein Kapitel von Objective-C Succinctly dar, ein kostenloses eBook des Teams von Syncfusion.