Objective-C ve Cocoa yazarken kullandığınız en iyi uygulamalar nelerdir? [kapalı]


346

HIG hakkında biliyorum (ki bu oldukça kullanışlı!), Ancak Objective-C yazarken ve daha özel olarak Cocoa (veya CocoaTouch) kullanırken hangi programlama uygulamalarını kullanıyorsunuz.


bu blog gönderisine bakın, çok güzel. ironwolf.dangerousgames.com/blog/archives/913
user392412

Yanıtlar:


398

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, someFloataslı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 atomicvarsayı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


3
Çift aritmetik hakkında güzel uç.
Adam Ernst

8
Sınıf uzantıları artık özel yöntemler için tercih edilen yöntemdir: developer.apple.com/Mac/library/documentation/Cocoa/Conceptual/…
Casebash

9
İPhone'daki çiftler hakkındaki tavsiyeleriniz güncel değil stackoverflow.com/questions/1622729/…
Casebash

3
Güncel değil; tamamen yanlış: Orijinal iPhone desteklenen donanımda yaklaşık aynı hızda yüzer ve iki katına çıkar. SQLite ayrıca işlemleri bellekte tutmaz; diskte günlüğe kaydedilirler. Kullanıcı arayüzünüzü yalnızca uzun sorgular engeller; her şeyi ana iş parçacığında çalıştırmak ve daha hızlı sorgular kullanmak daha az dağınıktır.
tc.

1
@tc: İşlemlerle ilgili SQL öğesini düzelttim, bu son dört öğeyi kendim yazmadığımı unutmayın. Ayrıca sorguların arka plana taşınmasıyla ilgili kısmın sadece çok uzun sorgular için olduğunu açıklığa kavuşturdum (bazen onları daha kısa tutamazsınız). Ama her şeyi bir kaç nokta yüzünden "yanlış" olarak adlandırmak oldukça aşırı hissediyorum. Ayrıca, yukarıdaki cevap zaten şunları söyledi: "Eski telefonlarda hesaplamalar aynı hızda çalışıyor", ancak daha fazla sayıda tek hassasiyetli kayıt hakkındaki kısmı hala tercih edilebilir kılıyor.
Kendall Helmstetter Gelner

109

Bilinmeyen dizeleri biçim dizeleri olarak kullanma

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);

4
Bunu daha önce ısırmıştım.
Adam Ernst

Bu herhangi bir programlama dili için iyi bir tavsiye
Tom Fobear

107

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 ; somethingveya _somethingadını kullanın ve buna bir örnek değişkeni deyin .
  • Alıcıya isim verme -getSomething; doğru Kakao adı sadece -something.
  • Bir ayarlayıcıya isim verme -something:; olmalı-setSomething:
  • Yöntem adı bağımsız değişkenlerle serpiştirilir ve iki nokta üst üste içerir; öyle -[NSObject performSelector:withObject:]değil NSObject::performSelector.
  • Alt çubuklar (alt çizgiler) yerine yöntem adlarında, parametrelerde, değişkenlerde, sınıf adlarında vb. Ara başlıklar (CamelCase) kullanın.
  • Sınıf isimleri büyük harf, değişken ve yöntem isimleri küçük harf ile başlar.

Bunu bir kenara bırakacak olursak, yok Win16 / Win32 tarzı Macar notasyonu kullanın. Microsoft bile .NET platformuna geçişten vazgeçti.


5
Ben iddia ediyorum, setSomething kullanmayın: / bir şey hiç - yerine özellikleri kullanın. Bu noktada gerçekten Tiger'ı hedeflemesi gereken az sayıda insan var (mülkleri kullanmamak için tek sebep)
Kendall Helmstetter Gelner

18
Özellikler sizin için yine de erişimci yöntemleri oluşturur ve mülk üzerindeki getter = / setter = öznitelikleri, yöntemlerin adlarını belirtmenize olanak tanır. Ayrıca, özellikleri olan foo.something sözdizimi yerine [foo bir şey] sözdizimini kullanabilirsiniz. Dolayısıyla, erişimci adlandırma hala geçerlidir.
Chris Hanson

