it-swarm.dev

Objective-C and Cocoa yazarken kullandığınız en iyi uygulamalar nelerdir?

HIG (ki bu oldukça kullanışlı!) Hakkında bilgim var, ancak Objective-C yazarken ve özellikle de Cocoa (veya CocoaTouch) kullanırken hangi programlama uygulamalarını kullanıyorsunuz?.

346
pixel

Yapmaya başladığım ve standart olmadığını düşündüğüm birkaç şey var:

1) Özelliklerin gelişmesiyle, artık "özel" sınıf değişkenlerini öneklemek için "_" kullanmıyorum. Sonuçta, bir değişken diğer sınıflar tarafından erişilebilirse, bunun için bir özellik olmamalı mı? Her zaman kod çirkin yapmak için "_" önekini beğenmedim, ve şimdi onu dışarıda bırakabilirim.

2) Özel şeylerden bahsetmişken, .m dosyası içindeki özel yöntem tanımlarını şöyle bir sınıf uzantısına yerleştirmeyi tercih ederim:

#import "MyClass.h"

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

@implementation MyClass

.H Dosyasını neden dışarı çıkarmayacaklarına dikkat etmeliyim? Empty (), .m dosyasındaki özel kategoriler için çalışır ve bildirilen yöntemleri uygulamazsanız derleme uyarıları verir.

3) .m dosyasının en üstüne, @synthesize yönergelerinin hemen altına dealloc koymaya başladım. Aldatmayacağınız şey, bir sınıfta düşünmek istediğiniz şeyler listesinin başında olmalı mı? Bu özellikle iPhone gibi bir ortamda geçerlidir.

3.5) Tablo hücrelerinde, her elemanı (hücrenin kendisi de dahil) performans için 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 aramaları için yanıtların önbelleğe alınmasını istediğiniz kuraldan daha fazla istisna olduğunu biliyorum. Yöntemin gösterildiği gibi uygulanması, yanıtların önbelleğe alınmasını engeller.

Ayrıca ilgi çekici, Joseph Mattiello'dan (iPhone posta listesinde alınan) bazı iPhone'a özel ipuçları. Dahası var, ancak bunlar düşündüğüm en genel olanıydı (cevaplarda sunulan detayları eklemek için birkaç bitin orijinalden biraz düzenlenmiş olduğunu unutmayın):

4) CoreLocation ile çalışırken olduğu gibi, sadece çift hassasiyeti kullanın. Gcc'nin yüzer olarak saklanmasını sağlamak için sabitlerinizi 'f' ile sonlandırdığınızdan emin olun.

float val = someFloat * 2.2f;

Bu, someFloat gerçekte çift olabileceği zaman çok önemlidir, çünkü karışık mod matematiğe ihtiyacınız yoktur, çünkü depolamada 'val' hassasiyetini kaybedersiniz. Kayan nokta sayıları iPhone'larda donanımda desteklenirken, tekli hassasiyetin aksine çift duyarlıklı aritmetik işlem yapmak daha uzun sürebilir. Referanslar:

Eski telefonlarda sözde hesaplamalar aynı hızda çalışıyor ancak kayıtlarda iki kattan daha fazla tek bileşenli bileşeniniz olabilir, bu nedenle birçok hesaplama için tek hassasiyet daha hızlı sonuçlanır.

5) Özelliklerinizi nonatomic olarak ayarlayın. Bunlar varsayılan olarak atomic'tır ve sentez sırasında çoklu iş parçacığı sorunlarını önlemek için semafor kodu oluşturulur. % 99'unuz muhtemelen bu konuda endişelenmenize gerek duymuyor ve kod, daha az şişirilmiş ve ademitomik olarak ayarlandığında hafıza açısından daha verimli.

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ın arasına BEGIN; ve COMMIT; göndererek birçok küçük yazma işleminden kaçının. Her yeni gönderimde sıfırlanan bir 2 saniyelik zamanlayıcı kullanıyoruz. Süresi dolduğunda, KOMİTE göndeririz; tüm yazarlarınızın büyük bir yığın halinde gitmesine neden olur. SQLite, işlem verilerini diske depolar ve bu Başlangıç ​​/ Bitiş paketlemesini yapmak, tüm işlemleri tek bir dosyada gruplandırarak birçok işlem dosyasının oluşturulmasını önler.

