Frage

Ich weiß davon HOCH (was ziemlich praktisch ist!), aber welche Programmierpraktiken verwenden Sie beim Schreiben von Objective-C und insbesondere bei der Verwendung von Cocoa (oder CocoaTouch)?

War es hilfreich?

Lösung

Es gibt ein paar Dinge, die ich begonnen habe, die ich nicht für Standard halte:

1) Mit dem Aufkommen von Eigenschaften verwende ich "_" nicht mehr, um "private" Klassenvariablen zu präfixen. Wenn auf eine Variable von anderen Klassen zugegriffen werden kann, sollte es keine Eigenschaft dafür geben? Ich mochte das "_" -Präfix immer nicht, um Code hässlicher zu machen, und jetzt kann ich es weglassen.

2) Wenn ich von privaten Dingen spreche, ziehe ich es vor, private Methodendefinitionen in die .m -Datei in einer Klassenerweiterung wie SO zu platzieren:

#import "MyClass.h"

@interface MyClass ()
- (void) someMethod;
- (void) someOtherMethod;
@end

@implementation MyClass

Warum sollten sich die .H -Datei mit Dingen, die Außenstehende nicht interessieren? Die leere () arbeitet für private Kategorien in der .m -Datei und Probleme kompilieren Warnungen, wenn Sie die deklarierten Methoden nicht implementieren.

3) Ich habe Dealloc an die Spitze der .m -Datei direkt unter den @synthesize -Richtlinien gestellt. Sollte das nicht ganz oben auf der Liste der Dinge stehen, über die Sie in einer Klasse nachdenken möchten? Das gilt insbesondere für eine Umgebung wie das iPhone.

3.5) Machen Sie in Tabellenzellen jedes Element (einschließlich der Zelle selbst) für die Leistung undurchsichtig. Das bedeutet, die entsprechende Hintergrundfarbe in allem festzulegen.

3.6) Wenn Sie eine NsurlConnection verwenden, möchten Sie in der Regel die Delegate -Methode implementieren:

- (NSCachedURLResponse *)connection:(NSURLConnection *)connection
                  willCacheResponse:(NSCachedURLResponse *)cachedResponse
{
      return nil;
}

Ich finde, die meisten Webanrufe sind sehr einzigartig und es ist mehr die Ausnahme als die Regel, die Sie mit Antworten zwischengespeichert werden möchten, insbesondere für Webdienstanrufe. Das Implementieren der Methode wie gezeigt deaktiviert das zwischengespeicherte Antworten.

Ebenfalls von Interesse sind einige gute iPhone -spezifische Tipps von Joseph Mattiello (erhalten in einer iPhone -Mailingliste). Es gibt mehr, aber diese waren die allgemein nützlichsten, die ich dachte (beachten Sie, dass einige Teile jetzt leicht vom Original bearbeitet wurden, um Details in Antworten enthalten):

4) Verwenden Sie nur doppelte Präzision, wenn Sie müssen, z. B. bei der Arbeit mit der Korelation. Stellen Sie sicher, dass Sie Ihre Konstanten in 'f' beenden, um GCC als Schwimmkörper zu lagern.

float val = someFloat * 2.2f;

Dies ist meistens wichtig, wenn someFloat Möglicherweise ist es tatsächlich ein Doppel, Sie brauchen nicht die Mixed-Mode-Mathematik, da Sie im Speicher eine Präzision in 'Val' verlieren. Während Floating-Punkt-Nummern in Hardware auf iPhones unterstützt werden, kann es noch mehr Zeit dauern, doppelte Präzisionsarithmetik im Gegensatz zu einer einzigen Präzision durchzuführen. Verweise:

Auf den älteren Telefonen arbeiten angeblich Berechnungen mit der gleichen Geschwindigkeit, aber Sie können mehr ein Präzisionskomponenten in Registern als verdoppelt haben, sodass für viele Berechnungen eine einzelne Präzision schneller werden.

5) Setzen Sie Ihre Eigenschaften als nonatomic. Sie sind atomic Standardmäßig und bei der Synthese wird der Semaphore-Code erstellt, um Multi-Threading-Probleme zu verhindern. 99% von Ihnen müssen sich wahrscheinlich keine Sorgen machen, und der Code ist viel weniger aufgebläht und speichereffizienter, wenn sie auf nichtatomar eingestellt sind.

6) SQLITE kann ein sehr, sehr schneller Weg sein, um große Datensätze zu leiten. Eine Kartenanwendung kann beispielsweise ihre Fliesen in SQLite -Dateien zwischenspeichern. Der teuerste Teil ist die Festplatte I/O. Vermeiden Sie viele kleine Schreibvorgänge durch Senden BEGIN; und COMMIT; zwischen großen Blöcken. Wir verwenden einen 2 -Sekunden -Timer zum Beispiel, der bei jedem neuen Subjekt zurückgesetzt wird. Wenn es abläuft, senden wir Commit; , was dazu führt, dass alle Ihre Schreibvorgänge in einem großen Stück gehen. SQLite speichert Transaktionsdaten auf Festplatten und dies wird mit Beginn/Endverpackung die Erstellung vieler Transaktionsdateien vermieden, wodurch alle Transaktionen in eine Datei gruppiert werden.