3
Bu, önerdiğiniz şeylerin çoğunu yaptığım C ++ 'dan gelen biri için harika bir referans.
Clinton Blackmore

4
Bir ayarlayıcı, bir şeyin veritabanına kaydedilmesine neden olmamalıdır. Temel Verilerin NSManagedObjectContext üzerinde ayarlayıcıların anında güncellemeler üretmesi yerine bir -save: yöntemi içermesinin bir nedeni vardır.
Chris Hanson

2
Bunun bir seçenek olmadığından şüpheliyim, ancak uygulama mimarinizi tekrar gözden geçirmeniz gerekebilir. (Açık olmak gerekirse: "Temel Verileri kullanmış olmalısınız" demiyorum. "Kümeler veritabanına kaydetmemeliyim" diyorum.) Nesnelerin grafiğini yönetmek için tek tek nesneleri kaydetmek yerine bir bağlama sahip olmak , neredeyse her zaman mümkün ve daha iyi bir çözümdür.
Chris Hanson

106

IBOutlets

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.


1
uç yükleme o zaman iki kez tutmak olmaz? (uçta bir kez, mülke atanarak ikinci olarak). Bunları dealloc'da serbest bırakmam gerekiyor mu?
Kornel

6
Sızıntıları önlemek için viewDidUnload'da (iPhone OS 3.0+) veya özel bir setView: yönteminde çıkışları sıfırlamanız gerekir. Açıkçası dealloc da serbest bırakmalısınız.
Frank Szczerba


Apple da işleri böyle yapıyor. "İPhone 3 geliştirmenin başlangıcı" bu değişiklikten önceki sürümlerde de bahsedildi.
ustun

Bunu başka bir yorumda belirtmiştim, ancak buraya yerleştirmeliydim: iOS uygulamaları için dinamik ivar sentezi gerçekleşmeye başladığında (eğer / ne zaman?), IBOutlet'i ivar'a karşı mülke koyduğunuza sevineceksiniz!
Joe D'Andrea

97

LLVM / Clang Statik Analizörünü Kullanma

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:

  1. En son sürümü bu sayfadan indirin .
  2. Komut satırından cdproje dizininize.
  3. Yürüt 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.


1
Ben bu talimatları takip edene kadar bu işe almakta bazı sorunlar vardı: oiledmachine.com/posts/2009/01/06/…
bbrown

15
Snow Leopard'daki XCode 3.2.1'de zaten yerleşiktir. Çalıştır -> Oluştur ve Analiz Et'i kullanarak manuel olarak çalıştırabilir veya "Statik Analizörü Çalıştır" oluşturma ayarını kullanarak tüm derlemeler için etkinleştirebilirsiniz. Bu aracın şu anda yalnızca C ve Objective-C'yi desteklediğini, ancak C ++ / Objective-C ++ desteklemediğini unutmayın.
oefe

94

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 deallocyaklaşı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;

8
Bu konuda ince bir şey yok, belgeler açıkça bunu yapmanız gerektiğini söylüyor. İtibaren 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.
johne

NULL yerine nil kullanmak daha iyidir, çünkü NULL belleği boşaltmayacaktır.
Naveen Shan

@NaveenShan nil == NULL. Bunun nilbir idve NULLbir a olması dışında tamamen aynıdır void *. İfadeniz doğru değil.

@WTP yep, nil == NULL, ancak nil kullanmak açıkça tercih edilen yoldur, eğer elma örnek kod parçalarına bakarsanız, her yerde nil kullanırlar ve dediğin gibi nil bir boşluktur, bu da boşluğa tercih edilebilir kılar * , kimlik gönderdiğiniz durumlarda.
Ahti