Ayrıca, ana iş parçacığınızda SQL, GUI'nizi engeller. Çok uzun bir sorunuz varsa, sorgularınızı statik nesneler olarak saklamak ve SQL'inizi ayrı bir dizide çalıştırmak iyi bir fikirdir. Sorgu dizeleri için veritabanını değiştiren her şeyi, @synchronize() {} blok içinde kaydırdığınızdan emin olun. Kısa sorgular için, kolaylık sağlamak için işleri ana iş parçacığına bırakın.

Daha fazla SQLite optimizasyon ipucu burada, ancak doküman güncel olmasa da, puanların çoğu hala iyi;

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

Bilinmeyen dizeleri biçim dizeleri olarak kullanmayın

Yöntemler veya işlevler bir biçim dizesi argümanını aldığında, biçim dizesinin içeriği üzerinde kontrol sahibi olduğunuzdan emin olmalısınız.

Örneğin, dizeleri günlüğe kaydederken, dize değişkenini tek değişken olarak NSLog öğesine iletmek cazip gelir:

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

Bununla ilgili sorun, dizgenin biçim dizeleri olarak yorumlanan karakterleri içermesidir. Bu, hatalı çıktılara, çökmelere ve güvenlik sorunlarına yol açabilir. Bunun yerine, dizge değişkenini bir biçim dizgisine değiştirmelisiniz:

    NSLog(@"%@", aString);
110
mmalc

Başka bir ortamdan alıştığınız şey yerine, standart Kakao adlandırma ve biçimlendirme kurallarını ve terimleri kullanın. Orada are Çok sayıda Kakao geliştiricisi var ve bunlardan bir tanesi kodunuzla çalışmaya başladığında, diğer Kakao koduna benziyor ve ona benziyorsa çok daha ulaşılabilir olacak.

Ne yapılacağı ve ne yapmama örnekleri:

  • Bir nesnenin arayüzünde id m_something; öğesini bildirmeyin ve buna bir üye değişkeni veya alan ; onun adı için something veya _something kullanın ve buna bir örnek değişkeni olarak adlandırın.
  • Bir alıcıyı adlandırma -getSomething; uygun kakao adı sadece -something.
  • Bir ayarlayıcıya ad vermeyin -something:; olması gereken -setSomething:
  • Yöntem adı, argümanlarla serpiştirilmiş ve sütunlar; -[NSObject performSelector:withObject:], NSObject::performSelector değil.
  • Alt çizgi (CamelCase), alt çizgi (alt çizgi) yerine yöntem adlarında, parametrelerde, değişkenlerde, sınıf adlarında vb.
  • Sınıf adları büyük harf, değişken ve küçük harf içeren yöntem adları ile başlar.

Ne yaparsanız yapın, yapma Win16/Win32 tarzı Macarca notasyonu kullanın. Microsoft bile .NET platformuna taşınmaktan vazgeçti.

108
Chris Hanson

IBOutlets

Tarihsel olarak, çıkışların hafıza yönetimi zayıftı. Mevcut en iyi uygulama, prizleri mülk olarak bildirmektir:

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

Özelliklerin kullanılması, bellek yönetimi anlamını açıklar; Örnek değişken sentezi kullanıyorsanız, ayrıca tutarlı bir desen sağlar.

107
mmalc

LLVM/Clang Statik Analizörünü kullanın

NOT: Xcode 4'te bu şimdi IDE'ye yerleştirilmiştir.

Mac OS X 10.5'te Clang Static Analyzer to - şaşırtıcı olmayan bir şekilde - C ve Objective-C kodunuzu (henüz C++ yok) kullanın. Yüklemek ve kullanmak çok önemlidir:

  1. En son sürümü bu sayfa adresinden indirin.
  2. Komut satırından cd proje dizininize.
  3. scan-build -k -V xcodebuild işlemini yürütün.