Außerdem blockiert SQL Ihre GUI, wenn sie sich in Ihrem Hauptfaden befindet. Wenn Sie eine sehr lange Anfrage haben, ist es eine gute Idee, Ihre Abfragen als statische Objekte zu speichern und Ihren SQL auf einem separaten Thread auszuführen. Stellen Sie sicher @synchronize() {} Blöcke. Für kurze Anfragen lassen Sie einfach die Sache leichter bequemer.

Weitere Tipps zur SQLite -Optimierung sind hier, obwohl das Dokument veraltet erscheint, sind viele der Punkte wahrscheinlich immer noch gut.

http://web.utk.edu/~jplyon/sqlite/sqlite_optimization_faq.html

Andere Tipps

Verwenden Sie keine unbekannten Zeichenfolgen als Formatketten

Wenn Methoden oder Funktionen ein Format -String -Argument annehmen, sollten Sie sicherstellen, dass Sie die Kontrolle über den Inhalt der Formatzeichenfolge haben.

Zum Beispiel ist es beim Protokollieren von Zeichenfolgen verlockend, die String -Variable als alleiniges Argument an zu übergeben NSLog:

    NSString *aString = // get a string from somewhere;
    NSLog(aString);

Das Problem dabei ist, dass die Zeichenfolge Zeichen enthalten kann, die als Formatketten interpretiert werden. Dies kann zu fehlerhaften Ausgaben, Abstürzen und Sicherheitsproblemen führen. Stattdessen sollten Sie die String -Variable in eine Formatzeichenfolge ersetzen:

    NSLog(@"%@", aString);

Verwenden Sie Standard -Kakao -Namens- und Formatierungskonventionen und Terminologie, anstatt das, was Sie aus einer anderen Umgebung gewohnt sind. Dort sind Viele Kakaoentwickler da draußen, und wenn ein anderer mit Ihrem Code beginnt, wird es viel zugänglicher sein, wenn er einem anderen Cocoa -Code ähnlich aussieht und sich ähnlich anfühlt.

Beispiele dafür, was zu tun ist und was nicht:

  • Erkläre nicht id m_something; in der Oberfläche eines Objekts und nennen Sie es a Mitgliedsvariable oder aufstellen; verwenden something oder _something für seinen Namen und nennen Sie es eine Instanzvariable.
  • Nennen Sie keinen Getter -getSomething; Der richtige Kakao -Name ist gerecht -something.
  • Nennen Sie keinen Setter -something:; es sollte sein -setSomething:
  • Der Methodenname ist mit den Argumenten durchsetzt und umfasst Kolons. es ist -[NSObject performSelector:withObject:], nicht NSObject::performSelector.
  • Verwenden Sie Inter-CAPs (Kamelcase) in Methodamen, Parametern, Variablen, Klassennamen usw. anstelle von Unterteilen (Unterstriche).
  • Die Klassennamen beginnen mit einem Oberfall-Buchstaben-, Variablen- und Methodennamen mit niedrigerer Fall.

Was auch immer Sie sonst tun, nicht Verwenden Sie die ungarische Notation im Win16/Win32-Stil. Sogar Microsoft gab das mit dem Wechsel zur .NET -Plattform auf.

Iboutlets

Historisch gesehen war die Gedächtnisverwaltung von Verkaufsstellen schlecht. Aktuelle Best Practice besteht darin, Outlets als Eigenschaften zu deklarieren:

@interface MyClass :NSObject {
    NSTextField *textField;
}
@property (nonatomic, retain) IBOutlet NSTextField *textField;
@end

Die Verwendung von Eigenschaften macht die Speicherverwaltungssemantik klar; Es bietet auch ein konsistentes Muster, wenn Sie eine Instanzvariablensynthese verwenden.

Verwenden Sie den statischen Analysator LLVM/Clang

Hinweis: Unter Xcode 4 ist dies jetzt in die IDE eingebaut.

Sie verwenden die Clang Static Analyzer zu-nicht überraschend-analysieren Sie Ihren C- und Objective-C-Code (noch nicht c ++) unter Mac OS X 10.5. Es ist trivial zu installieren und zu verwenden:

  1. Laden Sie die neueste Version von herunter diese Seite.
  2. Aus der Befehlszeile, cd zu Ihrem Projektverzeichnis.
  3. Ausführen scan-build -k -V xcodebuild.