1
@Ati tam olarak ve Nil(büyük harf) türündedir Class*. Hepsi eşit olsa da, yanlış olanı kullanmak, özellikle Objective-C ++ 'da kötü küçük hatalar getirebilir.

86

@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.


Bunu yapabilirsin ama açıkça "özel" bir bölüm olarak etiketlemek istiyorum (fonksiyonelden daha fazla dokümantasyon) tabii ki .m dosyasında yer aldığı zaten çok açık ...
Kendall Helmstetter Gelner

2
Özel kategoriler ve sınıf uzantıları arasında bir fark olması dışında : "Sınıf uzantıları, aşağıdaki örnekte gösterildiği gibi, birincil sınıf @interface bloğu dışındaki konumlarda bir sınıf için gerekli ek API bildirmenize olanak tanır:" Düzenlemedeki bağlantıya bakın.
schwa

CE yöntemlerini uygulamadığınızda derleyicinin sizi uyaracağı konusunda bir fark olduğunu kabul ediyorum - ancak tüm yöntemler aynı dosyada ve tüm özel olduğunda bu yönü çok önemli bulmuyorum. Hala ileri referans bloğunu özel olarak işaretlemenin sürdürülebilirlik yönünü tercih ediyorum
Kendall Helmstetter Gelner

3
(Özel) 'i ()' den daha fazla bakım yapılabilir olarak görmüyorum. Eğer endişeleniyorsanız, iyi bir yorum dozu yardımcı olabilir. Ama belli ki yaşa ve bırak. YMMV vb.
Schwa

17
(Veya başka bir kategori adı) ()yerine kullanmanın oldukça önemli bir avantajı vardır (Private): Özellikleri yalnızca salt okunur durumdayken halka açıkken readwrite olarak yeniden bildirebilirsiniz. :)
Pascal

75

Otomatik serbest bırakmadan kaçının

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 newObjectyö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ı .


6
Ben faydaları bulmak değil sallanmasını kullanarak maliyetlerini (yani daha bellek sızıntısı hatalar) ağır basar. Ana iş parçacığı üzerindeki kod yine de oldukça kısa olmalıdır (veya aksi takdirde kullanıcı arayüzünü dondurursunuz) ve daha uzun süreli, bellek yoğun arka plan kodu için, bellek yoğun bölümlerini her zaman yerel otomatik kiralama havuzlarına sarabilirsiniz.
adib

56
Katılmıyorum. Mümkün olduğunca otomatik olarak yayınlanmış nesneler kullanmalısınız. Eğer bellek ayak izini çok arttırırlarsa, başka bir bellek kullanmalısınız NSAutoreleasePool. Ama sadece bunun gerçekten bir sorun olduğunu onayladıktan sonra. Erken optimizasyon ve tüm bunlar ...
Sven

3
40 saniyeden az harcıyorum. yeni bir nesneyi başlatırken [someObject release] yazıp "ekstra satırı" okuyarak bir gün, ancak bir keresinde yalnızca özel durumlarda görünecek ve konsolda tutarlı bir hata vermeyen bir otomatik yayın hatası bulmak için 17 saat boyunca yandım. Bu yüzden adib ile "Otomatik yayın kullanmamanın maliyetlerinden ağır basmanın faydalarını buluyorum" gibi bir anlaşmaya katılıyorum.
RickiG

7
Sven ile aynı fikirdeyim. Birincil hedef, sadece gerektiğinde bellek optimizasyonu ile kod netliği ve kodlama hatalarını azaltmak olmalıdır. [[[Foo separa] init] otomatik yayın] yazmak hızlıdır ve bu yeni nesneyi serbest bırakma sorunuyla hemen ilgilenirsiniz. Kodu okurken sızıntı olmadığından emin olmak için ilgili sürüm için avlanmak zorunda değilsiniz.
Mike Weller

3
Otomatik olarak yayımlanan nesnelerin yaşam döngüsü iyi tanımlanmıştır ve yeterli düzeyde belirlenebilir.
Eonil