(Bazı ek kısıtlamalar vb. Vardır, özellikle bir projeyi "Hata Ayıklama" yapılandırmasında analiz etmelisiniz - bkz. http://clang.llvm.org/StaticAnalysisUsage.html ayrıntılar için - ama bu aşağı yukarı kaynaştığı şeydir.)

Analizör, sizin için olası bellek yönetimini ve derleyicinin tespit edemediği diğer temel sorunları gösteren sizin için bir dizi web sayfası hazırlar.

98
mmalc

Bu, ince olanı ama kullanışlı olanı. Kendinizi bir temsilci olarak başka bir nesneye devrediyorsanız, dealloc öğesinden önce bu nesnenin temsilcisini sıfırlayın.

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

Bunu yaparak daha fazla delege yönteminin gönderilmemesini sağlarsınız. dealloc yapmak üzereyken ve etere girerken, hiçbir şeyin size yanlışlıkla bir daha mesaj gönderemeyeceğinden emin olmak istersiniz. Self.someObject öğesinin başka bir nesne tarafından korunabileceğini (bir singleton veya otomatik yayın havuzunda ya da her neyse) hatırlayabildiğini ve "bana mesaj göndermeyi bırak!" Diyene kadar, hemen hemen tamamen-tükenmek üzere olan nesnenizi düşündüğünü unutmayın. adil bir oyundur.

Bu alışkanlık haline gelmek sizi hata ayıklamak için acı veren birçok garip kazadan kurtaracaktır.

Aynı prensip Anahtar Değer Gözlemciliği ve NSNotifications için de geçerlidir.

Düzenle:

Daha da savunmacı, değişim:

self.someObject.delegate = NULL;

içine:

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

@kendell

Onun yerine:

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

Kullanın:

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

Objective-C 2.0'daki Yenilikler.

Sınıf uzantıları Apple's Objective-C 2.0 Referansında açıklanmıştır.

"Sınıf uzantıları, birincil sınıf @ interface bloğu dışındaki konumlardaki bir sınıf için gereken ek API'yi bildirmenize izin verir"

Bu yüzden onlar gerçek sınıfın bir parçasıdır - ve sınıfa ek olarak (özel) bir kategori de DEĞİLDİR. İnce ama önemli bir fark.

87
schwa

Otomatik yayın önlemek

Genellikle (1) kullanım ömürleri üzerinde doğrudan kontrol sahibi olmadığınızdan, otomatik olarak yayınlanmış nesneler nispeten uzun bir süre boyunca devam edebilir ve uygulamanızın bellek izini gereksiz yere artırabilir. Masaüstünde bu çok az sonuç doğurabilirken, 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ınlanmış nesnelere yol açacak yöntemleri kullanmaktan kaçınmak ve bunun yerine tahsis/init modelini kullanmaya teşvik edilmeniz en iyi yöntem olarak kabul edilir.

Böylece, yerine:

aVariable = [AClass convenienceMethod];

mümkün olduğunda, yerine 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, yöntem adını "new" ile hazırlayarak serbest bırakılması gerektiğini alıcıya işaretlemek için Cocoa'nın adlandırma kuralı 'dan yararlanabilirsiniz. .

Böylece, yerine:

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

yazabilirsin:

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

Yöntem adı "yeni" ile başladığından, API'nizin tüketicileri alınan nesnenin serbest bırakılmasından sorumlu olduklarını bilir (bkz. Örneğin, NSObjectController's newObject method ).

(1) Kendi yerel otomatik yayın havuzlarınızı kullanarak kontrolü ele alabilirsiniz. Bununla ilgili daha fazla bilgi için bakınız Autorelease Pools .

75
mmalc