(Es gibt einige zusätzliche Einschränkungen usw., insbesondere sollten Sie ein Projekt in seiner "Debug" -Konfiguration analysieren - siehe http://clang.llvm.org/staticanalysisSage.html Für Details-das aber das ist mehr oder weniger, worauf es sich läuft.)

Der Analysator erstellt dann eine Reihe von Webseiten für Sie, die eine wahrscheinliche Speicherverwaltung und andere grundlegende Probleme anzeigen, die der Compiler nicht erkennen kann.

Dies ist subtil, aber praktisch. Wenn Sie sich als Delegierter an ein anderes Objekt übergeben, setzen Sie den Delegierten dieses Objekts vor Ihnen zurück dealloc.

- (void)dealloc
{
self.someObject.delegate = NULL;
self.someObject = NULL;
//
[super dealloc];
}

Auf diese Weise stellen Sie sicher, dass keine Delegierten -Methoden mehr gesendet werden. Wie Sie gerade sind dealloc und verschwinden in dem Äther, in dem Sie sicherstellen möchten, dass Ihnen nichts mehr Nachrichten senden kann. Denken Sie daran, dass Self.SomeObject von einem anderen Objekt beibehalten werden kann (es könnte sich um einen Singleton oder auf dem Autorelease-Pool oder was auch immer handeln) und bis Sie ihm sagen, "Hör auf, mir Nachrichten zu senden!" ist faires Spiel.

Wenn Sie sich dieser Gewohnheit einlassen, werden Sie viele seltsame Abstürze ersparen, die ein Schmerz für das Debuggen sind.

Der gleiche Auftraggeber gilt auch für die Beobachtung der wichtigsten Wertschöpfung und für NSNotifikationen.

Bearbeiten:

Noch defensiver, Veränderung:

self.someObject.delegate = NULL;

hinein:

if (self.someObject.delegate == self)
    self.someObject.delegate = NULL;

@kendell

Anstatt von:

@interface MyClass (private)
- (void) someMethod
- (void) someOtherMethod
@end

Verwenden:

@interface MyClass ()
- (void) someMethod
- (void) someOtherMethod
@end

Neu in Objective-C 2.0.

Klassenerweiterungen werden in der Referenz für Ziel-C 2.0 von Apple beschrieben.

"Klassenerweiterungen ermöglichen es Ihnen, zusätzliche erforderliche API für eine Klasse an anderen Stellen als innerhalb des primären Klasse @Interface -Block zu deklarieren."

Sie sind also Teil der tatsächlichen Klasse - und nicht zusätzlich zur Klasse eine (private) Kategorie. Subtiler, aber wichtiger Unterschied.

Vermeiden Sie Autorelease

Da Sie in der Regel (1) über ihre Lebensdauer in der Regel keine direkte Kontrolle haben, können autoreleased Objekte eine vergleichsweise lange Zeit bestehen und den Speicherpflichtiger Ihrer Anwendung unnötig erhöhen. Während des Desktops kann dies auf wenigen eingeschränkten Plattformen von geringer Folge sein. Auf allen Plattformen und insbesondere auf eingeschränkteren Plattformen wird daher als bewährte Praxis angesehen, um Methoden zu vermeiden, die zu autorieternden Objekten führen, und stattdessen werden Sie ermutigt, das Alloc/Init -Muster zu verwenden.

Also eher anstatt:

aVariable = [AClass convenienceMethod];

Wo fähig, sollten Sie stattdessen verwenden:

aVariable = [[AClass alloc] init];
// do things with aVariable
[aVariable release];

Wenn Sie Ihre eigenen Methoden schreiben, die ein neu erstelltes Objekt zurückgeben, können Sie die Vorteile nutzen Kakaos Namenskonvention Um dem Empfänger zu markieren, dass es veröffentlicht werden muss, indem der Methodenname mit "neu" vorbereitet wird.

Also statt:

- (MyClass *)convenienceMethod {
    MyClass *instance = [[[self alloc] init] autorelease];
    // configure instance
    return instance;
}

Sie könnten schreiben:

- (MyClass *)newInstance {
    MyClass *instance = [[self alloc] init];
    // configure instance
    return instance;
}

Da der Methodenname mit "neu" beginnt, wissen die Verbraucher Ihrer API, dass sie für die Veröffentlichung des empfangenen Objekts verantwortlich sind (siehe beispielsweise, NSObjectController newObject Methode).

(1) Sie können die Kontrolle übernehmen, indem Sie Ihre eigenen lokalen Autorelease -Pools verwenden. Weitere Informationen dazu finden Sie unter Autorelease -Pools.

Einige davon wurden bereits erwähnt, aber hier ist, woran ich mir vor meinem Kopf denken kann:

  • Befolgen Sie die KVO -Namensregeln. Auch wenn Sie KVO jetzt nicht verwenden, ist es meiner Erfahrung nach in Zukunft immer noch von Vorteil. Und wenn Sie KVO oder Bindungen verwenden, müssen Sie wissen, dass die Dinge so arbeiten, wie sie sollen. Dies deckt nicht nur Accessor-Methoden und Instanzvariablen ab, sondern auch zu vielen Beziehungen, Validierung, automatischen Abhängigkeit von abhängigen Schlüssel usw.
  • Geben Sie private Methoden in eine Kategorie ein. Nicht nur die Schnittstelle, sondern auch die Implementierung. Es ist gut, konzeptionell zwischen privaten und nicht privaten Methoden einen gewissen Distanz zu haben. Ich füge alles in meine .m -Datei ein.
  • Geben Sie Hintergrund -Thread -Methoden in eine Kategorie ein. Das gleiche wie oben. Ich habe festgestellt, dass es gut ist, eine klare konzeptionelle Barriere zu behalten, wenn Sie darüber nachdenken, was sich auf dem Hauptfaden befindet und was nicht.
  • Verwenden #pragma mark [section]. Normalerweise gruppiere ich mich nach eigenen Methoden, die Überschreibungen jeder Unterklasse und alle Informationen oder formalen Protokolle. Dies macht es viel einfacher, genau zu springen, wonach ich suche. Zum gleichen Thema Gruppen ähnliche Methoden (wie die Delegiermethoden der Tabellenansicht) zusammen, halten Sie sie nicht nur nirgendwo an.
  • Präfix private Methoden & Ivars mit _. Ich mag die Art und Weise, wie es aussieht, und ich benutze weniger wahrscheinlich einen Ivar, wenn ich versehentlich eine Eigenschaft meine.
  • Verwenden Sie keine Mutatormethoden / -eigenschaften in Init & overloc. Ich hatte noch nie etwas Schlimmes, aber ich kann die Logik sehen, wenn Sie die Methode ändern, um etwas zu tun, das vom Zustand Ihres Objekts abhängt.
  • Setzen Sie Iboutlets in Eigenschaften. Ich habe das eigentlich hier gelesen, aber ich werde damit anfangen. Unabhängig von Gedächtnisvorteilen scheint es besser stilistisch (zumindest für mich).
  • Vermeiden Sie es, Code zu schreiben, den Sie nicht unbedingt benötigen. Dies deckt wirklich viele Dinge ab, wie Ivars zu machen, wenn a #define Wird ein Array tun oder zwischenstrichen, anstatt es jedes Mal zu sortieren, wenn die Daten benötigt werden. Ich könnte viel darüber sagen, aber das Fazit schreibt keinen Code, bis Sie ihn benötigen, oder der Profiler sagt es Ihnen. Es erleichtert auf lange Sicht viel einfacher zu pflegen.
  • Beende, was du anfängst. Der Buggy-Code ist der schnellste Weg, um ein Projekt tot zu töten. Wenn Sie eine Stubmethode benötigen, die in Ordnung ist, geben Sie sie einfach an, indem Sie einfügen NSLog( @"stub" ) Im Inneren oder wie auch immer Sie die Dinge im Auge behalten möchten.

Schreiben Sie Unit -Tests. Sie können a testen viel von Dingen in Kakao, die in anderen Frameworks schwieriger sein könnten. Zum Beispiel können Sie mit dem UI -Code im Allgemeinen überprüfen, ob die Dinge so verbunden sind, wie sie sein sollten, und vertrauen darauf, dass sie bei der Verwendung arbeiten. Und Sie können Status einrichten und Delegate -Methoden aufrufen, um sie zu testen.

Sie haben auch keine öffentliche vs. geschützte und private Methoden -Sichtbarkeiten, die das Schreiben von Tests für Ihre Interna im Wege im Wege des Schreibens haben.

Goldene Regel: Wenn Sie alloc dann Sie release!

Update: Es sei denn, Sie verwenden ARC

Schreiben Sie kein objektives C, als wäre es Java/C#/C ++/etc.

Ich habe einmal gesehen, wie ein Team es gewohnt ist, Java EE -Webanwendungen zu schreiben, um eine Cocoa -Desktop -Anwendung zu schreiben. Als wäre es eine Java EE -Webanwendung. Es gab viele AbstractFoofactory und Footory und Ifoo und Foo flogen herum, wenn alles, was sie wirklich brauchten, eine Foo -Klasse und möglicherweise ein fooable Protokoll war.

Ein Teil der Sicherstellung, dass Sie dies nicht tun, besteht darin, die Unterschiede in der Sprache wirklich zu verstehen. Beispielsweise benötigen Sie nicht die obigen abstrakten Fabrik- und Fabrikklassen, da Objective-C-Klassenmethoden genauso dynamisch wie Instanzmethoden versandt werden und in Unterklassen überschrieben werden können.

Stellen Sie sicher, dass Sie das Lesezeichen versetzen Magie debuggen Seite. Dies sollte Ihr erster Zwischenstopp sein, wenn Sie Ihren Kopf gegen eine Wand schlagen, während Sie versuchen, die Quelle eines Kakaoprots zu finden.

Beispielsweise wird Ihnen aufgezeigt, wie Sie die Methode finden, bei der Sie zuerst Speicher zugewiesen haben, die später Abstürze verursachen (wie während der App -Beendigung).

Sortieren Sie Strings, wie der Benutzer will

Wenn Sie Strings so sortieren, wie Sie es dem Benutzer präsentieren, sollten Sie das einfache nicht verwenden compare: Methode. Stattdessen sollten Sie immer lokalisierte Vergleichsmethoden verwenden, z. localizedCompare: oder localizedCaseInsensitiveCompare:.

Weitere Informationen finden Sie unter Suchen, Vergleichen und Sortieren von Streichern.

Versuchen Sie zu vermeiden, was ich jetzt für den NewbieCategoryaholismus bezeichnet habe. Wenn Neuankömmlinge für objektive C-Kategorien entdecken, werden sie häufig wild und fügen jeder existierenden Klasse nützliche kleine Kategorien hinzu ("Was? Ich kann eine Methode hinzufügen, um eine Nummer in römische Ziffern in NsNumber Rock zu konvertieren!").

Tu das nicht.

Ihr Code ist tragbarer und leichter zu verstehen, ohne Dutzende von kleinen Kategorienmethoden, die über zwei Dutzend Fundamentkurse gestreut werden.

Meistens, wenn Sie wirklich der Meinung sind, dass Sie eine Kategorie -Methode benötigen, um einen Code zu optimieren, werden Sie die Methode nie wiederverwenden.

Es gibt auch andere Gefahren, es sei denn, Sie nennen Ihre Kategoriemethoden (und wer neben dem äußerst wahnsinnigen Ddribin besteht die Möglichkeit, dass Apple oder ein Plugin oder etwas anderes, das in Ihrem Adressraum ausgeführt wird, auch dieselbe Kategorie definiert Methode mit demselben Namen mit einem etwas anderen Nebeneffekt ....

OK. Jetzt, wo Sie gewarnt wurden, ignorieren Sie das "Nicht machen Sie diesen Teil". Aber extreme Zurückhaltung ausüben.

Widerstehen Sie der Welt. In Kakao erfolgt viel durch Delegation und Verwendung der zugrunde liegenden Laufzeit, die in anderen Frameworks durch Subklasser durchgeführt wird.

Zum Beispiel verwenden Sie in Java Instanzen von Anonymous *Listener Unterklassen viel und in .NET verwenden Sie Ihre EventArgs Unterklassen viel. In Kakao tun Sie es auch nicht-die Zielwirkung wird stattdessen verwendet.

Deklarierte Eigenschaften

Sie sollten in der Regel die Funktion Objective-C 2.0 für alle Ihre Eigenschaften verwenden. Wenn sie nicht öffentlich sind, fügen Sie sie in eine Klassenerweiterung hinzu. Durch die Verwendung deklarierter Eigenschaften wird die Semantik der Speicherverwaltung sofort klargestellt und erleichtert Sie die Überprüfung Ihrer Dealloc -Methode. Wenn Sie Ihre Eigenschaftserklärungen zusammen gruppieren, können Sie sie schnell scannen und mit der Implementierung Ihrer Dealloc -Methode vergleichen.

Sie sollten sich anstrengen, bevor Sie Eigenschaften nicht als "nichtatomar" markieren. Wie Der objektive C -Programmiersprachanleitung Anmerkungen, Eigenschaften sind standardmäßig atomar und verursachen erhebliche Overhead. Wenn Sie einfach alle Ihre Eigenschaften atomic erzeugen, sind Ihre Anwendungs-Thread nicht sicher. Beachten Sie natürlich auch, dass Sie sie atomarer Weise implementieren müssen, wenn Sie nicht "nichtatomar" und nicht "eigene Accessor -Methoden implementieren" (anstatt sie zu synthetisieren).

Denken Sie an NIL -Werte nach

Wie diese Frage Notizen, Nachrichten an nil sind in Objective-C gültig. Dies ist zwar häufig ein Vorteil-was zu sauberer und natürlicherer Code führt-, kann die Funktion gelegentlich zu besonderen und schwer zu verspüren Fehler führen, wenn Sie eine erhalten nil Wert, wenn Sie es nicht erwartet haben.

Verwenden Sie Nsassert und Freunde. Ich benutze NIL ständig als gültiges Objekt ... insbesondere das Senden von Nachrichten an Nil ist in OBJ-C perfekt gültig. Wenn ich jedoch wirklich den Zustand einer Variablen sicherstellen möchte, verwende ich NSassert und NsParameterassert, was dazu beiträgt, Probleme leicht aufzuspüren.

Einfach, aber oft vergessen. Nach Ansicht:

Im Allgemeinen müssen Methoden in verschiedenen Klassen mit demselben Selektor (gleicher Name) auch dieselben Rendite- und Argumententypen teilen. Diese Einschränkung wird vom Compiler auferlegt, um eine dynamische Bindung zu ermöglichen.

In diesem Fall alle gleichen benannten Selektoren, Auch wenn in verschiedenen Klassen, wird als identische Rückgabe-/Argumententypen angesehen. Hier ist ein einfaches Beispiel.

@interface FooInt:NSObject{}
-(int) print;
@end

@implementation FooInt
-(int) print{
    return 5;
}
@end

@interface FooFloat:NSObject{}
-(float) print;
@end

@implementation FooFloat
-(float) print{
    return 3.3;
}
@end

int main (int argc, const char * argv[]) {

    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];    
    id f1=[[FooFloat alloc]init];
    //prints 0, runtime considers [f1 print] to return int, as f1's type is "id" and FooInt precedes FooBar
    NSLog(@"%f",[f1 print]);

    FooFloat* f2=[[FooFloat alloc]init];
    //prints 3.3 expectedly as the static type is FooFloat
    NSLog(@"%f",[f2 print]);

    [f1 release];
    [f2 release]
    [pool drain];

    return 0;
}   

Wenn Sie Leopard (Mac OS X 10.5) oder später verwenden, können Sie die Instrumenteanwendung verwenden, um Speicherlecks zu finden und zu verfolgen. Wählen Sie nach dem Erstellen Ihres Programms in Xcode aus, um mit dem Leistungstool> Lecks zu starten.

Auch wenn Ihre App keine Lecks anzeigt, halten Sie möglicherweise Objekte zu lange. In Instrumenten können Sie das ObjectAllloc -Instrument dafür verwenden. Wählen Sie das ObjectAlloc -Instrument in Ihrem Instrumente -Dokument aus und geben Sie das Detail des Instruments (falls es nicht bereits angezeigt wird) an, indem Sie die Ansicht> Details auswählen (es sollte ein Scheck -Zeichen daneben haben). Stellen Sie unter "Allocation LifeSespan" im ObjectAllloc -Detail sicher, dass Sie den Optionsfeld neben "erstellt und noch leben" auswählen.

Wenn Sie nun die Aufzeichnung Ihrer Anwendung einstellen, zeigt Ihnen die Auswahl des ObjectAllloc-Tools an, wie viele Referenzen auf jedes noch lebende Objekt in Ihrer Anwendung in der Spalte "# net" enthalten sind. Stellen Sie sicher, dass Sie sich nicht nur Ihre eigenen Klassen ansehen, sondern auch die Klassen der obersten Objekte der NIB-Dateien. Wenn Sie beispielsweise keine Fenster auf dem Bildschirm haben und Verweise auf einen noch lebenden NSWindow sehen, haben Sie es möglicherweise nicht in Ihrem Code veröffentlicht.

Aufräumen in Dealloc.

Dies ist eines der Dinge, die man am leichtesten vergisst – insbesondere.beim Codieren mit 150 Meilen pro Stunde.Bereinigen Sie immer, immer, immer Ihre Attribute/Mitgliedsvariablen in Dealloc.

Ich verwende gerne Objc 2-Attribute - mit die neue Punktnotation – das macht die Bereinigung schmerzlos.Oft so einfach wie:

- (void)dealloc
{
    self.someAttribute = NULL;
    [super dealloc];
}

Dadurch wird die Veröffentlichung für Sie erledigt und das Attribut auf NULL gesetzt (was ich als defensive Programmierung betrachte – für den Fall, dass eine andere Methode weiter unten in Dealloc erneut auf die Mitgliedsvariable zugreift – was aber selten vorkommt könnte passieren).

Wenn GC in 10.5 aktiviert ist, ist dies nicht mehr so ​​sehr erforderlich. Möglicherweise müssen Sie jedoch noch andere von Ihnen erstellte Ressourcen bereinigen. Dies können Sie stattdessen in der Finalize-Methode tun.

All diese Kommentare sind großartig, aber ich bin wirklich überrascht, dass niemand erwähnt wird Googles Objective-C-Stilhandbuch Das wurde vor einiger Zeit veröffentlicht. Ich denke, sie haben einen sehr gründlichen Job gemacht.

Auch halbbezogenes Thema (mit Platz für weitere Antworten!):

Was sind diese kleinen Xcode -Tipps und -tricks, von denen Sie sich vor 2 Jahren kennen?.

Vergessen Sie nicht, dass NswindowController und NSViewController die Objekte der Top-Ebene der von ihnen regierenden NIB-Dateien veröffentlichen.

Wenn Sie eine NIB-Datei manuell laden, sind Sie dafür verantwortlich, die Objekte der NIB-obersten Ebene zu veröffentlichen, wenn Sie mit ihnen fertig sind.

Eine ziemlich offensichtliche für einen Anfänger zu verwenden: Verwenden Sie die automatische Indentationsfunktion von Xcode für Ihren Code. Selbst wenn Sie von einer anderen Quelle kopieren/einfügen, können Sie nach dem Einfügen des Codes den gesamten Codeblock auswählen, mit der rechten Maustaste darauf klicken und dann die Option auswählen, alles in diesem Block neu zu vermitteln.

Xcode analysiert tatsächlich diesen Abschnitt und führt ihn basierend auf Klammern, Schleifen usw. ein. Es ist viel effizienter, als für jede Zeile die Space -Balk- oder Registerkarte zu treffen.

Ich weiß, dass ich das übersehen habe, als ich zum ersten Mal in die Kakao -Programmierung eingestiegen bin.

Stellen Sie sicher, dass Sie die Verantwortlichkeiten des Speichermanagements in Bezug auf NIB -Dateien verstehen. Sie sind dafür verantwortlich, die Objekte der obersten Ebene in jeder NIB-Datei zu veröffentlichen, die Sie geladen haben. Lesen Apples Dokumentation zum Thema.

Schalten Sie alle GCC -Warnungen ein und schalten Sie diejenigen aus, die regelmäßig durch Apples Header verursacht werden, um den Geräusch zu reduzieren.

Führen Sie auch die statische Klanganalyse häufig durch; Sie können es für alle Builds über die Einstellung "Static Analyzer" aktivieren.

Schreiben Sie Unit -Tests und führen Sie sie mit jedem Build aus.

Variablen und Eigenschaften

1/ Halten Sie Ihre Header sauber, die Implementierung verstecken
Fügen Sie keine Instanzvariablen in Ihren Kopfzeile auf. Private Variablen, die als Eigenschaften in die Klassen fortgesetzt werden. Öffentliche Variablen deklarieren als öffentliche Eigenschaften in Ihrem Kopfball. Wenn es nur gelesen werden sollte, deklarieren Sie es als Readonly und überschreiben Sie es als Readwrite in der Klassenkontinutation. Grundsätzlich verwende ich überhaupt keine Variablen, nur Eigenschaften.

2/ Geben Sie Ihren Eigenschaften einen nicht eingestellten Variablennamen an, Beispiel:


@synthesize property = property_;

Grund 1: Sie werden Fehler aufnehmen, die durch das Vergessen von "Selbst" verursacht werden. Bei der Zuweisung der Eigenschaft. Grund 2: Aus meinen Experimenten hat Leak Analyzer in Instrumenten Probleme, die undichte Eigenschaft mit Standardnamen zu erkennen.

3/ NIEMALS BAUR BAUF UND DIRBESTELLUNGEN UNTER DEM Eigenschaften (oder nur in sehr außergewöhnlichen Situationen) verwenden. In Ihrem Overlyloc weisen Sie ihnen einfach einen Nil zu. Beibehalten von Eigenschaften sollen die Rückhalteversorgung von selbst verarbeiten. Sie wissen nie, ob ein Setter beispielsweise Beobachter hinzufügt oder entfernt. Sie sollten die Variable nur direkt in Setter und Getter verwenden.

Ansichten

1/ Legen Sie jede Ansichtsdefinition in ein XIB ein, wenn Sie können (die Ausnahme ist normalerweise dynamischer Inhalt und Ebeneneinstellungen). Es spart Zeit (es ist einfacher als das Schreiben von Code), es ist einfach zu ändern und hält Ihren Code sauber.

2/ Versuchen Sie nicht, die Ansichten zu optimieren, indem Sie die Anzahl der Ansichten verringern. Erstellen Sie UIImageView nicht in Ihrem Code anstelle von XIB, nur weil Sie Subviews dazu hinzufügen möchten. Verwenden Sie stattdessen UIImageView als Hintergrund. Das View -Framework kann ohne Probleme Hunderte von Ansichten verarbeiten.

3/ iboutlets müssen nicht immer immer erhalten bleiben (oder stark). Beachten Sie, dass die meisten Ihrer Iboutlets Teil Ihrer Sichtweise sind und damit implizit beibehalten werden.

4/ Veröffentlichung alle Iboutlets in ViewDidunload

5/ Call ViewDidunload von Ihrer Overalloc -Methode. Es wird nicht implizit genannt.

Erinnerung

1/ Autorelease -Objekte, wenn Sie sie erstellen. Viele Fehler werden durch Verschieben Ihres Release-Anrufs in einen IF-ELSE-Zweig oder nach einer Rückgabeanweisung verursacht. Die Freigabe anstelle von Autorelease sollte nur in außergewöhnlichen Situationen verwendet werden - z. B. wenn Sie auf einen Runloop warten und Sie nicht möchten, dass Ihr Objekt zu früh autorelea ist.

2/ Auch wenn Sie authomatische Referenzzählung verwenden, müssen Sie perfekt verstehen, wie die Methoden zur Veröffentlichung von Veröffentlichungen funktionieren. Die manuelle Verwendung von Retain-Veröffentlichungen ist nicht komplizierter als ARC, in beiden Fällen müssen Sie etwas über Lecks und Haltezykle haben. Erwägen Sie manuell für große Projekte oder komplizierte Objekthierarchien zu verwenden.

Kommentare

1/ Machen Sie Ihren Code autodokumentiert. Jeder variable Name und jeder Methodenname sollte sagen, was er tut. Wenn Code korrekt geschrieben wird (Sie benötigen viel Übung darin), benötigen Sie keine Code -Kommentare (nicht die gleichen wie Dokumentationskommentare). Algorithmen können kompliziert sein, aber der Code sollte immer einfach sein.

2/ Manchmal brauchen Sie einen Kommentar. In der Regel ein nicht scheinbares Codeverhalten oder Hack zu beschreiben. Wenn Sie das Gefühl haben, einen Kommentar schreiben zu müssen, versuchen Sie zunächst, den Code so umzuschreiben, um einfacher und ohne Kommentare erforderlich zu sein.

Vertiefung

1/ Erhöhen Sie die Indentation nicht zu sehr. Der größte Teil Ihres Methodscode sollte auf der Methodenebene eingerichtet werden. Verschachtelte Blöcke (wenn, für usw.) verringern die Lesbarkeit. Wenn Sie drei verschachtelte Blöcke haben, sollten Sie versuchen, die inneren Blöcke in eine separate Methode zu setzen. Vier oder mehr verschachtelte Blöcke sollten nie verwendet werden. Wenn sich der größte Teil Ihres Methodencodes in einem if befindet, negieren Sie die IF -Bedingung, Beispiel:


if (self) {
   //... long initialization code ...
}

return self;


if (!self) {
   return nil;
}

//... long initialization code ...

return self;

Verstehen Sie C -Code, hauptsächlich C -Strukturen

Beachten Sie, dass OBJ-C nur eine leichte OOP-Schicht über C-Sprache ist. Sie sollten verstehen, wie grundlegende Codestrukturen in C (Enums, Strukturen, Arrays, Zeiger usw.) funktionieren. Beispiel:


view.frame = CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, view.frame.size.height + 20);