69

Bunlardan bazılarından daha önce bahsedilmişti, ancak başımın üstünden düşünebileceğim şey:

  • KVO adlandırma kurallarına uyun. Şimdi KVO kullanmasanız bile, tecrübelerime göre, gelecekte hala faydalıdır. Ve KVO veya ciltleri kullanıyorsanız, şeylerin olması gerektiği gibi çalışacağını bilmeniz gerekir. Bu, yalnızca erişimci yöntemlerini ve örnek değişkenleri değil, birçok ilişki, doğrulama, otomatik bildirim bağımlı anahtarları vb. Kapsar.
  • Özel yöntemleri bir kategoriye yerleştirin. Sadece arayüz değil, aynı zamanda uygulama. Özel ve özel olmayan yöntemler arasında kavramsal olarak biraz mesafe olması iyidir. Her şeyi .m dosyama ekliyorum.
  • Arka plan iş parçacığı yöntemlerini bir kategoriye yerleştirin. Yukarıdaki ile aynı. Ana iş parçacığında neyin olup olmadığını düşündüğünüzde açık bir kavramsal engel tutmanın iyi olduğunu gördüm.
  • Kullanın #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.
  • Özel yöntemlerin ve ivarların önüne _ ekleyin. Görünüşünü seviyorum ve kazara bir mülk demek istediğimde bir ivar kullanma olasılığı daha az.
  • İnit & dealloc'da mutator yöntemlerini / özelliklerini kullanmayın. Bu yüzden hiç kötü bir şey olmadı, ama nesnesinin durumuna bağlı bir şey yapmak için yöntemi değiştirirseniz mantığı görebiliyorum.
  • IBOutlet'leri özelliklere koyun. Aslında bunu burada okudum, ama yapmaya başlayacağım. Herhangi bir bellek 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 kod yazmaktan kaçının. Bu, ivar'ları bir #defineirade 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.
  • Başladığınız işi bitirin. Çok sayıda yarı bitmiş, buggy koduna sahip olmak, bir projeyi öldürmenin en hızlı yoludur. İyi bir saplama yöntemine ihtiyacınız varsa, sadece NSLog( @"stub" )içine koyarak belirtin veya şeyleri takip etmek istersiniz.

3
Bir dersin devamında özel yöntemler koymanızı öneririm. (yani @interface Sınıfım () ... @end içinde .m)
Jason Medeiros

3
#PRAGMA yerine, daha taşınabilir ve aynı şekilde çalışan bir yorum // İşaretle: [Bölüm] kullanabilirsiniz.
aleemb

Özel bir sözdizimi olmadığı sürece, // Mark: Xcode'un işlevler açılır menüsüne etiket eklemez, bu da onu kullanmanın nedeninin yarısıdır.
Marc Charbonneau

6
Açılır pencerede görünmesi için "// MARK: ..." büyük harfini kullanmanız gerekir.
Rhult

3
Bununla ilgili olarak , açılır menüde görünecek olan tamamlama kodunu işaretlemek için Finish what you startde kullanabilirsiniz // TODO:.
iwasrobbed

56

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.


Hangi test çerçevelerini öneriyorsunuz?
melfar

13
Xcode, bir Objective-C birim test çerçevesi olan OCUnit'i ve derleme sürecinizin bir parçası olarak birim test paketlerini çalıştırmak için destek içerir.
Chris Hanson

55

Altın Kural: Eğer sen alloco zaman sen release!

GÜNCELLEME: ARC kullanmadığınız sürece


26
Ayrıca eğer copy, mutableCopy, newveya retain.
Sven

54

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.


10
Objective-C'de soyut bir fabrika yazmış bir Java geliştiricisi olarak bunu ilgi çekici buluyorum. Bunun nasıl çalıştığını biraz daha açıklamak ister misiniz - belki bir örnekle?
teabot