Bunlardan bazıları çoktan bahsedildi, fakat işte kafamın üstünden düşünebildiğim şey:

  • KVO adlandırma kurallarına uyun. Şimdi KVO'yu kullanmasanız bile, benim deneyimimde çoğu zaman gelecekte yararı olur. KVO veya cilt kullanıyorsanız, işlerin olması gerektiği gibi çalıştığını bilmeniz gerekir. Bu, yalnızca erişimci yöntemlerini ve örnek değişkenlerini değil, aynı zamanda çok sayıda ilişki, doğrulama, otomatik olarak bildirme bağımlı anahtarları vb.
  • Bir kategoriye özel yöntemler koyun. Yalnızca arayüz değil, uygulama da. Kavramsal olarak özel ve özel olmayan yöntemler arasında biraz mesafe olması iyidir. Her şeyi .m dosyama ekliyorum.
  • Arka plan iş parçacığı yöntemlerini bir kategoriye yerleştirin. Yukarıdakiyle aynı. Ana başlıkta ne olup bittiğini düşünürken açık bir kavramsal engel oluşturmanın iyi olduğunu buldum.
  • se #pragma mark [section]. Genellikle, kendi yöntemlerime, her bir alt sınıfın geçersiz kılmaları ve herhangi bir bilgi veya resmi protokollere göre gruplarım. Bu, tam olarak aradığım şeye atlamayı çok daha kolaylaştırıyor. Aynı konuda, benzer yöntemleri (tablo görünümünün temsilci yöntemleri gibi) birlikte gruplayın, yalnızca bunları bir yere yapıştırmayın.
  • Özel yöntemleri & ivars ile ön eki _. Görünüşünü seviyorum ve kazara bir mülk demek istediğimde bir ivar kullanmam daha az olası.
  • init & dealloc'ta mutator yöntemlerini/özelliklerini kullanmayın. Bu nedenle hiçbir şey olmadı, ama yöntemi değiştiren bir şeyi yapmak için yöntemi değiştirirseniz mantığı görebiliyorum. nesnenin durumu.
  • IBOutlet'leri özelliklere yerleştirin. Aslında bunu sadece burada okudum, ancak yapmaya başlayacağım. Herhangi bir hafıza avantajından bağımsız olarak, stilistik olarak daha iyi görünüyor (en azından benim için).
  • Kesinlikle ihtiyacınız olmayan bir kod yazmaktan kaçının. Bu, bir #define'in yapacağı zaman ivars yapmak veya her veriyi sıralamak yerine bir diziyi önbelleğe almak gibi birçok şeyi kapsar. gereklidir. Bununla ilgili söyleyebileceğim çok şey var, ancak sonuçta, ihtiyacınız olana kadar kod yazmıyorsunuz veya profilci size söylesin. Uzun vadede işlerin korunmasını kolaylaştırır.
  • Başladığın işi bitir. Çok fazla yarı bitmiş olan buggy kodu, bir projeyi öldürmenin en hızlı yoludur. İyi bir saplama yöntemine ihtiyacınız varsa, bunu sadece içine NSLog( @"stub" ) ekleyerek belirtin ya da bir şeyleri takip etmek istediğinizde belirtin.
70
Marc Charbonneau

Birim testleri yaz. Kakao'da diğer çerçevelerde daha zor olabilecek şeyleri lot test edebilirsiniz. Örneğin, UI kodu ile genellikle işlerin olması gerektiği gibi bağlı olduğunu doğrulayabilir ve kullanıldıklarında çalışacaklarına güvenebilirsiniz. Ayrıca, durumlarını belirleyebilir ve bunları sınamak için delege yöntemlerini kolayca çalıştırabilirsiniz.

Ayrıca, dahili sistemleriniz için testler yazma yolunda kamuya karşı korumalı ve özel yöntem görünürlüğüne sahip değilsiniz.

56
Chris Hanson

Altın Kural: Eğer alloc - o zaman release!

GÜNCELLEME: ARC kullanmıyorsanız

55
JamesSugrue

Objective-C yazıyormuş gibi Java/C #/C++/etc.

Bir keresinde Java EE web uygulamalarını yazmaya çalışan bir takım gördüm, bir Cocoa masaüstü uygulaması yazmaya çalıştım. Sanki bir Java EE web uygulamasıydı. Gerçekten çok ihtiyaç duydukları bir Foo sınıfı ve muhtemelen bir Fooable protokolü olduğunda, etrafında birçok AbstractFooFactory ve FooFactory ile IFoo ve Foo vardı.

Bunu yapmamanızı sağlamanın bir kısmı, dildeki farklılıkları gerçekten anlamaktır. Örneğin, yukarıdaki soyut fabrika ve fabrika sınıflarına ihtiyacınız yoktur, çünkü Objective-C sınıfı yöntemleri, örnek yöntemler gibi dinamik olarak gönderilir ve alt sınıflarda geçersiz kılınabilir.

55
Chris Hanson

Debugging Magic sayfasını işaretlediğinizden emin olun. Bir Kakao böceğinin kaynağını bulmaya çalışırken, başınızı duvara çarparken ilk durağınız bu olmalı.

Örneğin, daha sonra çökmelere neden olacak ilk bellek ayırdığınız yöntemi nasıl bulacağınızı size söyleyecektir (uygulama sonlandırması sırasında olduğu gibi).

50
mj1531

Dizeleri kullanıcının istediği gibi sırala

Kullanıcıya sunmak için dizeleri sıraladığınızda, basit compare: yöntemini kullanmamalısınız. Bunun yerine, her zaman localizedCompare: veya localizedCaseInsensitiveCompare: gibi yerel karşılaştırma yöntemlerini kullanmalısınız.

Daha fazla ayrıntı için, bkz. Dizeleri Arama, Karşılaştırma ve Sıralama .

38
mmalc