ist das gleiche wie:


CGRect frame = view.frame;
frame.size.height += 20;
view.frame = frame;

Und viele mehr

Mantain Ihr eigenes Codierungsstandards -Dokument und aktualisiert es häufig. Versuchen Sie, aus Ihren Fehlern zu lernen. Verstehen Sie, warum ein Fehler erstellt wurde, und versuchen Sie, ihn mithilfe von Codierungsstandards zu vermeiden.

Unsere Codierungsstandards haben derzeit etwa 20 Seiten, eine Mischung aus Java-Codierungsstandards, Google OBJ-C/C ++-Standards und unseren eigenen Addings. Dokumentieren Sie Ihren Code, verwenden Sie Standard -Standardeinschluss, weiße Räume und leere Zeilen an den richtigen Stellen usw.

Sei mehr funktional.

Objective-C ist eine objektorientierte Sprache, aber das Kakao-Framework-Funktionsstil bewusst und ist in vielen Fällen funktionaler Stil gestaltet.

  1. Es gibt Trennung der Veränderlichkeit. Verwenden unveränderlich Klassen als primäres und veränderliches Objekt als sekundär. Verwenden Sie beispielsweise nsArray hauptsächlich und verwenden Sie NSMutablearray nur, wenn Sie benötigen.

  2. Es gibt reine Funktionen. Nicht so viele, kaufen viele Rahmen -APIs wie reine Funktion. Betrachten Sie Funktionen wie CGRectMake() oder CGAffineTransformMake(). Offensichtlich sieht Zeigerform effizienter aus. Indirekte Argumente mit Zeigern können jedoch keine Nebeneffektfreiheit bieten. Entwurfsstrukturen so weit wie möglich. Trennen sogar Zustandsobjekte. Verwenden -copy Anstatt von -retain beim Übergeben eines Wertes an ein anderes Objekt. Weil der gemeinsame Zustand die Mutation zum Wert in anderen Objekten stillschweigend beeinflussen kann. Ich kann also nicht seitlich effektfrei sein. Wenn Sie einen Wert von externem vom Objekt haben, kopieren Sie ihn. Daher ist es auch wichtig, den gemeinsamen Zustand so minimal wie möglich zu entwerfen.

Haben Sie jedoch keine Angst davor, unreine Funktionen zu verwenden.

  1. Es gibt eine faule Bewertung. Sehen Sie so etwas wie -[UIViewController view] Eigentum. Die Ansicht wird nicht erstellt, wenn das Objekt erstellt wird. Es wird beim Lesen des Anrufers erstellt view Eigentum zum ersten Mal. UIImage wird erst geladen, bis es tatsächlich gezeichnet wird. Es gibt viele Implementierung wie dieses Design. Diese Art von Designs ist sehr hilfreich für das Ressourcenmanagement. Wenn Sie jedoch das Konzept der faulen Bewertung nicht kennen, ist es nicht leicht, das Verhalten von ihnen zu verstehen.

  2. Es gibt Schließung. Verwenden Sie C-Blocks so weit wie möglich. Dies wird Ihr Leben stark vereinfachen. Lesen Sie jedoch noch einmal über Block-Memory-Management, bevor Sie es verwenden.

  3. Es gibt Semi-Auto GC. NSAUTORELEASEPOOL. Verwenden -autorelease primär. Handbuch verwenden -retain/-release sekundär, wenn Sie wirklich brauchen. (Beispiel: Speicheroptimierung, explizite Ressourcenlöschung)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top