2
Bu yanıtı yayınladığınızdan bu yana geçmiş zamanların hepsinden sonra soyut fabrika sınıflarına ihtiyacımız olmadığını hala düşünüyor musunuz?
kirk.burleson

50

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).


1
Şimdi Debugging Magic sayfasının iOS'a özel bir sürümü var .
Jeethu

38

Ş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.


Cevabınızı beğendim, tavsiyem, bazı kodları birden fazla yerde çoğaltmak üzereyken ve kod açıkça kategorize etmek üzere olduğunuz sınıfa ait değilse, yardımcı kod depolamak için bir kategori kullanmazsınız ...
Kendall Helmstetter Gelner

Sadece isim aralığı kategorisi yöntemleri için desteğimi vermek ve seslendirmek istiyorum. Sadece yapılacak doğru şey gibi görünüyor.
Michael Buckley

+1 yalnızca Romen rakamları içinse. Bunu kesinlikle yapardım!
Brian Postow

14
Kontrpuan: Geçtiğimiz bir buçuk yıldır tam tersi bir politika izledim: "Eğer bir kategoride uygulanabilirse bunu yapın." Sonuç olarak, kodum Apple'ın sağladığı ayrıntılı örnek koddan çok daha özlü, daha etkileyici ve okunması daha kolay. Bir isim alanı çatışması için yaklaşık 10 dakika kaybettim ve muhtemelen kendim için yarattığım verimliliklerden insan ayları kazandım. Her biri için, ama riskleri bilerek bu politikayı benimsedim ve yaptığım için çok mutluyum.
cduhn

7
Kabul etmiyorum. Bir işlev olacak ve bir Vakıf nesnesi için geçerliyse ve iyi bir ad düşünebiliyorsanız, onu bir kategoriye yapıştırın. Kodunuz daha okunabilir olacaktır. Bence buradaki en göze çarpan nokta şudur: her şeyi ölçülü yapın.
mxcl

37

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 *Listeneralt sınıf örneklerini çok kullanırsınız ve .NET'te EventArgsalt sınıflarınızı çok kullanırsınız. Kakao'da ikisini de yapmazsınız - bunun yerine hedef eylem kullanılır.


6
Aksi takdirde "Kalıtım üzerine kompozisyon" olarak bilinir.
Andrew Ebling

37

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

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 .


31

Beyan Edilen Özellikler

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.


26

Sıfır değerleri düşünün

Bu soruda belirtildiği gibi , iletiler nilObjective-C'de geçerlidir. Bu genellikle bir avantaj olsa da - daha temiz ve daha doğal kodlara yol açıyor - özellik, nilbeklemediğiniz bir değer alırsanız bazen tuhaf ve izlenmesi zor hatalara yol açabilir .


Bunu alabilir: #define SXRelease(o); o = nilve aynı CFReleaseve free. Bu her şeyi basitleştirir.

26

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.



23

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;
}   

unutması kolay. Yine de önemli
Brock Woolf

3
Bu yalnızca statik yazımdan kaçınırken bir endişe kaynağıdır. Derleyici türü biliyorsa, bağımsız değişken ve dönüş türleri sorunsuz olarak değişebilir. Şahsen, bunun sık sık bir sorun olmadığını düşünüyorum. Apple'ın aynı ada sahip, ancak dönüş türlerinde farklı olan birçok yöntemi var. Son olarak, belirsiz durumlarda sizi uyaran bir derleyici bayrağı var.
Nikolai Ruhe

Apple'ın adlandırma konvansiyonu
kuralına uyursak

22

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.


21

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.


12
Genel olarak gereken değil bir erişim yöntemine dealloc (veya init) kullanmak.
mmalc

1
Performans nedenlerinin dışında (erişimciler doğrudan erişimden biraz daha yavaştır) neden erişim sağlayıcılarını dealloc veya init içinde kullanmamalıyım?
schwa