Şimdi Newbiecategoryaholism'u aramaya karar verdiklerimden kaçınmaya çalışın. Objective-C'ye yeni başlayanlar kategorileri keşfettiklerinde, genellikle çılgına dönerler ve var olan her sınıfa yararlı küçük kategoriler eklerler ("Ne? Bir sayıyı Romen rakamlarına NSNumber rock'ına dönüştürmek için bir yöntem ekleyebilirim!").

Bunu yapma.

İki düzine hazırlık sınıfı üzerine serpilmiş onlarca küçük kategori yöntemiyle kodunuz daha taşınabilir ve anlaşılması kolay olacaktır.

Bazı kodları düzenlemeye yardımcı olmak için bir kategori yöntemine gerçekten ihtiyacınız olduğunu düşündüğünüz çoğu zaman, yöntemi yeniden kullanmayacağınızı göreceksiniz.

Kategori yöntemlerinizi belirtmediğiniz sürece (ve tamamen delice ddribin'in kim?) Başka tehlikeler de var, Apple, bir eklenti veya adres alanınızda çalışan başka bir şeyin de aynı kategoriyi tanımlaması ihtimali biraz farklı yan etkisi ile aynı adı taşıyan yöntem ....

TAMAM. Artık uyarıldığına göre, "bu kısmı yapma" deyin. Ancak aşırı kısıtlama egzersiz yapın.

38
schwa

Dünyayı alt sınıflamaya diren. Cocoa'da, delegasyon ve diğer çalışma çerçevelerinde alt sınıflandırma ile yapılan çalışma zamanının kullanımı ile çok şey yapılır.

Örneğin, Java uygulamasında anonim *Listener alt sınıfının örneklerini kullanıyorsunuz ve .NET'te EventArgs alt sınıflarınızı çok kullanıyorsunuz. Kakao'da ikisini de yapmazsınız - hedef eylem yerine kullanılır.

37
Chris Hanson

Beyan Edilen Özellikler

Tüm özellikleriniz için genellikle Objective-C 2.0 Belared Properties özelliğini kullanmalısınız. Herkese açık değilse, bunları bir sınıf uzantısına ekleyin. Beyan edilen özelliklerin kullanılması, hafıza yönetimi anlamını derhal netleştirir ve dealloc yönteminizi kontrol etmenizi kolaylaştırır - mal beyanlarınızı birlikte gruplandırırsanız, bunları hızlıca tarayabilir ve dealloc yönteminizin uygulanmasıyla karşılaştırabilirsiniz.

Özellikleri 'nonatomik' olarak işaretlemeden önce çok düşünmelisiniz. Gibi Amaç C Programlama Dili Kılavuz belirtildiği gibi, özellikler varsayılan olarak atomiktir ve ek yüke neden olur. Dahası, sadece tüm özelliklerinizi atomik yapmak, uygulamanızı iş parçacığı için güvenli yapmaz. Ayrıca, elbette, eğer 'isimsiz' belirtmezseniz ve kendi erişim metotlarınızı (bunları sentezlemekten ziyade) uygularsanız, bunları atomik bir şekilde uygulamanız gerektiğini unutmayın.

31
mmalc

Nil değerlerini düşün

bu sor belirtildiği gibi, nil için olan mesajlar Objective-C'de geçerlidir. Bu sık sık bir avantaj olsa da - daha temiz ve daha doğal bir kodun ortaya çıkmasına neden oluyor - özellik beklemiyorsanız nil değeri alırsanız, zaman zaman tuhaf ve izlemesi zor hatalara yol açabilir .

26
mmalc

NSAssert ve arkadaşlarını kullan. Nil'i her zaman geçerli nesne olarak kullanıyorum ... özellikle nil'e mesaj göndermek Obj-C'de mükemmel şekilde geçerli. Bununla birlikte, bir değişkenin durumundan gerçekten emin olmak istersem, problemleri kolayca izlememize yardımcı olan NSAssert ve NSParameterAssert'i kullanırım.

26
NikWest

Basit ama unutulmuş biri. Özelliğe göre:

Genel olarak, aynı seçiciye sahip (aynı adı taşıyan) farklı sınıflardaki yöntemler aynı dönüş ve argüman türlerini de paylaşmalıdır. Bu kısıtlama, derleyici tarafından dinamik bağlanmaya izin vermek için uygulanır.

bu durumda, aynı adlandırılmış seçicilerin tümü farklı sınıflarda olsa bile, aynı dönüş/argüman türlerine sahip sayılır. İş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;
}   
23
Özgür

Leopard (Mac OS X 10.5) veya üstünü 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ıyla Başlat> Kaçaklar'ı seçin.

