Odpowiedzi:
Jest kilka rzeczy, które zacząłem robić, ale nie uważam ich za standardowe:
1) Wraz z pojawieniem się właściwości nie używam już znaku „_” do prefiksu zmiennych „prywatnych”. W końcu, jeśli dostęp do zmiennej mogą uzyskać inne klasy, czy nie powinna istnieć dla niej własność? Zawsze nie podobał mi się prefiks „_” powodujący, że kod był brzydszy, a teraz mogę go pominąć.
2) Mówiąc o rzeczach prywatnych, wolę umieszczać definicje metod prywatnych w pliku .m w rozszerzeniu klasy, takim jak:
#import "MyClass.h"
@interface MyClass ()
- (void) someMethod;
- (void) someOtherMethod;
@end
@implementation MyClass
Po co zaśmiecać plik .h sprawami, na które osoby z zewnątrz nie powinny się przejmować? Funkcja empty () działa dla kategorii prywatnych w pliku .m i wydaje kompilowane ostrzeżenia, jeśli nie zaimplementujesz zadeklarowanych metod.
3) Zacząłem umieszczać dealloc na górze pliku .m, tuż pod dyrektywami @synthesize. Czy to, czego zwalniasz, nie powinno znajdować się na szczycie listy rzeczy, o których chcesz pomyśleć w klasie? Jest to szczególnie prawdziwe w środowisku takim jak iPhone.
3.5) W komórkach tabeli, aby każdy element (w tym sama komórka) był nieprzezroczysty dla wydajności. Oznacza to ustawienie we wszystkim odpowiedniego koloru tła.
3.6) Podczas korzystania z NSURLConnection z reguły możesz chcieć zaimplementować metodę delegowania:
- (NSCachedURLResponse *)connection:(NSURLConnection *)connection
willCacheResponse:(NSCachedURLResponse *)cachedResponse
{
return nil;
}
Uważam, że większość połączeń internetowych jest bardzo pojedyncza i jest to raczej wyjątek niż reguła, że będziesz chciał buforować odpowiedzi, szczególnie w przypadku połączeń z usługami internetowymi. Implementacja przedstawionej metody wyłącza buforowanie odpowiedzi.
Interesujące są także dobre wskazówki Josepha Mattiello dotyczące iPhone’a (otrzymane na liście mailingowej iPhone'a). Jest ich więcej, ale były to najbardziej przydatne, jak myślałem (zwróć uwagę, że kilka bitów zostało nieco zmodyfikowanych w stosunku do oryginału, aby zawierały szczegóły oferowane w odpowiedziach):
4) Używaj podwójnej precyzji tylko w razie potrzeby, na przykład podczas pracy z CoreLocation. Upewnij się, że kończysz swoje stałe literą „f”, aby gcc zapisał je jako zmiennoprzecinkowe.
float val = someFloat * 2.2f;
Jest to szczególnie ważne, gdy w someFloat
rzeczywistości może być podwójna, nie potrzebujesz matematyki w trybie mieszanym, ponieważ tracisz precyzję w „val” podczas przechowywania. Chociaż liczby zmiennoprzecinkowe są obsługiwane sprzętowo na iPhone'ach, wykonywanie arytmetyki podwójnej precyzji może zająć więcej czasu niż pojedynczej precyzji. Bibliografia:
Na starszych telefonach podobno obliczenia działają z tą samą prędkością, ale w rejestrach może znajdować się więcej pojedynczych elementów precyzyjnych niż podwójnych, więc w przypadku wielu obliczeń pojedyncza precyzja będzie szybsza.
5) Ustaw swoje właściwości jako nonatomic
. Są atomic
domyślnie i po syntezie utworzony zostanie kod semafora, aby zapobiec problemom z wielowątkowością. 99% z was prawdopodobnie nie musi się o to martwić, a kod jest znacznie mniej rozdęty i bardziej wydajny pod względem pamięci, gdy ustawiony jest na tryb nieatomowy.
6) SQLite może być bardzo, bardzo szybkim sposobem buforowania dużych zbiorów danych. Na przykład aplikacja do mapowania może buforować swoje kafelki w plikach SQLite. Najdroższą częścią jest dysk I / O. Unikaj wielu małych zapisów, wysyłając BEGIN;
i COMMIT;
między dużymi blokami. Używamy na przykład 2-sekundowego timera, który resetuje się przy każdym nowym przesłaniu. Kiedy wygasa, wysyłamy COMMIT; , co powoduje, że wszystkie Twoje zapisy idą w jednym dużym kawałku. SQLite przechowuje dane transakcji na dysk. Dzięki temu zawijanie początku / końca pozwala uniknąć tworzenia wielu plików transakcji, grupując wszystkie transakcje w jeden plik.
Ponadto SQL zablokuje GUI, jeśli znajduje się w głównym wątku. Jeśli masz bardzo długie zapytanie, dobrym pomysłem jest przechowywanie zapytań jako obiektów statycznych i uruchamianie SQL w osobnym wątku. Pamiętaj, aby owinąć wszystko, co modyfikuje bazę danych dla ciągów zapytań w @synchronize() {}
blokach. W przypadku krótkich zapytań wystarczy zostawić rzeczy w głównym wątku, aby ułatwić sobie obsługę.
Więcej wskazówek dotyczących optymalizacji SQLite znajduje się tutaj, choć dokument wydaje się nieaktualny, wiele punktów jest prawdopodobnie nadal dobrych;
http://web.utk.edu/~jplyon/sqlite/SQLite_optimization_FAQ.html
Gdy metody lub funkcje przyjmują argument ciągu formatu, należy upewnić się, że masz kontrolę nad zawartością ciągu formatu.
Na przykład podczas rejestrowania ciągów kuszące jest przekazanie zmiennej ciąg jako jedynego argumentu do NSLog
:
NSString *aString = // get a string from somewhere;
NSLog(aString);
Problem polega na tym, że ciąg może zawierać znaki interpretowane jako ciągi formatu. Może to prowadzić do błędnych wyników, awarii i problemów z bezpieczeństwem. Zamiast tego należy zastąpić zmienną łańcuchową łańcuchem formatującym:
NSLog(@"%@", aString);
Używaj standardowych konwencji nazewnictwa i formatowania Cocoa oraz terminologii, a nie tego, do czego przywykłeś z innego środowiska. Tam są dużo programistów kakao tam, a gdy drugi z nich rozpoczyna pracę z kodem, to będzie dużo bardziej przystępny jeśli wygląda i czuje się podobny do innego kodu Cocoa.
Przykłady tego, co robić, a czego nie robić:
id m_something;
w interfejsie obiektu i nie nazywaj go zmienną składową lub polem ; użyj something
lub _something
dla jego nazwy i nazwij ją zmienną instancji .-getSomething
; właściwa nazwa kakao jest po prostu -something
.-something:
; powinno być-setSomething:
-[NSObject performSelector:withObject:]
nie jest NSObject::performSelector
.Cokolwiek robisz, nie używaj notacji węgierskiej w stylu Win16 / Win32. Nawet Microsoft zrezygnował z tego, przechodząc na platformę .NET.
Historycznie zarządzanie pamięcią gniazd było słabe. Obecnie najlepszą praktyką jest deklarowanie punktów sprzedaży jako właściwości:
@interface MyClass :NSObject {
NSTextField *textField;
}
@property (nonatomic, retain) IBOutlet NSTextField *textField;
@end
Korzystanie z właściwości wyjaśnia semantykę zarządzania pamięcią; zapewnia również spójny wzorzec, jeśli używasz syntezy zmiennych instancji.
UWAGA: pod Xcode 4 jest teraz wbudowany w IDE.
Korzystasz z Clang Static Analyzer, aby - co nie dziwi - analizować kod C i Objective-C (jeszcze nie C ++) w Mac OS X 10.5. Instalacja i obsługa jest banalna:
cd
do katalogu projektu.scan-build -k -V xcodebuild
.(Istnieją pewne dodatkowe ograniczenia itp., W szczególności powinieneś przeanalizować projekt w konfiguracji „Debuguj” - patrz http://clang.llvm.org/StaticAnalysisUsage.html w celu uzyskania szczegółowych informacji - ale to mniej więcej tak do czego sprowadza się.)
Analizator tworzy następnie zestaw stron internetowych, które pokazują prawdopodobne zarządzanie pamięcią i inne podstawowe problemy, których kompilator nie jest w stanie wykryć.
To jest subtelne, ale przydatne. Jeśli przekazujesz siebie jako delegata do innego obiektu, zresetuj delegata tego obiektu przed sobą dealloc
.
- (void)dealloc
{
self.someObject.delegate = NULL;
self.someObject = NULL;
//
[super dealloc];
}
Robiąc to, upewniasz się, że żadne metody delegowania nie zostaną wysłane. Jak masz zamiardealloc
zniknąć w eterze i chcesz się upewnić, że nic nie będzie w stanie wysłać Ci więcej wiadomości przez przypadek. Pamiętaj, że self.someObject może zostać zatrzymany przez inny obiekt (może to być singleton lub pula autorelease lub cokolwiek innego) i dopóki nie powiesz mu „przestań wysyłać mi wiadomości!”, Myśli, że twój obiekt jest prawie niedozwolony jest uczciwa gra.
Przyzwyczajenie się do tego nawyku uratuje cię przed wieloma dziwnymi awariami, które trudno jest debugować.
Ta sama zasada dotyczy również Obserwacji Wartości Kluczowych, a także Powiadomień NS.
Edytować:
Jeszcze bardziej defensywne, zmień:
self.someObject.delegate = NULL;
w:
if (self.someObject.delegate == self)
self.someObject.delegate = NULL;
Memory Management Programming Guide for Cocoa
: Additional cases of weak references in Cocoa include, but are not restricted to, table data sources, outline view items, notification observers, and miscellaneous targets and delegates. In most cases, the weak-referenced object is aware of the other object’s weak reference to it, as is the case for circular references, and is responsible for notifying the other object when it deallocates.
nil == NULL
. Są dokładnie takie same, z wyjątkiem tego, że nil
jest id
i NULL
jest void *
. Twoje stwierdzenie nie jest prawdziwe.
@kendell
Zamiast:
@interface MyClass (private)
- (void) someMethod
- (void) someOtherMethod
@end
Posługiwać się:
@interface MyClass ()
- (void) someMethod
- (void) someOtherMethod
@end
Nowości w Objective-C 2.0.
Rozszerzenia klas opisano w dokumentacji Apple Objective-C 2.0.
„Rozszerzenia klas pozwalają zadeklarować dodatkowe wymagane API dla klasy w lokalizacjach innych niż w bloku klasy podstawowej @interface”
Są więc częścią rzeczywistej klasy - a NIE kategorią (prywatną) oprócz klasy. Subtelna, ale ważna różnica.
()
zamiast (Private)
(lub jakiejś innej nazwy kategorii): możesz ponownie ustawić właściwości jako readwrite, podczas gdy publicznie są one tylko do odczytu. :)
Ponieważ zazwyczaj (1) nie masz bezpośredniej kontroli nad ich czasem życia, automatycznie wydane obiekty mogą utrzymywać się przez stosunkowo długi czas i niepotrzebnie zwiększają powierzchnię pamięci aplikacji. Chociaż na pulpicie może to nie mieć większego znaczenia, na bardziej ograniczonych platformach może to być znaczący problem. Dlatego na wszystkich platformach, a zwłaszcza na platformach o ograniczonym dostępie, za najlepszą praktykę uważa się unikanie stosowania metod prowadzących do automatycznie wydanych obiektów, a zamiast tego zachęca się do korzystania ze wzoru alokacji / inicjowania.
Dlatego zamiast:
aVariable = [AClass convenienceMethod];
w miarę możliwości należy zamiast tego użyć:
aVariable = [[AClass alloc] init];
// do things with aVariable
[aVariable release];
Pisząc własne metody zwracające nowo utworzony obiekt, możesz skorzystać konwencji nazewnictwa Cocoa aby oznaczyć odbiornik, że należy go zwolnić, dodając nazwę metody do „new”.
Dlatego zamiast:
- (MyClass *)convenienceMethod {
MyClass *instance = [[[self alloc] init] autorelease];
// configure instance
return instance;
}
możesz napisać:
- (MyClass *)newInstance {
MyClass *instance = [[self alloc] init];
// configure instance
return instance;
}
Ponieważ nazwa metody zaczyna się od „nowy”, konsumenci twojego API wiedzą, że są odpowiedzialni za zwolnienie otrzymanego obiektu (patrz na przykład metoda NSObjectControllernewObject
).
(1) Możesz przejąć kontrolę, korzystając z własnych lokalnych pul automatycznych wydań. Aby uzyskać więcej informacji na ten temat, zobacz Pule automatycznego wydawania .
NSAutoreleasePool
. Ale dopiero po potwierdzeniu, że to naprawdę problem. Przedwczesna optymalizacja i tak dalej ...
Niektóre z nich zostały już wspomniane, ale oto, co mogę myśleć z góry:
#pragma mark [section]
. Zwykle grupuję według własnych metod, przesłonięć każdej podklasy i wszelkich informacji lub protokołów formalnych. To znacznie ułatwia przejście do dokładnie tego, czego szukam. Na ten sam temat zgrupuj podobne metody (takie jak metody delegowania widoku tabeli), nie po prostu ich nigdzie.#define
zrobi, lub buforowanie tablicy zamiast sortowania jej za każdym razem, gdy potrzebne są dane. Mogę o tym wiele powiedzieć, ale najważniejsze jest to, że nie pisz kodu, dopóki go nie potrzebujesz, bo inaczej profiler ci to nakazuje. Na dłuższą metę znacznie ułatwia utrzymanie.NSLog( @"stub" )
środka, lub w inny sposób chcesz śledzić różne rzeczy.Finish what you start
możesz również użyć // TODO:
do zaznaczenia kodu do wypełnienia, który pojawi się w menu rozwijanym.
Napisz testy jednostkowe. Możesz dużo przetestować Kakao rzeczy, które mogą być trudniejsze w innych ramach. Na przykład za pomocą kodu interfejsu użytkownika można ogólnie sprawdzić, czy rzeczy są połączone tak, jak powinny, i ufać, że będą działać, gdy zostaną użyte. Możesz też łatwo skonfigurować metody stanowe i wywołać delegowane metody, aby je przetestować.
Nie masz też widoczności metody publicznej vs. chronionej vs. prywatnej, która przeszkadza w pisaniu testów dla twoich elementów wewnętrznych.
Złota reguła: Jeśli ty, alloc
to ty release
!
AKTUALIZACJA: Chyba że używasz ARC
copy
, mutableCopy
, new
lub retain
.
Nie pisz Objective-C tak, jakby to był Java / C # / C ++ / etc.
Kiedyś widziałem, jak zespół przyzwyczajony do pisania aplikacji internetowych Java EE próbuje napisać aplikację komputerową Cocoa. Jakby była to aplikacja internetowa Java EE. Dużo latało w pobliżu AbstractFooFactory i FooFactory oraz IFoo i Foo, kiedy wszystko, czego naprawdę potrzebowali, to klasa Foo i ewentualnie protokół Fooable.
Częścią upewnienia się, że tego nie zrobisz, jest prawdziwe zrozumienie różnic w języku. Na przykład nie potrzebujesz abstrakcyjnych fabryk i klas fabrycznych powyżej, ponieważ metody klasy Objective-C są wysyłane tak dynamicznie jak metody instancji i mogą być zastępowane w podklasach.
Pamiętaj, aby dodać do zakładek Magię debugowania strony . To powinien być twój pierwszy przystanek, gdy uderzysz głową w ścianę, próbując znaleźć źródło błędu kakao.
Na przykład powie Ci, jak znaleźć metodę, w której najpierw przydzielono pamięć, która później powoduje awarie (na przykład podczas zamykania aplikacji).
Staraj się unikać tego, co postanowiłem nazywać Newbiecategoryaholism. Kiedy nowicjusze w Objective-C odkrywają kategorie, często szaleją, dodając użyteczne małe kategorie do każdej istniejącej klasy ( „Co? Mogę dodać metodę konwersji liczby na cyfry rzymskie na NSNumber rock!”. ).
Nie rób tego
Twój kod będzie bardziej przenośny i łatwiejszy do zrozumienia dzięki dziesiątkom metod kategorii pokrytych dwoma tuzinami klas podstawowych.
Przez większość czasu, kiedy naprawdę uważasz, że potrzebujesz metody kategorii, aby usprawnić trochę kodu, przekonasz się, że nigdy więcej nie użyjesz tej metody.
Istnieją również inne niebezpieczeństwa, chyba że używasz metod nazw kategorii (a kto oprócz całkowicie szalonego ddribina?) Istnieje szansa, że Apple, wtyczka lub coś innego działającego w twojej przestrzeni adresowej również zdefiniuje tę samą kategorię metoda o tej samej nazwie z nieco innym efektem ubocznym ....
OK. Teraz, gdy zostałeś ostrzeżony, zignoruj „nie rób tego”. Ale ćwicz ekstremalną powściągliwość.
Opieraj się podklasowaniu świata. W kakao wiele się dzieje poprzez delegowanie i używanie podstawowego środowiska wykonawczego, które w innych ramach odbywa się poprzez podklasowanie.
Na przykład w Javie *Listener
często używasz instancji anonimowych podklas, aw .NET często używasz swoich EventArgs
podklas. W Cocoa również tego nie robisz - zamiast tego używana jest akcja target.
Podczas sortowania ciągów, które mają być prezentowane użytkownikowi, nie należy używać prostej compare:
metody. Zamiast tego należy zawsze używać zlokalizowanych metod porównywania, takich jak localizedCompare:
lub localizedCaseInsensitiveCompare:
.
Aby uzyskać więcej informacji, zobacz Wyszukiwanie, porównywanie i sortowanie ciągów .
Zazwyczaj należy używać funkcji deklarowanych właściwości Objective-C 2.0 dla wszystkich swoich właściwości. Jeśli nie są publiczne, dodaj je w rozszerzeniu klasy. Korzystanie z zadeklarowanych właściwości natychmiast poprawia semantykę zarządzania pamięcią i ułatwia sprawdzenie metody dealloc - jeśli zgrupujesz deklaracje właściwości razem, możesz szybko je przeskanować i porównać z implementacją metody dealloc.
Powinieneś dobrze przemyśleć, zanim nie oznaczysz właściwości jako „nieatomowe”. Jak zauważa Przewodnik po języku programowania Objective C , właściwości są domyślnie atomowe i powodują znaczne obciążenie. Co więcej, po prostu przekształcenie wszystkich właściwości w atomowe nie powoduje, że aplikacja jest bezpieczna dla wątków. Zauważ też oczywiście, że jeśli nie określisz „nonatomic” i nie zaimplementujesz własnych metod akcesorów (zamiast ich syntezy), musisz je zaimplementować w sposób atomowy.
Tak jak tym pytaniu , komunikaty, które nil
są ważne w Celu C. Chociaż jest to często zaletą - prowadzi do czystszego i bardziej naturalnego kodu - funkcja ta może czasami prowadzić do osobliwych i trudnych do wyśledzenia błędów, jeśli otrzymasz nil
wartość, gdy się jej nie spodziewałeś.
Użyj NSAssert i przyjaciół. Cały czas używam zera jako ważnego obiektu ... zwłaszcza wysyłanie wiadomości do zera jest całkowicie poprawne w Obj-C. Jeśli jednak naprawdę chcę się upewnić o stanie zmiennej, używam NSAssert i NSParameterAssert, co pomaga w łatwym śledzeniu problemów.
Prosty, ale często zapomniany. Zgodnie ze specyfikacją:
Zasadniczo metody w różnych klasach, które mają ten sam selektor (tę samą nazwę), muszą również mieć takie same typy zwracanych argumentów i argumentów. To ograniczenie jest nakładane przez kompilator, aby umożliwić dynamiczne wiązanie.
w takim przypadku wszystkie selektory o tych samych nazwach, nawet jeśli w różnych klasach , będą uważane za mające identyczne typy return / argument. Oto prosty przykład.
@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;
}
Jeśli używasz systemu Leopard (Mac OS X 10.5) lub nowszego, możesz użyć aplikacji Instruments do wyszukiwania i śledzenia wycieków pamięci. Po zbudowaniu programu w Xcode wybierz Uruchom> Uruchom z Performance Tool> Wycieki.
Nawet jeśli Twoja aplikacja nie wykazuje żadnych wycieków, być może trzymasz obiekty zbyt długo. W Instrumentach możesz do tego użyć instrumentu ObjectAlloc. Wybierz instrument ObjectAlloc w dokumencie Instruments i wyświetl szczegóły instrumentu (jeśli jeszcze go nie pokazuje), wybierając Widok> Szczegół (obok niego powinien znajdować się znacznik wyboru). W obszarze „Długość życia alokacji” w szczegółach ObjectAlloc upewnij się, że wybrałeś przycisk opcji obok „Utworzono i wciąż żyję”.
Teraz, gdy przestaniesz rejestrować aplikację, wybranie narzędzia ObjectAlloc pokaże, ile odwołań do każdego wciąż żyjącego obiektu w aplikacji w kolumnie „# Net”. Upewnij się, że patrzysz nie tylko na własne klasy, ale także na klasy obiektów najwyższego poziomu w plikach NIB. Na przykład, jeśli nie masz okien na ekranie i widzisz odniesienia do wciąż działającego programu NSWindow, być może nie opublikowałeś go w kodzie.
Posprzątaj w dealloc.
To jedna z najłatwiejszych rzeczy do zapomnienia - szczególnie. podczas kodowania z prędkością 150 mil na godzinę. Zawsze, zawsze, zawsze usuwaj atrybuty / zmienne składowe w dealloc.
Lubię używać atrybutów Objc 2 - z nową notacją kropkową - dzięki czemu czyszczenie jest bezbolesne. Często tak proste jak:
- (void)dealloc
{
self.someAttribute = NULL;
[super dealloc];
}
Spowoduje to załatwienie wydania i ustawienie atrybutu na NULL (co uważam za programowanie defensywne - w przypadku, gdy inna metoda w dalszej części dealloc ponownie uzyskuje dostęp do zmiennej członka - rzadko, ale może zdarzyć).
Po włączeniu GC w wersji 10.5 nie jest to już tak bardzo potrzebne - ale może być konieczne wyczyszczenie innych zasobów, które utworzysz, możesz to zrobić w metodzie finalizacji.
-init
i -dealloc
metod, można znaleźć tutaj: mikeash.com/?page=pyblog/...
Wszystkie te komentarze są świetne, ale jestem naprawdę zaskoczony, że nikt nie wspomniał o Przewodniku stylu Objective-C Google, który został opublikowany jakiś czas temu. Myślę, że wykonali bardzo dokładną robotę.
Również częściowo powiązany temat (z miejscem na więcej odpowiedzi!):
Jakie są te małe wskazówki i sztuczki Xcode, o których chciałbyś wiedzieć 2 lata temu? .
Jeden dość oczywisty dla początkującego: użyj funkcji automatycznego wcięcia Xcode dla swojego kodu. Nawet jeśli kopiujesz / wklejasz z innego źródła, po wklejeniu kodu możesz zaznaczyć cały blok kodu, kliknąć go prawym przyciskiem myszy, a następnie wybrać opcję ponownego wcięcia wszystkiego w tym bloku.
Xcode parsuje tę sekcję i wcina ją na podstawie nawiasów, pętli itp. Jest to o wiele bardziej wydajne niż naciśnięcie klawisza spacji lub klawisza tabulacji dla każdej linii.
Wiem, że przeoczyłem to po raz pierwszy w programowaniu Cocoa.
Upewnij się, że rozumiesz obowiązki zarządzania pamięcią dotyczące plików NIB. Odpowiadasz za zwolnienie obiektów najwyższego poziomu w każdym ładowanym pliku NIB. Przeczytaj dokumentację Apple na ten temat.
Włącz wszystkie ostrzeżenia GCC, a następnie wyłącz te, które są regularnie powodowane przez nagłówki Apple w celu zmniejszenia hałasu.
Często też uruchamiaj analizę statyczną Clanga; możesz włączyć to dla wszystkich kompilacji za pomocą ustawienia kompilacji „Uruchom statyczny analizator”.
Napisz testy jednostkowe i uruchom je przy każdej kompilacji.
Zmienne i właściwości
1 / Utrzymywanie nagłówków w czystości, ukrywanie implementacji
Nie dołączaj zmiennych instancji do nagłówka. Zmienne prywatne wprowadzone do kontynuacji klasy jako właściwości. Zmienne publiczne deklarują jako nagłówki właściwości publiczne. Jeśli powinien być tylko odczytany, zadeklaruj go jako tylko do odczytu i zastąp go jako readwrite w klasie kontynuacji. Zasadniczo nie używam zmiennych, tylko właściwości.
2 / Nadaj swoim właściwościom inną niż domyślna nazwę zmiennej, przykład:
@synthesize property = property_;
Powód 1: Wyłapiecie błędy spowodowane zapomnieniem „ja”. podczas przypisywania właściwości Powód 2: Z moich eksperymentów, Leak Analyzer in Instruments ma problemy z wykryciem przeciekającej właściwości o domyślnej nazwie.
3 / Nigdy nie używaj zatrzymania lub zwolnienia bezpośrednio na nieruchomościach (lub tylko w wyjątkowych sytuacjach). W swoim dealloc po prostu przypisz im zero. Właściwości zachowania służą do samodzielnego zarządzania zachowaniem / zwolnieniem. Nigdy nie wiadomo, czy osoba ustawiająca nie na przykład dodaje lub usuwa obserwatorów. Powinieneś używać zmiennej bezpośrednio tylko w jej seterze i getterze.
Wyświetlenia
1 / Umieść każdą definicję widoku w xib, jeśli możesz (wyjątkiem są zwykle dynamiczne ustawienia treści i warstw). Oszczędza czas (jest łatwiejszy niż pisanie kodu), łatwo go zmienić i utrzymuje kod w czystości.
2 / Nie próbuj optymalizować widoków, zmniejszając liczbę wyświetleń. Nie twórz UIImageView w swoim kodzie zamiast xib tylko dlatego, że chcesz do niego dodać widoki podrzędne. Zamiast tego użyj UIImageView jako tła. Struktura widoków może bez problemu obsługiwać setki widoków.
3 / IBOutlety nie zawsze muszą być utrzymywane (lub silne). Zauważ, że większość twoich IBOutletów jest częścią twojej hierarchii widoków, a zatem niejawnie zachowana.
4 / Zwolnij wszystkie IBOutlety w viewDidUnload
5 / Wywołanie viewDidUnload z metody dealloc. Nie jest to domyślnie nazywane.
Pamięć
1 / Automatyczne uwalnianie obiektów podczas ich tworzenia. Wiele błędów jest powodowanych przez przeniesienie wywołania release do jednej gałęzi if-else lub po instrukcji return. Zwolnienie zamiast automatycznego uwalniania powinno być używane tylko w wyjątkowych sytuacjach - np. Gdy czekasz na runloop i nie chcesz, aby twój obiekt był zbyt wcześnie automatycznie uwalniany.
2 / Nawet jeśli używasz automatycznego liczenia referencji, musisz doskonale zrozumieć, w jaki sposób działają metody zatrzymania-wydania. Ręczne korzystanie z retain-release nie jest bardziej skomplikowane niż ARC, w obu przypadkach musisz zająć się wyciekami i cyklami retain. Zastanów się nad ręcznym zachowaniem wydania w dużych projektach lub skomplikowanych hierarchiach obiektów.
Komentarze
1 / Ustaw kod w automatycznej dokumentacji. Każda nazwa zmiennej i nazwa metody powinny informować o tym, co robi. Jeśli kod jest napisany poprawnie (potrzebujesz w tym dużo praktyki), nie będziesz potrzebować żadnych komentarzy do kodu (nie to samo co komentarze do dokumentacji). Algorytmy mogą być skomplikowane, ale kod powinien być zawsze prosty.
2 / Czasami potrzebujesz komentarza. Zwykle w celu opisania nieoczywistego zachowania kodu lub włamania. Jeśli uważasz, że musisz napisać komentarz, najpierw spróbuj przepisać kod, aby był prostszy i nie wymagał komentarzy.
Wcięcie
1 / Nie zwiększaj nadmiernie wcięcia. Większość kodu metody powinna być wcięta na poziomie metody. Zagnieżdżone bloki (jeśli itp.) Zmniejszają czytelność. Jeśli masz trzy zagnieżdżone bloki, powinieneś spróbować umieścić bloki wewnętrzne w osobnej metodzie. Nigdy nie należy używać czterech lub więcej zagnieżdżonych bloków. Jeśli większość kodu metody znajduje się w if, zignoruj warunek if, przykład:
if (self) {
//... long initialization code ...
}
return self;
if (!self) {
return nil;
}
//... long initialization code ...
return self;
Zrozum kod C, głównie struktury C.
Zauważ, że Obj-C jest tylko lekką warstwą OOP w języku C. Powinieneś zrozumieć, jak działają podstawowe struktury kodu w C (wyliczenia, struktury, tablice, wskaźniki itp.). Przykład:
view.frame = CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, view.frame.size.height + 20);
jest taki sam jak:
CGRect frame = view.frame;
frame.size.height += 20;
view.frame = frame;
I wiele więcej
Zarządzaj własnym dokumentem standardów kodowania i często go aktualizuj. Spróbuj uczyć się na swoich błędach. Dowiedz się, dlaczego błąd został utworzony i staraj się go unikać, stosując standardy kodowania.
Nasze standardy kodowania obejmują obecnie około 20 stron, mieszankę standardów kodowania Java, standardów Google Obj-C / C ++ i własnych dodatków. Udokumentuj swój kod, użyj standardowych standardowych wcięć, białych spacji i pustych linii we właściwych miejscach itp.
Bądź bardziej funkcjonalny .
Objective-C jest językiem zorientowanym obiektowo, ale funkcjonuje w stylu Cocoa Framework i jest zaprojektowany w wielu przypadkach.
Istnieje rozdzielność zmienności. Użyj niezmiennych klas jako podstawowego, a zmiennego obiektu jako wtórnego. Na przykład używaj przede wszystkim NSArray i NSMutableArray tylko wtedy, gdy potrzebujesz.
Są czyste funkcje. Nie tak wielu, kup wiele frameworkowych interfejsów API zaprojektowanych jak czysta funkcja. Spójrz na funkcje takie jak CGRectMake()
lub CGAffineTransformMake()
. Oczywiście wskaźnik wygląda bardziej wydajnie. Jednak pośredni argument ze wskaźnikami nie może zaoferować efektów ubocznych. Projektuj struktury w jak największym stopniu. Oddziel nawet obiekty stanu. Użyj -copy
zamiast, -retain
gdy przekazujesz wartość do innego obiektu. Ponieważ stan współużytkowany może cicho wpływać na mutację na wartość w innym obiekcie. Więc nie może być bez skutków ubocznych. Jeśli masz wartość z zewnętrznego obiektu, skopiuj ją. Dlatego ważne jest również zaprojektowanie stanu współdzielonego tak minimalnie, jak to możliwe.
Nie obawiaj się jednak także korzystania z nieczystych funkcji.
Jest leniwa ocena. Zobacz coś jak -[UIViewController view]
własność. Widok nie zostanie utworzony podczas tworzenia obiektu. Zostanie utworzony view
przy pierwszym czytaniu właściwości osoby dzwoniącej . UIImage
nie zostanie załadowany, dopóki nie zostanie faktycznie narysowany. Istnieje wiele implementacji takich jak ten projekt. Tego rodzaju projekty są bardzo pomocne w zarządzaniu zasobami, ale jeśli nie znasz koncepcji leniwej oceny, nie jest łatwo zrozumieć ich zachowanie.
Jest zamknięcie. Używaj C-bloków jak najwięcej. To znacznie uprości twoje życie. Ale przed użyciem przeczytaj jeszcze raz o zarządzaniu pamięcią bloków.
Istnieje półautomatyczny GC. NSAutoreleasePool. Użyj -autorelease
pierwotnego. Użyj ręcznego -retain/-release
pomocniczego, gdy naprawdę potrzebujesz. (np .: optymalizacja pamięci, jawne usuwanie zasobów)
autorelease
że pamięć będzie przechowywana dłużej, a instrukcja retain/release
może zmniejszyć zużycie pamięci w przypadku. Jednak powinna to być wskazówka dotycząca optymalizacji przypadków specjalnych (nawet jeśli zawsze się czujesz!), Nie może być powodem do generalizowania przedwczesnej optymalizacji jako praktyki . W rzeczywistości twoja sugestia nie jest przeciwna do mnie. Wspomniałem o tym, jak naprawdę potrzebuję :)