Yanıtlar:
Standart olduğunu sanmıyorum yapmaya başladığım birkaç şey var:
1) Özelliklerin ortaya çıkmasıyla birlikte, artık "özel" sınıf değişkenlerini önek olarak kullanmak için "_" kullanmıyorum. Sonuçta, bir değişkene diğer sınıflar tarafından erişilebiliyorsa, bunun için bir özellik olmamalı mı? Kod çirkin yapmak için her zaman "_" önekini sevmedim ve şimdi bunu bırakabilirim.
2) Özel şeylerden bahsetmişken, .m dosyası içindeki özel yöntem tanımlarını aşağıdaki gibi bir sınıf uzantısına yerleştirmeyi tercih ederim:
#import "MyClass.h"
@interface MyClass ()
- (void) someMethod;
- (void) someOtherMethod;
@end
@implementation MyClass
Neden .h dosyasını yabancıların umursamaması gereken şeylerle karıştırın? Empty (), .m dosyasındaki özel kategoriler için çalışır ve bildirilen yöntemleri uygulamazsanız derleme uyarıları verir.
3) .loc dosyasının en üstüne, synthesize yönergelerinin hemen altına dealloc koymaya başladım. Anlaştığınız şey bir sınıfta düşünmek istediğiniz şeyler listesinin başında olmamalı mı? Bu özellikle iPhone gibi bir ortamda geçerlidir.
3.5) Tablo hücrelerinde, performans için her öğeyi (hücrenin kendisi dahil) opak yapın. Bu, her şeyde uygun arka plan rengini ayarlamak anlamına gelir.
3.6) Bir NSURLConnection kullanırken, kural olarak delege yöntemini uygulamak isteyebilirsiniz:
- (NSCachedURLResponse *)connection:(NSURLConnection *)connection
willCacheResponse:(NSCachedURLResponse *)cachedResponse
{
return nil;
}
Çoğu web aramasının çok tekil olduğunu ve özellikle web hizmeti çağrıları için önbellek yanıtları isteyeceğiniz kuraldan daha istisna olduğunu görüyorum. Yöntemin gösterildiği gibi uygulanması, yanıtların önbelleğe alınmasını devre dışı bırakır.
Ayrıca, Joseph Mattiello'dan (iPhone posta listesinde alınan) bazı iyi iPhone'a özgü ipuçları da var. Daha fazlası var, ancak bunlar en genel olarak yararlı olduğunu düşündüm (birkaç bitin, yanıtlarda sunulan ayrıntıları içermek için orijinalinden biraz düzenlendiğini unutmayın):
4) CoreLocation ile çalışırken sadece çift hassasiyet kullanın. Gcc'nin float olarak depolaması için sabitlerinizi 'f' ile bitirdiğinizden emin olun.
float val = someFloat * 2.2f;
Bu, someFloat
aslında bir çift olabileceği zaman önemlidir , karışık mod matematiğine ihtiyacınız yoktur, çünkü depolamadaki 'val' da hassasiyet kaybedersiniz. Kayan noktalı sayılar iPhone'larda donanımda desteklenirken, tek duyarlık yerine çift duyarlıklı aritmetik yapmak daha fazla zaman alabilir. Referanslar:
Eski telefonlarda hesaplamalar aynı hızda çalışır, ancak kayıtlarda iki kattan daha fazla tek hassas bileşen olabilir, bu nedenle birçok hesaplama için tek hassasiyet daha hızlı olur.
5) Özelliklerinizi olarak ayarlayın nonatomic
. Onlar konum atomic
varsayılan olarak ve sentez üzerine, semafor kod çoklu iş parçacığı sorunları önlemek için oluşturulacaktır. % 99'unuz muhtemelen bunun için endişelenmenize gerek yoktur ve kod, anatomik olmayan olarak ayarlandığında çok daha az şişirilmiş ve bellek açısından daha verimlidir.
6) SQLite, büyük veri kümelerini önbelleğe almanın çok, çok hızlı bir yolu olabilir. Örneğin bir harita uygulaması, döşemelerini SQLite dosyalarına önbelleğe alabilir. En pahalı kısım disk G / Ç'dir. Büyük bloklar göndererek BEGIN;
ve COMMIT;
arasında çok sayıda küçük yazı yazmaktan kaçının . Örneğin her yeni gönderimde sıfırlanan 2 saniyelik bir zamanlayıcı kullanıyoruz. Sona erdiğinde, COMMIT göndeririz; bu da tüm yazılarınızın büyük bir parça halinde kalmasını sağlar. SQLite, işlem verilerini diske depolar ve bu Başlangıç / Bitiş kaydırma işleminin gerçekleştirilmesi birçok işlem dosyasının oluşturulmasını önler ve tüm işlemleri tek bir dosyada gruplandırır.
Ayrıca, SQL, ana iş parçacığında GUI'nizi engeller. Çok uzun bir sorgunuz varsa, sorgularınızı statik nesneler olarak saklamak ve SQL'inizi ayrı bir iş parçacığında çalıştırmak iyi bir fikirdir. Sorgu dizeleri için veritabanını değiştiren her şeyi @synchronize() {}
bloklar halinde sarmayı unutmayın . Kısa sorgular için, kolaylık sağlamak amacıyla işleri ana iş parçacığında bırakın.
Daha fazla SQLite optimizasyon ipucu burada, ancak belge eski görünüyor olsa da, noktaların çoğu muhtemelen hala iyidir;
http://web.utk.edu/~jplyon/sqlite/SQLite_optimization_FAQ.html
Yöntemler veya işlevler bir biçim dizesi bağımsız değişkeni aldığında, biçim dizesinin içeriği üzerinde kontrolünüz olduğundan emin olmalısınız.
Örneğin, dizeleri günlüğe kaydederken, dize değişkenini şu tek değişken olarak geçirmek cazip gelebilir NSLog
:
NSString *aString = // get a string from somewhere;
NSLog(aString);
Bu sorun, dize biçim dizeleri olarak yorumlanmış karakterler içerebilir olmasıdır. Bu hatalı çıktılara, çökmelere ve güvenlik sorunlarına yol açabilir. Bunun yerine, dize değişkenini bir biçim dizesiyle değiştirmelisiniz:
NSLog(@"%@", aString);
Başka bir ortamdan alışık olduğunuz şey yerine standart Kakao adlandırma ve biçimlendirme kurallarını ve terminolojisini kullanın. Orada çok sayıda Kakao geliştiricisi var ve bunlardan bir diğeri kodunuzla çalışmaya başladığında, diğer Kakao koduna benziyor ve hissediyorsa çok daha ulaşılabilir olacaktır.
Ne yapılacağı ve ne yapılamayacağına örnekler:
id m_something;
Bir nesnenin arayüzünde bildirme ve ona üye değişken veya alan demez ; something
veya _something
adını kullanın ve buna bir örnek değişkeni deyin .-getSomething
; doğru Kakao adı sadece -something
.-something:
; olmalı-setSomething:
-[NSObject performSelector:withObject:]
değil NSObject::performSelector
.Bunu bir kenara bırakacak olursak, yok Win16 / Win32 tarzı Macar notasyonu kullanın. Microsoft bile .NET platformuna geçişten vazgeçti.
Tarihsel olarak, satış noktalarının hafıza yönetimi zayıftı. Mevcut en iyi uygulama, satış noktaları mülk olarak ilan etmektir:
@interface MyClass :NSObject {
NSTextField *textField;
}
@property (nonatomic, retain) IBOutlet NSTextField *textField;
@end
Özelliklerin kullanılması bellek yönetimi semantiğini netleştirir; örnek değişkeni sentezi kullanıyorsanız tutarlı bir model de sağlar.
NOT: Xcode 4 altında bu artık IDE'de yerleşiktir.
Sen kullanmak Clang statik Analyzer şaşırtıcı olmayan - - için C analiz etmek ve Mac OS X 10.5 üzerinde Objective-C kodu (hiçbir C ++ henüz). Yüklemek ve kullanmak önemsizdir:
cd
proje dizininize.scan-build -k -V xcodebuild
.(Bazı ek kısıtlamalar vb. Vardır, özellikle de bir projeyi "Hata Ayıkla" yapılandırmasında analiz etmelisiniz - ayrıntılar için http://clang.llvm.org/StaticAnalysisUsage.html adresine bakın - ama bu aşağı yukarı ne kaynar.)
Daha sonra analizör, sizin için bellek yönetimini ve derleyicinin algılayamadığı diğer temel sorunları gösteren bir dizi web sayfası üretir.
Bu ince ama kullanışlı olanı. Kendinizi başka bir nesneye delege olarak geçiriyorsanız, önünüzdeki nesnenin delegesini sıfırlayın dealloc
.
- (void)dealloc
{
self.someObject.delegate = NULL;
self.someObject = NULL;
//
[super dealloc];
}
Bunu yaparak, başka temsilci yönteminin gönderilmemesini sağlarsınız. Etere dealloc
yaklaşıp yok edildikçe, hiçbir şeyin size yanlışlıkla daha fazla mesaj gönderemeyeceğinden emin olmak istersiniz. Self.someObject öğesinin başka bir nesne tarafından saklanabileceğini unutmayın (tek birton veya otomatik yayın havuzunda veya herhangi bir şeyde olabilir) ve "bana mesaj göndermeyi durdur!" adil bir oyundur.
Bu alışkanlığa girmeniz, sizi hata ayıklamak için acı olan birçok garip çökmeden kurtaracaktır.
Aynı prensip Anahtar Değer İzleme ve NS Bildirimleri için de geçerlidir.
Düzenle:
Daha da savunmacı, değiştirin:
self.someObject.delegate = NULL;
içine:
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
. Bunun nil
bir id
ve NULL
bir a olması dışında tamamen aynıdır void *
. İfadeniz doğru değil.
@kendell
Onun yerine:
@interface MyClass (private)
- (void) someMethod
- (void) someOtherMethod
@end
kullanın:
@interface MyClass ()
- (void) someMethod
- (void) someOtherMethod
@end
Objective-C 2.0'da yeni.
Sınıf uzantıları Apple'ın Objective-C 2.0 Başvurusu bölümünde açıklanmıştır.
"Sınıf uzantıları, birincil sınıf @interface bloğu dışındaki konumlarda bir sınıf için gerekli ek API bildirmenize olanak tanır"
Yani gerçek sınıfın bir parçasıdırlar ve sınıfa ek olarak (özel) bir kategori DEĞİLDİR. İnce ama önemli bir fark.
()
yerine kullanmanın oldukça önemli bir avantajı vardır (Private)
: Özellikleri yalnızca salt okunur durumdayken halka açıkken readwrite olarak yeniden bildirebilirsiniz. :)
Genellikle (1) ömürleri üzerinde doğrudan kontrole sahip olmadığınız için, otomatik olarak serbest bırakılan nesneler nispeten uzun bir süre devam edebilir ve gereksiz yere uygulamanızın bellek kapladığı alanı artırabilir. Masaüstünde bu çok az sonuç olsa da, daha kısıtlı platformlarda bu önemli bir sorun olabilir. Bu nedenle, tüm platformlarda ve özellikle daha kısıtlı platformlarda, otomatik olarak yayımlanan nesnelere yol açacak yöntemleri kullanmaktan kaçınmak için en iyi uygulama olarak kabul edilir ve bunun yerine ayırma / başlatma desenini kullanmanız önerilir.
Böylece, yerine:
aVariable = [AClass convenienceMethod];
mümkün olduğunda, bunun yerine şunları kullanmalısınız:
aVariable = [[AClass alloc] init];
// do things with aVariable
[aVariable release];
Yeni oluşturulan bir nesneyi döndüren kendi yöntemlerinizi yazarken , alıcıya yöntem adını "yeni" ile başlatarak serbest bırakılması gerektiğini işaretlemek için Cocoa'nın adlandırma kuralından yararlanabilirsiniz.
Böylece, yerine:
- (MyClass *)convenienceMethod {
MyClass *instance = [[[self alloc] init] autorelease];
// configure instance
return instance;
}
yazabilirsiniz:
- (MyClass *)newInstance {
MyClass *instance = [[self alloc] init];
// configure instance
return instance;
}
Yöntem adı "yeni" ile başladığından, API'nızın tüketicileri alınan nesneyi serbest bırakmaktan sorumlu olduklarını bilir (örneğin, bkz . NSObjectController newObject
yöntemi ).
(1) Kendi yerel otomatik yayın havuzlarınızı kullanarak kontrolü ele alabilirsiniz. Bu konuda daha ayrıntılı bilgi için bkz otomatik salma Havuzları .
NSAutoreleasePool
. Ama sadece bunun gerçekten bir sorun olduğunu onayladıktan sonra. Erken optimizasyon ve tüm bunlar ...
Bunlardan bazılarından daha önce bahsedilmişti, ancak başımın üstünden düşünebileceğim şey:
#pragma mark [section]
. Genellikle kendi yöntemlerime, her alt sınıfın geçersiz kılmalarına ve herhangi bir bilgi veya resmi protokole göre gruplandırırım. Bu, tam olarak aradığım şeye atlamayı çok daha kolay hale getirir. Aynı konuda, benzer yöntemleri (tablo görünümünün temsilci yöntemleri gibi) birlikte gruplayın, yalnızca hiçbir yere yapıştırmayın.#define
irade yaparken yapmak veya veriye her ihtiyaç duyulduğunda sıralamak yerine bir diziyi önbelleğe almak gibi bir çok şeyi kapsar . Bu konuda söyleyebileceğim çok şey var, ancak sonuçta ihtiyacınız olana kadar kod yazmayın veya profiler size söyler. Uzun vadede işlerin bakımını çok daha kolay hale getirir.NSLog( @"stub" )
içine koyarak belirtin veya şeyleri takip etmek istersiniz.Finish what you start
de kullanabilirsiniz // TODO:
.
Birim testleri yazma. Kakao'da diğer çerçevelerde daha zor olabilecek birçok şeyi test edebilirsiniz . Örneğin, UI kodu ile, genellikle şeylerin olması gerektiği gibi bağlandığını doğrulayabilir ve kullanıldıklarında çalışacaklarına güvenebilirsiniz. Ayrıca, durumu test edebilir ve bunları test etmek için delege yöntemlerini kolayca çağırabilirsiniz.
Ayrıca, dahili cihazlarınız için testler yazma yolunda kamuya karşı korumalı ve özel yöntem görünürlüğüne sahip değilsiniz.
Altın Kural: Eğer sen alloc
o zaman sen release
!
GÜNCELLEME: ARC kullanmadığınız sürece
copy
, mutableCopy
, new
veya retain
.
Objective-C'yi Java / C # / C ++ / etc gibi yazmayın.
Bir keresinde Java EE web uygulamalarını yazmak için kullanılan bir ekibin bir Cocoa masaüstü uygulaması yazmaya çalıştığını gördüm. Java EE web uygulamasıymış gibi. Bir sürü AbstractFooFactory ve FooFactory ve IFoo ve Foo gerçekten ihtiyaç duydukları şey bir Foo sınıfı ve muhtemelen Fooable protokolüydü.
Bunu yapmamanızı sağlamanın bir parçası da dildeki farklılıkları gerçekten anlamaktır. Örneğin, yukarıdaki abstract factory ve factory sınıflarına ihtiyacınız yoktur, çünkü Objective-C sınıfı yöntemleri örnek yöntemleri kadar dinamik olarak gönderilir ve alt sınıflarda geçersiz kılınabilir.
Hata Ayıklama Sihirli sayfasına yer işareti koyduğunuzdan emin olun . Bu, bir Kakao böceğinin kaynağını bulmaya çalışırken başınızı duvara vururken ilk durağınız olmalıdır.
Örneğin, daha sonra kilitlenmelere neden olan belleği ilk olarak ayırdığınız yöntemi nasıl bulacağınızı söyleyecektir (uygulama sonlandırma sırasında olduğu gibi).
Şimdi Newbiecategoryaholism demeye karar verdiğim şeylerden kaçınmaya çalışın. Objective-C için yeni başlayanlar kategorileri keşfettiklerinde, genellikle var olan her sınıfa yararlı küçük kategoriler ekleyerek ( "Ne? İ bir sayıyı Romen rakamlarına NSNumber rock on dönüştürmek için bir yöntem ekleyebilir!" ).
Bunu yapma.
İki düzine temel sınıfının üzerine serpilmiş düzinelerce küçük kategori yöntemi ile kodunuz daha taşınabilir ve anlaşılması daha kolay olacaktır.
Çoğu zaman, gerçekten bazı kodları düzene sokmak için bir kategori yöntemine ihtiyacınız olduğunu düşündüğünüzde, asla yöntemi tekrar kullanamayacağınızı göreceksiniz.
Kategori yöntemlerinizi adlandırmadığınız sürece (ve tamamen çılgın ddribinin yanı sıra kim?) Apple'ın veya bir eklentinin veya adres alanınızda çalışan başka bir şeyin de aynı kategoriyi tanımlaması ihtimali vardır. biraz farklı bir yan etkisi ile aynı adı taşıyan yöntem ....
TAMAM. Artık uyarıldığınıza göre, "bu kısmı yapma" yı görmezden gelin. Ancak aşırı kısıtlama uygulayın.
Dünyaya alt sınıfa diren. Kakao'da, diğer çerçevelerde alt sınıflandırma yoluyla yapılan temel çalışma süresinin devri ve kullanımı yoluyla çok şey yapılır.
Örneğin, Java'da anonim *Listener
alt sınıf örneklerini çok kullanırsınız ve .NET'te EventArgs
alt sınıflarınızı çok kullanırsınız. Kakao'da ikisini de yapmazsınız - bunun yerine hedef eylem kullanılır.
Dizeleri kullanıcıya sunacak şekilde sıraladığınızda, basit compare:
yöntemi kullanmamalısınız . Bunun yerine, her zaman localizedCompare:
veya gibi yerelleştirilmiş karşılaştırma yöntemlerini kullanmalısınız localizedCaseInsensitiveCompare:
.
Daha fazla ayrıntı için bkz . Dizeleri Arama, Karşılaştırma ve Sıralama .
Tüm özellikleriniz için genellikle Objective-C 2.0 Bildirilen Özellikler özelliğini kullanmalısınız. Herkese açık değilse, bunları bir sınıf uzantısına ekleyin. Bildirilen özellikleri kullanmak, bellek yönetimi semantiğini hemen netleştirir ve dealloc yönteminizi kontrol etmenizi kolaylaştırır - özellik bildirimlerinizi birlikte gruplandırırsanız, bunları hızlı bir şekilde tarayabilir ve dealloc yönteminizin uygulanmasıyla karşılaştırabilirsiniz.
Özellikleri 'anatomik olmayan' olarak işaretlemeden önce çok düşünmelisiniz. As Dil Rehberi Programlama Objective C notları, özellikleri varsayılan olarak atom vardır ve tabi hatırı sayılır havai. Ayrıca, tüm özelliklerinizi atomik yapmak uygulamanızı iş parçacığı açısından güvenli hale getirmez. Ayrıca, elbette, 'anatomik olmayan' belirtmezseniz ve kendi erişimci yöntemlerinizi (bunları sentezlemek yerine) uygularsanız, bunları atomik bir şekilde uygulamanız gerektiğini unutmayın.
Bu soruda belirtildiği gibi , iletiler nil
Objective-C'de geçerlidir. Bu genellikle bir avantaj olsa da - daha temiz ve daha doğal kodlara yol açıyor - özellik, nil
beklemediğiniz bir değer alırsanız bazen tuhaf ve izlenmesi zor hatalara yol açabilir .
NSAssert ve arkadaşlarını kullanın. Nil'i her zaman geçerli nesne olarak kullanıyorum ... özellikle nil'e mesaj göndermek Obj-C'de son derece geçerli. Ancak, bir değişkenin durumundan gerçekten emin olmak istersem, NSAssert ve NSParameterAssert kullanıyorum, bu da problemlerin kolayca izlenmesine yardımcı oluyor.
Basit ama unutulmuş bir tane. Spec göre:
Genel olarak, aynı seçiciye (aynı ada) sahip farklı sınıflardaki yöntemler de aynı dönüş ve bağımsız değişken türlerini paylaşmalıdır. Bu sınırlama derleyici tarafından dinamik bağlanmaya izin vermek için uygulanır.
bu durumda , farklı sınıflarda bile olsa , aynı adlandırılmış seçicilerin özdeş dönüş / bağımsız değişken türlerine sahip olduğu kabul edilecektir. İşte basit bir örnek.
@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;
}
Leopard (Mac OS X 10.5) veya daha yenisini kullanıyorsanız, bellek sızıntılarını bulmak ve izlemek için Instruments uygulamasını kullanabilirsiniz. Programınızı Xcode'da oluşturduktan sonra Çalıştır> Performans Aracı ile Başlat> Sızıntılar'ı seçin.
Uygulamanız herhangi bir sızıntı göstermese bile, nesneleri çok uzun süre saklıyor olabilirsiniz. Enstrümanlar'da bunun için ObjectAlloc enstrümanını kullanabilirsiniz. Enstrümanlar belgenizdeki ObjectAlloc cihazını seçin ve Görünüm> Detay (yanında bir onay işareti bulunmalıdır) öğesini seçerek enstrümanın ayrıntılarını (zaten gösterilmiyorsa) getirin. ObjectAlloc ayrıntısındaki "Ayırma Ömrü" altında, "Oluşturulan ve Hareketsiz Yaşam" ın yanındaki radyo düğmesini seçtiğinizden emin olun.
Şimdi uygulamanızı kaydetmeyi her durdurduğunuzda, ObjectAlloc aracını seçtiğinizde "# Net" sütununda uygulamanızda hala yaşayan her nesneye kaç tane başvuru olduğu gösterilecektir. Sadece kendi sınıflarınıza değil, aynı zamanda NIB dosyalarınızın üst düzey nesnelerinin sınıflarına da baktığınızdan emin olun. Örneğin, ekranda pencereniz yoksa ve hala canlı olan bir NSWindow'a başvurular görürseniz, kodunuzda yayınlamamış olabilirsiniz.
Dealloc'da temizleyin.
Bu unutulması en kolay şeylerden biri - esp. 150mph'de kodlama yaparken. Her zaman, her zaman, dealloc'daki niteliklerinizi / üye değişkenlerinizi her zaman temizleyin.
Objc 2 özelliklerini - yeni nokta gösterimi ile - kullanmayı seviyorum , bu yüzden temizliği ağrısız hale getiriyor. Genellikle şu kadar basit:
- (void)dealloc
{
self.someAttribute = NULL;
[super dealloc];
}
Bu, sizin için sürümle ilgilenecek ve özniteliği NULL olarak ayarlayacaktır (ki bu da savunmacı programlamayı düşünüyorum - dealloc'da başka bir yöntemin üye değişkene tekrar erişmesi durumunda - nadir ancak olabilir ).
GC 10.5'te açıldığında, buna artık gerek yoktur - ancak yine de oluşturduğunuz diğer kaynakları temizlemeniz gerekebilir, bunun yerine sonlandırma yönteminde bunu yapabilirsiniz.
-init
ve -dealloc
yöntemlerinin kullanılıp kullanılmayacağına ilişkin daha geniş bir görünümü burada bulabilirsiniz: mikeash.com/?page=pyblog/…
Tüm bu yorumlar harika, ancak kimsenin Google'ın bir süre önce yayınlanan Objective-C Stil Kılavuzu'ndan bahsetmediğine gerçekten şaşırdım . Bence çok kapsamlı bir iş çıkardılar.
Ayrıca, yarı ilgili konu (daha fazla yanıt için yer var!):
Yaklaşık 2 yıl önce bilmenizi istediğiniz küçük Xcode ipuçları ve püf noktaları nelerdir? .
Yeni başlayanlar için oldukça açık olanı: Xcode'un kodunuz için otomatik girintileme özelliğini kullanın. Başka bir kaynaktan kopyala / yapıştırıyor olsanız bile, kodu yapıştırdıktan sonra, tüm kod bloğunu seçebilir, sağ tıklayabilir ve ardından o bloktaki her şeyi yeniden girintili hale getirme seçeneğini belirleyebilirsiniz.
Xcode aslında bu bölüm boyunca ayrıştırır ve parantez, döngüler vb. Temel alır.
Kakao programlamaya ilk girdiğimde bunu göz ardı ettiğimi biliyorum.
NIB dosyalarıyla ilgili bellek yönetimi sorumluluklarını anladığınızdan emin olun. Yüklediğiniz herhangi bir NIB dosyasında en üst düzey nesneleri serbest bırakmak sizin sorumluluğunuzdadır. Apple'ın konuyla ilgili Dokümantasyonunu okuyun .
Tüm GCC uyarılarını açın, ardından Apple'ın başlıklarının gürültüyü azaltması için düzenli olarak neden olanları kapatın.
Ayrıca Clang statik analizini sık sık çalıştırın; "Statik Analizörü Çalıştır" derleme ayarıyla tüm derlemeler için etkinleştirebilirsiniz.
Birim testleri yazın ve bunları her derlemede çalıştırın.
Değişkenler ve özellikler
1 / Başlıklarınızı temiz tutmak, uygulamayı gizlemek
Başlığınıza örnek değişkenleri eklemeyin. Özel değişkenler sınıfın devamı niteliğindedir. Genel değişkenler, başlığınızda genel mülkler olarak bildirilir. Sadece okunması gerekiyorsa, bunu salt okunur olarak ilan edin ve sınıf devamında readwrite olarak üzerine yazın. Temelde değişkenleri hiç kullanmıyorum, sadece özellikler.
2 / Özelliklerinize varsayılan olmayan bir değişken adı verin, örnek:
@synthesize property = property_;
Sebep 1: "Kendini" unutmanın neden olduğu hataları yakalayacaksınız. özelliği atarken. Sebep 2: Deneylerimden, Enstrümanlar'daki Sızıntı Analizörü varsayılan isimle sızıntı özelliğini tespit etmekte sorun yaşıyor.
3 / Asla doğrudan mülklerde (veya sadece çok istisnai durumlarda) alıkoymayın veya bırakmayın. Senin dealloc sadece onlara bir nil atar. Koruma özellikleri, tutma / bırakma işlemlerini kendileri gerçekleştirmeyi amaçlamaktadır. Bir ayarlayıcının örneğin gözlemci eklemek veya çıkarmak olmadığını asla bilemezsiniz. Değişkeni doğrudan yalnızca ayarlayıcı ve alıcısında kullanmalısınız.
Görüntüleme
1 / Mümkünse her görünüm tanımını xib içine koyun (istisna genellikle dinamik içerik ve katman ayarlarıdır). Zaman kazandırır (kod yazmaktan daha kolaydır), değiştirilmesi kolaydır ve kodunuzu temiz tutar.
2 / Görüntüleme sayısını azaltarak görünümleri optimize etmeye çalışmayın. Sadece alt görünümler eklemek istediğiniz için kodunuzda xib yerine UIImageView oluşturmayın. Bunun yerine arka plan olarak UIImageView kullanın. Görünüm çerçevesi yüzlerce görünümü sorunsuz bir şekilde ele alabilir.
3 / IBOutlet'lerin her zaman tutulması (veya güçlü) olması gerekmez. IBOutlet'larınızın çoğunun görünüm hiyerarşinizin bir parçası olduğunu ve dolayısıyla dolaylı olarak saklandığını unutmayın.
4 / viewDidUnload'daki tüm IBOutlet'leri serbest bırakın
5 / dealloc yönteminizden viewDidUnload'u çağırın. Örtük olarak çağrılmaz.
Hafıza
1 / Nesneleri oluştururken otomatik serbest bırak. Birçok hata, sürüm çağrınızı bir if-else şubesine veya bir return ifadesinden sonra taşımasından kaynaklanır. Otomatik serbest bırakma yerine serbest bırakma yalnızca istisnai durumlarda kullanılmalıdır - örneğin bir runloop beklerken ve nesnenizin çok erken otomatik olarak yayınlanmasını istemediğinizde.
2 / Otomatik Referans Sayımı kullanıyor olsanız bile, tutma-bırakma yöntemlerinin nasıl çalıştığını mükemmel bir şekilde anlamalısınız. Tutmayı bırakmayı manuel olarak kullanmak ARC'den daha karmaşık değildir, her iki durumda da sızıntılar ve tutuş döngüleri hakkında bir şey yapmanız gerekir. Elde bırakmayı büyük projelerde veya karmaşık nesne hiyerarşilerinde manuel olarak kullanmayı düşünün.
Yorumlar
1 / Kodunuzu otomatik olarak belgelendirin. Her değişken adı ve yöntem adı ne yaptığını söylemelidir. Kod doğru yazılmışsa (bu konuda çok fazla pratik yapmanız gerekir), kod yorumlarına (doküman yorumlarıyla aynı değildir) ihtiyacınız olmayacaktır. Algoritmalar karmaşık olabilir, ancak kod her zaman basit olmalıdır.
2 / Bazen bir yoruma ihtiyacınız olabilir. Genellikle belirgin olmayan bir kod davranışı veya hack'i tanımlamak için kullanılır. Yorum yazmak zorunda olduğunuzu düşünüyorsanız, önce kodu daha basit ve yorumlara ihtiyaç duymadan yeniden yazmayı deneyin.
girinti
1 / Girintiyi fazla artırmayın. Yöntem kodunuzun çoğu yöntem düzeyinde girintili olmalıdır. İç içe bloklar (vb. İçin) okunabilirliği azaltır. Üç iç içe blokunuz varsa, iç blokları ayrı bir yönteme koymaya çalışmalısınız. Dört veya daha fazla iç içe blok asla kullanılmamalıdır. Yöntem kodunuzun çoğu bir if içinde ise, if koşulunu reddedin, örnek:
if (self) {
//... long initialization code ...
}
return self;
if (!self) {
return nil;
}
//... long initialization code ...
return self;
C kodunu, özellikle C yapılarını anlama
Obj-C'nin C dili üzerinde sadece hafif bir OOP katmanı olduğuna dikkat edin. C'deki temel kod yapılarının nasıl çalıştığını anlamalısınız (numaralar, yapılar, diziler, işaretçiler vb.). Misal:
view.frame = CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, view.frame.size.height + 20);
aynıdır:
CGRect frame = view.frame;
frame.size.height += 20;
view.frame = frame;
Ve daha fazlası
Kendi kodlama standartları belgenizi koruyun ve sık sık güncelleyin. Böceklerinizden öğrenmeye çalışın. Bir hatanın neden oluşturulduğunu anlayın ve kodlama standartlarını kullanarak bundan kaçınmaya çalışın.
Kodlama standartlarımız şu anda yaklaşık 20 sayfa, Java Kodlama Standartları, Google Obj-C / C ++ Standartları ve kendi eklemelerimizin bir karışımına sahiptir. Kodunuzu belgeleyin, standart standart girinti, beyaz boşluklar ve doğru yerlerde boş satırlar vb. Kullanın.
Daha işlevsel olun .
Objective-C nesne yönelimli bir dildir, ancak Kakao çerçeve işlevsel stil farkında ve birçok durumda işlevsel stil tasarlanmıştır.
Değişebilirlik ayrılığı vardır. Birincil olarak değişmez sınıflar ve ikincil olarak değişebilir nesne kullanın . Örneğin, öncelikle NSArray kullanın ve yalnızca ihtiyacınız olduğunda NSMutableArray kullanın.
Saf fonksiyonlar var. Çok değil, birçok çerçeve API satın saf işlev gibi tasarlanmıştır. CGRectMake()
Veya gibi işlevlere bakın CGAffineTransformMake()
. Açıkçası işaretçi formu daha verimli görünüyor. Bununla birlikte, işaretçilerle dolaylı argüman yan etki yaratmaz. Yapıları tamamen mümkün olduğunca tasarlayın. Durum nesnelerini bile ayırın. Başka bir nesneye değer iletmek -copy
yerine kullanın -retain
. Çünkü paylaşılan durum mutasyonun diğer nesnelerdeki değere sessizce etki edebilmesini sağlar. Bu yüzden yan etkisi yoktur. Nesneden harici bir değeriniz varsa, kopyalayın. Bu nedenle, paylaşılan durumu olabildiğince az tasarlamak da önemlidir.
Ancak saf olmayan işlevleri kullanmaktan da korkmayın.
Tembel bir değerlendirme var. -[UIViewController view]
Mülkiyet gibi bir şey görün . Nesne oluşturulduğunda görünüm oluşturulmaz. Arayan kişi view
özelliği ilk kez okurken oluşturulur . UIImage
gerçekte çizilene kadar yüklenmeyecektir. Bu tasarım gibi birçok uygulama var. Bu tür tasarımlar kaynak yönetimi için çok yararlıdır, ancak tembel değerlendirme kavramını bilmiyorsanız, bunların davranışlarını anlamak kolay değildir.
Kapanış var. C bloklarını mümkün olduğunca kullanın. Bu hayatınızı büyük ölçüde kolaylaştıracaktır. Ancak kullanmadan önce blok bellek yönetimi hakkında bir kez daha okuyun.
Yarı otomatik GC var. NSAutoreleasePool. -autorelease
Birincil kullanın . -retain/-release
Gerçekten ihtiyacınız olduğunda manuel ikincil kullanın . (ör: bellek optimizasyonu, açık kaynak silme)
autorelease
Genel olarak hafızayı daha uzun tutacağına katılıyorum ve manuel retain/release
, bu durumda hafıza tüketimini azaltabilir. Bununla birlikte, özel durum optimizasyonu için rehberlik olmalıdır (her zaman hissediyor olsanız bile!), Erken optimizasyonu pratik olarak genelleştirmenin nedeni olamaz . Aslında öneriniz benden farklı değil. Gerçekten ihtiyaç olarak bahsetmiştim :)