Uygulamanız herhangi bir sızıntı göstermese bile, nesneleri çok uzun süre çevresinde tutuyor olabilirsiniz. Aletler'de bunun için ObjectAlloc aletini kullanabilirsiniz. Enstrümanlar belgenizden ObjectAlloc enstrümanını seçin ve enstrüman ayrıntılarını (zaten görünmüyorsa) Görünüm> Ayrıntı'yı seçerek (yanında onay işareti olması gerekir) seçin. ObjectAlloc detayındaki "Tahsis Ömrü" altında, "Created & Still Living" seçeneğinin yanındaki radyo düğmesini seçtiğinizden emin olun.

Şimdi ne zaman uygulamanızı kaydetmeyi bıraktıysanız, ObjectAlloc aracını seçmek, uygulamanızdaki "# Net" sütununda her bir canlı nesneye kaç referans bulunduğunu gösterecektir. Yalnızca kendi sınıflarınıza değil, NIB dosyalarınızın en üst düzey nesnelerinin sınıflarına da baktığınızdan emin olun. Örneğin, ekranda hiç pencere yoksa ve hala yaşayan bir NSWindow'a referanslar görüyorsanız, kodunuzda serbest bırakmamış olabilirsiniz.

22
mj1531

Dealloc'da temizleyin.

Bu unutulması en kolay şeylerden biri. 150mph de kodlama yaparken. Her zaman, her zaman, her zaman niteliklerinizi/üye değişkenlerinizi dealloc'ta temizleyin.

Objc 2 özniteliklerini kullanmayı seviyorum - with yeni nokta gösterimi - böylece temizleme ağrısız olur. Genellikle şu kadar basit:

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