1
(a) Performans nedenleri kendi başlarına mükemmel bir nedendir (özellikle erişimcilerin atomikse). (b) Erişimcilerin sahip olabileceği yan etkilerden kaçınmalısınız. İkincisi, sınıfınız alt sınıflara ayrılmışsa özellikle bir sorundur.
mmalc

3
Sentezlenmiş ivarlarla modern çalışma zamanında çalışıyorsanız, dealloc'da erişimcileri kullanmanız gerektiğini unutmayın . Modern çalışma zamanı kodu birçoğu GC'dir, ancak hepsi değildir.
Louis Gerbarg

1
Accessor yöntemlerinin / özelliklerinin -initve -deallocyöntemlerinin kullanılıp kullanılmayacağına ilişkin daha geniş bir görünümü burada bulabilirsiniz: mikeash.com/?page=pyblog/…
Johan Kool

17

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.


7
Hmm, ilk örnek zaten saçmalıklarla dolu. Asla dil deyimlerini belgelemeyin. Bir başlık dosyasında bu tür yorumları bulabilirsem okumaya uğramazdım.
Stephan Eggermont

5
Ah gözlerim !!!!! Ne gördüğüme inanamıyorum.
Eonil


13

NSWindowController ve NSViewController'ın yönettikleri NIB dosyalarının en üst düzey nesnelerini yayınlayacağını unutmayın.

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


12

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.


Hatta Girinti girecek şekilde ayarlayabilirsiniz ve sonra Cmd-A ve Sekme yapabilirsiniz.
Plumenator

10

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 .


6
Bu doğru değil. Üst düzey nesneleri serbest bırakmaktan sorumlu olup olmamanız, hangi sınıftan miras aldığınıza ve hangi platformu kullandığınıza bağlıdır. Diğerlerinin yanı sıra developer.apple.com/documentation/Cocoa/Conceptual/MemoryMgmt/… adresine bakın .
mmalc

10

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.


Ve mümkünse, “Uyarılara Hata Olarak davran” seçeneğini açın. Uyarı yapılmasına izin verme.
Peter Hosey

2
Projenizi önerilen uyarılarla ayarlamak için kullanışlı bir komut dosyası bulabilirsiniz: rentzsch.tumblr.com/post/237349423/hoseyifyxcodewarnings-scpt
Johan Kool

10

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.


9

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.

  1. 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.

  2. 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 -copyyerine 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.

  1. 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 . UIImagegerç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.

  2. 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.

  3. Yarı otomatik GC var. NSAutoreleasePool. -autoreleaseBirincil kullanın . -retain/-releaseGerçekten ihtiyacınız olduğunda manuel ikincil kullanın . (ör: bellek optimizasyonu, açık kaynak silme)


2
3'e gelince, karşıt yaklaşımı önereceğim: Mümkün olan yerlerde manuel tutma / bırakma kullanın! Bu kodun nasıl kullanılacağını kim bilir - ve sıkı bir döngüde kullanılacaksa, bellek kullanımınızı gereksiz yere patlatabilir.
Eiko

@Eiko Bu sadece Erken Bir Optimizasyon , genel rehberlik olamaz.
Eonil

1
Bence bu daha çok bir tasarım işi, özellikle de model sınıfları üzerinde çalışırken. Büyüyen belleği bir yan etki olarak görüyorum ve sık sık görünmesini istediğim şey bu değil. Daha da kötüsü, kodumu kullanan başka bir geliştiricinin pahalı çağrıları otomatik yayın havuzlarına sarmaktan başka şansı yok (mümkünse - nesnelerim başka bir kütüphane koduna gönderilebilir). Ve bu sorunları daha sonra teşhis etmek zordur, ancak en başta kaçınmak ucuzdur. Aktarılan nesneleri kopyalar / otomatik olarak serbest bırakırsanız, beklediğinizden çok daha büyükse kaybolabilirsiniz. Yine de GUI kodu ile daha rahatım.
Eiko

@Eiko autoreleaseGenel 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 :)
Eonil
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.