Bu sürüm sizin için serbest bırakacak ve özniteliği NULL olarak ayarlayacaktır (savunmalı programlamayı düşünürüm - dealloc'ta başka bir yöntem daha üye değişkene tekrar erişirse - nadir ama olabilir olur).

GC 10.5'te açıkken, buna artık çok ihtiyaç duyulmuyor - ama yine de yarattığınız kaynakları temizlemeniz gerekebilir, bunun yerine finalize etme yönteminde bunu yapabilirsiniz.

21
schwa

Tüm bu yorumlar harika, ama kimseden bahsetmediğine gerçekten şaşırdım Google'ın Amaç-C Stil Rehberi bir süre önce yayınlandı. Bence çok kapsamlı bir iş yaptılar.

17
slf

Ayrıca, yarı ilgili konu (daha fazla cevap için yer ile!):

2 yıl önce bilmesini istediğiniz küçük Xcode ipuçları ve püf noktaları nelerdir? .

15
schwa

NSWindowController ve NSViewController'in yönetdikleri NIB dosyalarının en üst düzey nesnelerini serbest bırakacaklarını unutmayın.

Bir NIB dosyasını manuel olarak yüklerseniz, bu NIB'nin üst düzey nesnelerini onlarla işiniz bittiğinde serbest bırakmak sizin sorumluluğunuzdadır.

13
mj1531

Yeni başlayanların kullanması için oldukça belirgin olanı: Xcode'un kodunuzu otomatik girme özelliğinden yararlanın. Başka bir kaynaktan kopyalayıp yapıştırıyor olsanız bile, kodu bir kez yapıştırdığınızda, kod bloğunun tamamını seçebilir, üzerine sağ tıklayabilir ve ardından o blok içindeki her şeyi yeniden girintiye alma seçeneğini seçebilirsiniz.

Xcode aslında bu bölümden ayrışacak ve onu parantez, halka vb. Temeline göre girintileyecektir. Her satır için boşluk çubuğuna veya sekme tuşuna basmaktan çok daha etkilidir.

12
iwasrobbed

Değişkenler ve özellikler

1/Başlıklarınızı temiz tutmak, uygulamayı gizlemek
Başlığınıza örnek değişkenler eklemeyin. Özel değişkenler sınıf devamlılığına özellik olarak konur. Genel değişkenler, başlığınızda genel özellikler olarak bildirir. Sadece okunması gerekiyorsa, onu salt okunur olarak beyan edin ve derse devamında okuma yazma olarak yazın. Temelde değişkenleri hiç kullanmıyorum, sadece özellikleri kullanıyorum.

2/Özelliklerinize varsayılan olmayan bir değişken adı verin, örneğin:


@synthesize property = property_;

Sebep 1: "Kendini" unutmaktan kaynaklanan hataları yakalayacaksınız. özelliği atarken Sebep 2: Denemelerime göre, Cihazlardaki Sızıntı Analizörü, varsayılan adla sızıntı yapma özelliğini saptamada sorun yaşıyor.

3/Asla doğrudan mülklerde tutma veya bırakma özelliğini kullanmayın (veya yalnızca çok istisnai durumlarda). Sizin dealloc'unuzda sadece bir sıfır atayın. Tutma özellikleri, tutma/bırakma işlemlerini kendi başlarına yapmak içindir. Bir pasifin örneğin gözlemci ekleme veya silmediğini asla bilemezsiniz. Değişkeni doğrudan yalnızca ayarlayıcı ve alıcı içinde kullanmalısınız.

Görünümler

1/Yapabiliyorsanız her görünüm tanımını bir 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ünüm sayısını azaltarak görünümleri optimize etmeye çalışmayın. Sadece içine alt görünüm eklemek istediğinizden, xib yerine kodunuzda UIImageView oluşturmayın. Bunun yerine UIImageView'ı arka plan olarak kullanın. Görüş çerçevesi, yüzlerce görüşü sorunsuzca ele alabilir.

3/IBOutlet'lerin her zaman muhafaza edilmeleri gerekmez (veya güçlüdür). IBOutlet'larınızın çoğunun görünüm hiyerarşinizin bir parçası olduğunu ve dolaylı olarak muhafaza edildiğini unutmayın.

4/viewDidUnload'daki tüm IBOutlet'leri yayınla

5/Call viewDidUllload metodunu kullanarak yükle. Örtük olarak adlandırılmaz.

Bellek

1/Oluşturduğunuzda Autorelease nesneleri. Birçok hata, serbest bırakma çağrınızı bir if-else dalına veya bir return ifadesinden sonra taşımanıza neden olur. Otomatik yayın yerine bırakma yalnızca istisnai durumlarda kullanılmalıdır - örn. bir runloop beklerken ve nesnenin çok erken saatlerde serbest bırakılmasını istemiyorsanız.

2/Otomatik Referans Sayımı kullanıyor olsanız bile, alıkonma-bırakma yöntemlerinin nasıl çalıştığını mükemmel bir şekilde anlamanız gerekir. Tutma serbest bırakmayı manuel olarak kullanmak ARC'den daha karmaşık değildir, her iki durumda da kaçaklar ve tutma döngüleri hakkında bir şeyler yapmanız gerekir. Büyük projelerde veya karmaşık nesne hiyerarşilerinde el ile serbest bırakmayı kullanmayı düşünün.

Yorumlar

1/Kodunuzu otomatik olarak belgelendirin. Her değişken ismi ve metod ismi ne yaptığını söylemelidir. Kod doğru yazılırsa (bu konuda çok fazla pratik yapmanız gerekir), herhangi bir kod yorumuna ihtiyacınız olmaz (dokümantasyon yorumlarıyla aynı değildir). Algoritmalar karmaşık olabilir ancak kod her zaman basit olmalıdır.

2/Bazen bir yoruma ihtiyacınız olacak. Genellikle görünmeyen bir kod davranışını veya kesmeyi tanımlamak için. Bir yorum yazmanız gerektiğine inanıyorsanız, önce kodu daha basit ve yorum yapmaya gerek kalmadan yeniden yazmaya çalışın.

Girinti

1/Girintiyi çok fazla arttırmayın. Yöntem kodunuzun çoğu, yöntem düzeyinde girintili olmalıdır. İç içe bloklar (eğer varsa, vb.) 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'in içindeyse, if koşulunu reddedin, örneğin:


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

return self;


if (!self) {
   return nil;
}

//... long initialization code ...

return self;

C kodunu anlayın, esas olarak C yapılarını

Obj-C'nin, C dili üzerinde yalnızca hafif bir OOP katmanı olduğunu unutmayın. C'deki temel kod yapılarının nasıl çalıştığını anlamalısınız (sayılar, yapılar, diziler, işaretçiler vb.). Örnek:


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 birçok

Kendi kodlama standartları belgenizi yönetin ve sık sık güncelleyin. Hatalarından ders almayı dene. Bir hatanın neden yaratıldığını anlayın ve kodlama standartlarını kullanmaktan kaçının.

Kodlama standartlarımız şu anda yaklaşık 20 sayfa, Java Kodlama Standartları, Google Obj-C/C++ Standartları ve kendi eklerimizin bir karışımını içeriyor. Kodunuzu belgeleyin, standart standart girintiyi, beyaz boşlukları ve doğru yerlerde boş satırları vb. Kullanın.

10
Sulthan

Tüm GCC uyarılarını açın, ardından gürültüyü azaltmak için Apple'ın üstbilgilerinin neden olduğu düzenli olarak kapatın.

Ayrıca sık sık Clang statik analizi çalıştırın; "Statik Analizörü Çalıştır" derleme ayarı ile tüm yapılarda bunu etkinleştirebilirsiniz.

Birim testleri yaz ve bunları her derlemede çalıştır.

10
oefe

Kakao programcılığına ilk girerken bunu göz ardı ettiğimi biliyorum.

NIB dosyalarıyla ilgili bellek yönetimi sorumluluklarını anladığınızdan emin olun. Yüklemiş olduğunuz NIB dosyalarındaki en üst düzey nesneleri serbest bırakmak sizin sorumluluğunuzdadır. Konuyla ilgili Apple'ın Belgeleri okuyun.

10
mj1531

Daha fazla ol işlevsel.

Objective-C nesne yönelimli bir dildir, ancak Cocoa çerçevesi fonksiyonel tarzı tanımaktadır ve birçok durumda işlevsel stilde tasarlanmıştır.

  1. Değişebilirlik ayrımı var. Birincil olarak değişmez sınıfları ve ikincil olarak değişken nesneler kullanın. Örneğin, öncelikle NSArray kullanın ve yalnızca ihtiyacınız olduğunda NSMutableArray kullanın.

  2. Saf fonksiyonlar var. Çok fazla değil, pek çok çerçeve API satın almak saf fonksiyon gibi tasarlanmıştır. CGRectMake() veya CGAffineTransformMake() gibi fonksiyonlara bakın. Açıkçası işaretçi formu daha verimli görünüyor. Ancak, işaretçilerle dolaylı tartışma yan etki gerektirmez. Yapıları tamamen mümkün olduğunca tasarlayın. Durum nesnelerini bile ayırın. Bir değeri başka bir nesneye geçirirken -copy yerine -retain kullanın. Çünkü ortak durum sessizce diğer nesnede değere mutasyon etkileyebilir. Öyleyse yan etkisi olmadan olamaz. Dış nesneden bir değeriniz varsa, kopyalayın. Bu nedenle, paylaşılan durumu mümkün olduğu kadar minimal bir şekilde tasarlamak da önemlidir.

Ancak saf olmayan işlevler kullanmaktan da korkmayın.

  1. Tembel bir değerlendirme var. -[UIViewController view] property gibi bir şey görün. Nesne oluşturulduğunda görünüm oluşturulmaz. Arayan ilk kez view özelliğini okuduğunda oluşturulur. UIImage gerçekten çizilene kadar yüklenmeyecek. Bu tasarım gibi birçok uygulama var. Bu tür tasarımlar kaynak yönetimi için çok faydalıdır, ancak tembel değerlendirme kavramını bilmiyorsanız, davranışlarını anlamak kolay değildir.

  2. Kapatma var. C bloklarını mümkün olduğunca kullanın. Bu, hayatınızı büyük ölçüde kolaylaştıracak. Ancak kullanmadan önce blok bellek yönetimi hakkında bir kez daha okuyun.

  3. Yarı otomatik GC var. NSAutoreleasePool. Birincil -autorelease kullanın. Gerçekten ihtiyacınız olduğunda ikincil _ -retain/-release ikincil kullanın. (örn: bellek optimizasyonu, açık kaynak silme)

9
Eonil

Gördüğüm Apple tarafından sağlanan örnekler, Uygulama temsilcisine bir veri yöneticisi, bir veri yöneticisi olarak davrandı. Bu yanlış. Bir singleton oluşturun ve bunu Uygulama temsilcisinde başlatabilirsiniz, ancak Uygulama temsilcisini uygulama düzeyinde etkinlik işleme dışında bir şey olarak kullanmaktan uzak durun. Ben yürekten tavsiyeleri ikinci bu blog girişi . Bu kon beni uyardı.

8
bbrown

Yalnızca bir özellik in dealloc yöntemini bırakın. property 'nin tuttuğu hafızayı serbest bırakmak istiyorsanız, nil olarak ayarlayın:

self.<property> = nil;
4
Tuan Nguyen
#import "MyClass.h"

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

@implementation MyClass
0
Nirmit Pathak