Jawaban:
Ada beberapa hal yang sudah mulai saya lakukan yang menurut saya tidak standar:
1) Dengan munculnya properti, saya tidak lagi menggunakan "_" untuk awalan variabel kelas "pribadi". Lagi pula, jika variabel dapat diakses oleh kelas lain, tidakkah seharusnya ada properti untuknya? Saya selalu tidak menyukai awalan "_" untuk membuat kode lebih buruk, dan sekarang saya bisa mengabaikannya.
2) Berbicara tentang hal-hal pribadi, saya lebih suka menempatkan definisi metode pribadi dalam file .m dalam ekstensi kelas seperti:
#import "MyClass.h"
@interface MyClass ()
- (void) someMethod;
- (void) someOtherMethod;
@end
@implementation MyClass
Mengapa mengacaukan file .h dengan hal-hal yang tidak dipedulikan orang luar? Kosong () berfungsi untuk kategori pribadi dalam file .m, dan mengeluarkan kompilasi peringatan jika Anda tidak mengimplementasikan metode yang dideklarasikan.
3) Saya telah mengambil untuk menempatkan dealloc di bagian atas file .m, tepat di bawah arahan @sintesis. Bukankah seharusnya yang Anda miliki berada di urutan teratas dalam daftar hal-hal yang ingin Anda pikirkan di kelas? Itu terutama berlaku di lingkungan seperti iPhone.
3.5) Dalam sel tabel, buat setiap elemen (termasuk sel itu sendiri) buram untuk kinerja. Itu berarti mengatur warna latar belakang yang sesuai dalam segala hal.
3.6) Saat menggunakan NSURLConnection, sebagai aturan Anda mungkin ingin menerapkan metode delegasi:
- (NSCachedURLResponse *)connection:(NSURLConnection *)connection
willCacheResponse:(NSCachedURLResponse *)cachedResponse
{
return nil;
}
Saya menemukan sebagian besar panggilan web sangat unik dan ini lebih merupakan pengecualian daripada aturan yang Anda ingin cached tanggapan, terutama untuk panggilan layanan web. Menerapkan metode seperti yang ditunjukkan menonaktifkan caching tanggapan.
Yang juga menarik, adalah beberapa kiat khusus iPhone yang bagus dari Joseph Mattiello (diterima di milis iPhone). Ada lebih banyak, tetapi ini adalah yang paling berguna menurut saya (perhatikan bahwa beberapa bit sekarang telah sedikit diedit dari aslinya untuk memasukkan rincian yang ditawarkan dalam tanggapan):
4) Hanya gunakan presisi ganda jika Anda harus, seperti ketika bekerja dengan CoreLocation. Pastikan Anda mengakhiri konstanta Anda di 'f' untuk membuat gcc menyimpannya sebagai pelampung.
float val = someFloat * 2.2f;
Ini sebagian besar penting ketika someFloat
sebenarnya merupakan dobel, Anda tidak memerlukan matematika mode campuran, karena Anda kehilangan presisi dalam 'val' pada penyimpanan. Sementara angka floating-point didukung dalam perangkat keras pada iPhone, masih mungkin membutuhkan lebih banyak waktu untuk melakukan aritmatika presisi ganda sebagai lawan dari presisi tunggal. Referensi:
Pada ponsel lama seharusnya perhitungan beroperasi pada kecepatan yang sama tetapi Anda dapat memiliki lebih banyak komponen presisi tunggal dalam register daripada dua kali lipat, sehingga untuk banyak perhitungan presisi tunggal akan berakhir menjadi lebih cepat.
5) Tetapkan properti Anda sebagai nonatomic
. Mereka atomic
secara default dan pada sintesis, kode semaphore akan dibuat untuk mencegah masalah multi-threading. 99% dari Anda mungkin tidak perlu khawatir tentang hal ini dan kodenya jauh lebih sedikit membengkak dan lebih hemat memori ketika diatur ke nonatomik.
6) SQLite bisa menjadi cara yang sangat, sangat cepat untuk men-cache set data yang besar. Aplikasi peta misalnya dapat men-cache ubinnya ke file SQLite. Bagian yang paling mahal adalah disk I / O. Hindari banyak tulisan kecil dengan mengirim BEGIN;
dan di COMMIT;
antara blok besar. Kami menggunakan penghitung waktu 2 detik misalnya yang diatur ulang pada setiap pengiriman baru. Ketika kedaluwarsa, kami mengirimkan COMMIT; , yang menyebabkan semua tulisan Anda masuk dalam satu potongan besar. SQLite menyimpan data transaksi ke disk dan melakukan pembungkus Begin / End ini menghindari pembuatan banyak file transaksi, mengelompokkan semua transaksi menjadi satu file.
Juga, SQL akan memblokir GUI Anda jika ada di utas utama Anda. Jika Anda memiliki kueri yang sangat panjang, ide yang bagus untuk menyimpan kueri Anda sebagai objek statis, dan menjalankan SQL Anda di utas terpisah. Pastikan untuk membungkus apa pun yang memodifikasi database untuk string kueri dalam @synchronize() {}
blok. Untuk pertanyaan singkat tinggalkan saja hal-hal di utas utama untuk kenyamanan yang lebih mudah.
Lebih banyak kiat pengoptimalan SQLite ada di sini, meskipun dokumen tersebut kedaluwarsa, banyak poin yang mungkin masih bagus;
http://web.utk.edu/~jplyon/sqlite/SQLite_optimization_FAQ.html
Ketika metode atau fungsi mengambil argumen string format, Anda harus memastikan bahwa Anda memiliki kontrol atas konten string format.
Misalnya, saat mencatat string, tergoda untuk meneruskan variabel string sebagai satu-satunya argumen untuk NSLog
:
NSString *aString = // get a string from somewhere;
NSLog(aString);
Masalah dengan ini adalah bahwa string dapat berisi karakter yang ditafsirkan sebagai format string. Ini dapat menyebabkan masalah output, crash, dan masalah keamanan. Sebagai gantinya, Anda harus mengganti variabel string menjadi string format:
NSLog(@"%@", aString);
Gunakan konvensi penamaan dan pemformatan standar Cocoa dan terminologi alih-alih apa pun yang Anda gunakan dari lingkungan lain. Ada yang banyak pengembang Kakao di luar sana, dan ketika salah satu dari mereka mulai bekerja dengan kode Anda, itu akan jauh lebih mudah didekati jika terlihat dan terasa mirip dengan kode Cocoa lain.
Contoh apa yang harus dilakukan dan apa yang tidak boleh dilakukan:
id m_something;
dalam antarmuka objek dan menyebutnya variabel anggota atau bidang ; gunakan something
atau _something
untuk namanya dan sebut itu variabel instan .-getSomething
; nama Kakao yang tepat adalah adil -something
.-something:
; harus-setSomething:
-[NSObject performSelector:withObject:]
, tidak NSObject::performSelector
.Apa pun yang Anda lakukan, jangan gunakan notasi Hungaria gaya Win16 / Win32. Bahkan Microsoft menyerah pada itu dengan pindah ke platform .NET.
Secara historis, manajemen memori outlet sudah buruk. Praktik terbaik saat ini adalah mendeklarasikan outlet sebagai properti:
@interface MyClass :NSObject {
NSTextField *textField;
}
@property (nonatomic, retain) IBOutlet NSTextField *textField;
@end
Menggunakan properti membuat semantik manajemen memori menjadi jelas; itu juga menyediakan pola yang konsisten jika Anda menggunakan sintesis variabel instan.
CATATAN: Di bawah Xcode 4 ini sekarang dibangun ke dalam IDE.
Anda menggunakan Clang Static Analyzer untuk - secara tidak mengejutkan - menganalisis kode C dan Objective-C Anda (belum ada C ++) di Mac OS X 10.5. Sepele untuk menginstal dan menggunakan:
cd
ke direktori proyek Anda.scan-build -k -V xcodebuild
.(Ada beberapa kendala tambahan dll., Khususnya Anda harus menganalisis proyek dalam konfigurasi "Debug" - lihat http://clang.llvm.org/StaticAnalysisUsage.html untuk detailnya - tapi itu lebih atau kurang apa intinya.)
Penganalisa kemudian menghasilkan satu set halaman web untuk Anda yang menunjukkan kemungkinan manajemen memori dan masalah dasar lainnya yang tidak dapat dideteksi oleh kompiler.
Ini yang halus tapi praktis. Jika Anda menyerahkan diri sebagai delegasi ke objek lain, setel ulang delegasi objek itu sebelum Anda dealloc
.
- (void)dealloc
{
self.someObject.delegate = NULL;
self.someObject = NULL;
//
[super dealloc];
}
Dengan melakukan ini, Anda memastikan tidak ada lagi metode delegasi yang akan dikirim. Saat Anda akandealloc
dan menghilang ke eter Anda ingin memastikan bahwa tidak ada yang dapat mengirimi Anda pesan lagi secara tidak sengaja. Ingat diri Anda sendiri. Beberapa objek dapat disimpan oleh objek lain (bisa tunggal atau di kolam autorelease atau apa pun) dan sampai Anda mengatakan "berhenti mengirimi saya pesan!", Ia berpikir objek Anda yang baru saja akan dealloced adalah permainan yang adil.
Masuk ke kebiasaan ini akan menyelamatkan Anda dari banyak crash aneh yang menyulitkan untuk debug.
Prinsipal yang sama berlaku untuk Pengamatan Nilai Kunci, dan NSNotifikasi juga.
Edit:
Yang lebih defensif, ubah:
self.someObject.delegate = NULL;
ke:
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
. Mereka persis sama kecuali itu nil
adalah id
dan NULL
adalah a void *
. Pernyataan Anda tidak benar.
@endell
Dari pada:
@interface MyClass (private)
- (void) someMethod
- (void) someOtherMethod
@end
Menggunakan:
@interface MyClass ()
- (void) someMethod
- (void) someOtherMethod
@end
Baru di Objective-C 2.0.
Ekstensi kelas dijelaskan dalam Referensi Objective-C 2.0 Apple.
"Ekstensi kelas memungkinkan Anda untuk mendeklarasikan API tambahan yang diperlukan untuk kelas di lokasi selain dari dalam kelas utama @interface blok"
Jadi mereka adalah bagian dari kelas aktual - dan BUKAN kategori (pribadi) selain kelas. Perbedaan yang halus tapi penting.
()
daripada (Private)
(atau beberapa nama kategori lainnya): Anda dapat mendeklarasikan ulang properti sebagai readwrite sementara untuk umum mereka hanya dibaca saja. :)
Karena Anda biasanya (1) tidak memiliki kendali langsung selama masa pakainya, objek autoreleased dapat bertahan untuk waktu yang relatif lama dan secara tidak perlu meningkatkan jejak memori aplikasi Anda. Sementara di desktop ini mungkin ada konsekuensi kecil, pada platform yang lebih terbatas ini bisa menjadi masalah yang signifikan. Oleh karena itu, pada semua platform, dan terutama pada platform yang lebih terbatas, ini dianggap praktik terbaik untuk menghindari menggunakan metode yang akan mengarah ke objek autoreleased dan sebaliknya Anda didorong untuk menggunakan pola alokasi / init.
Jadi, daripada:
aVariable = [AClass convenienceMethod];
jika memungkinkan, Anda sebaiknya menggunakan:
aVariable = [[AClass alloc] init];
// do things with aVariable
[aVariable release];
Saat Anda menulis metode Anda sendiri yang mengembalikan objek yang baru dibuat, Anda dapat memanfaatkan konvensi penamaan Cocoa untuk menandai ke penerima yang harus dilepaskan dengan menambahkan nama metode dengan "baru".
Jadi, bukannya:
- (MyClass *)convenienceMethod {
MyClass *instance = [[[self alloc] init] autorelease];
// configure instance
return instance;
}
Anda bisa menulis:
- (MyClass *)newInstance {
MyClass *instance = [[self alloc] init];
// configure instance
return instance;
}
Karena nama metode dimulai dengan "baru", konsumen API Anda tahu bahwa mereka bertanggung jawab untuk melepaskan objek yang diterima (lihat, misalnya, metode NSObjectController'snewObject
).
(1) Anda dapat mengambil kendali dengan menggunakan kolam autorelease lokal Anda sendiri. Untuk lebih lanjut tentang ini, lihat Autorelease Pools .
NSAutoreleasePool
. Tetapi hanya setelah Anda mengkonfirmasi bahwa ini benar-benar masalah. Optimalisasi prematur dan semua itu ...
Beberapa di antaranya telah disebutkan, tetapi inilah yang dapat saya pikirkan dari atas kepala saya:
#pragma mark [section]
. Biasanya saya mengelompokkan dengan metode saya sendiri, penggantian setiap subclass, dan informasi atau protokol formal apa pun. Ini membuatnya jauh lebih mudah untuk melompat ke apa yang saya cari. Pada topik yang sama, kelompokkan metode serupa (seperti metode delegasi tampilan tabel) bersama-sama, jangan hanya menempelkannya di mana saja.#define
akan melakukan, atau caching array bukannya mengurutkannya setiap kali data dibutuhkan. Ada banyak yang bisa saya katakan tentang ini, tetapi intinya adalah jangan menulis kode sampai Anda membutuhkannya, atau profiler memberitahu Anda untuk melakukannya. Itu membuat banyak hal lebih mudah untuk dipertahankan dalam jangka panjang.NSLog( @"stub" )
dalam, atau bagaimanapun Anda ingin melacak hal-hal.Finish what you start
Anda juga dapat menggunakan // TODO:
untuk menandai kode untuk penyelesaian yang akan muncul di drop down.
Tulis tes unit. Anda dapat menguji banyak hal dalam Kakao yang mungkin lebih sulit dalam kerangka kerja lain. Misalnya, dengan kode UI, Anda biasanya dapat memverifikasi bahwa segala sesuatu terhubung sebagaimana mestinya dan percaya bahwa semuanya akan berfungsi saat digunakan. Dan Anda dapat mengatur negara & memanggil metode delegasi dengan mudah untuk mengujinya.
Anda juga tidak memiliki visibilitas metode publik vs. terlindungi vs pribadi yang menghalangi penulisan tes untuk internal Anda.
Golden Rule: Jika kamu alloc
maka kamu release
!
UPDATE: Kecuali Anda menggunakan ARC
copy
, mutableCopy
, new
atau retain
.
Jangan menulis Objective-C seolah-olah itu Java / C # / C ++ / etc.
Saya pernah melihat tim yang biasa menulis aplikasi web Java EE mencoba menulis aplikasi desktop Cocoa. Seolah-olah itu adalah aplikasi web Java EE. Ada banyak AbstractFooFactory dan FooFactory dan IFoo dan Foo terbang di sekitar ketika semua yang mereka butuhkan adalah kelas Foo dan mungkin protokol Fooable.
Bagian dari memastikan Anda tidak melakukan ini adalah benar-benar memahami perbedaan dalam bahasa. Misalnya, Anda tidak memerlukan pabrik abstrak dan kelas pabrik di atas karena metode kelas Objective-C dikirimkan sama dinamisnya dengan metode instance, dan dapat ditimpa dalam subkelas.
Pastikan Anda mem-bookmark halaman Magic Debugging . Ini harus menjadi perhentian pertama Anda ketika membenturkan kepala ke dinding saat mencoba menemukan sumber bug Cocoa.
Misalnya, ini akan memberi tahu Anda bagaimana menemukan metode di mana Anda pertama kali mengalokasikan memori yang kemudian menyebabkan kerusakan (seperti saat penghentian aplikasi).
Cobalah untuk menghindari apa yang sekarang saya putuskan untuk memanggil Newbiecategoryaholism. Ketika pendatang baru di Objective-C menemukan kategori mereka sering menjadi liar, menambahkan kategori kecil yang berguna untuk setiap kelas yang ada ( "Apa? Saya bisa menambahkan metode untuk mengubah angka menjadi angka romawi menjadi NSNumber rock on!" ).
Jangan lakukan ini.
Kode Anda akan lebih portabel dan lebih mudah dipahami tanpa banyak metode kategori kecil yang ditaburkan di atas dua lusin kelas dasar.
Sebagian besar waktu ketika Anda benar-benar berpikir Anda membutuhkan metode kategori untuk membantu merampingkan beberapa kode Anda akan menemukan Anda tidak pernah akhirnya menggunakan kembali metode tersebut.
Ada bahaya lain juga, kecuali jika Anda menempatkan metode kategori Anda (dan siapa selain ddribin yang benar-benar gila?) Ada kemungkinan bahwa Apple, atau plugin, atau sesuatu yang berjalan di ruang alamat Anda juga akan menentukan kategori yang sama metode dengan nama yang sama dengan efek samping yang sedikit berbeda ....
BAIK. Sekarang Anda telah diperingatkan, abaikan "jangan lakukan bagian ini". Tetapi berolahraga dengan menahan diri.
Tahan subklas dunia. Dalam Cocoa banyak dilakukan melalui pendelegasian dan penggunaan runtime yang mendasarinya yang dalam kerangka kerja lain dilakukan melalui subclassing.
Sebagai contoh, di Jawa Anda sering menggunakan instance dari *Listener
subclass anonim dan .NET Anda banyak menggunakan EventArgs
subclass Anda . Di Cocoa, Anda tidak melakukan keduanya - target-aksi digunakan sebagai gantinya.
Saat Anda mengurutkan string untuk disajikan kepada pengguna, Anda tidak harus menggunakan compare:
metode sederhana . Sebagai gantinya, Anda harus selalu menggunakan metode perbandingan lokal seperti localizedCompare:
atau localizedCaseInsensitiveCompare:
.
Untuk detail lebih lanjut, lihat Menelusuri, Membandingkan, dan Menyortir String .
Anda biasanya harus menggunakan fitur Objective-C 2.0 Declared Properties untuk semua properti Anda. Jika tidak publik, tambahkan di ekstensi kelas. Menggunakan properti yang dideklarasikan membuat semantik manajemen memori segera menjadi jelas, dan membuatnya lebih mudah bagi Anda untuk memeriksa metode dealloc Anda - jika Anda mengelompokkan deklarasi properti Anda bersama-sama, Anda dapat dengan cepat memindai dan membandingkannya dengan penerapan metode dealloc Anda.
Anda harus berpikir keras sebelum tidak menandai properti sebagai 'nonatomik'. Seperti yang dicatat oleh Panduan Bahasa Pemrograman Objective C , properti adalah atom secara default, dan menimbulkan overhead yang besar. Selain itu, hanya membuat semua properti Anda tidak membuat aplikasi Anda aman. Juga perhatikan, tentu saja, bahwa jika Anda tidak menentukan 'nonatomik' dan mengimplementasikan metode pengakses Anda sendiri (daripada mensintesisnya), Anda harus mengimplementasikannya dengan cara atom.
Sebagaimana dicatat oleh pertanyaan ini , pesan-pesan menjadi nil
valid di Objective-C. Meskipun ini sering merupakan keuntungan - yang mengarah pada kode yang lebih bersih dan lebih alami - fitur ini kadang-kadang dapat menyebabkan bug yang aneh dan sulit dilacak jika Anda mendapatkan nil
nilai saat Anda tidak mengharapkannya.
Gunakan NSAssert dan teman-teman. Saya menggunakan nil sebagai objek yang valid sepanjang waktu ... terutama mengirim pesan ke nil benar-benar valid di Obj-C. Namun jika saya benar-benar ingin memastikan keadaan variabel, saya menggunakan NSAssert dan NSParameterAssert, yang membantu melacak masalah dengan mudah.
Sederhana tapi sering dilupakan. Menurut spec:
Secara umum, metode di kelas yang berbeda yang memiliki pemilih yang sama (nama yang sama) juga harus berbagi jenis argumen dan pengembalian yang sama. Batasan ini dikenakan oleh kompiler untuk memungkinkan pengikatan dinamis.
dalam hal ini semua penyeleksi bernama yang sama, bahkan jika dalam kelas yang berbeda , akan dianggap memiliki tipe pengembalian / argumen yang identik. Ini adalah contoh sederhana.
@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;
}
Jika Anda menggunakan Leopard (Mac OS X 10.5) atau lebih baru, Anda dapat menggunakan aplikasi Instruments untuk menemukan dan melacak kebocoran memori. Setelah membuat program Anda di Xcode, pilih Jalankan> Mulai dengan Alat Kinerja> Kebocoran.
Bahkan jika aplikasi Anda tidak menunjukkan kebocoran, Anda mungkin menyimpan benda terlalu lama. Di Instrumen, Anda bisa menggunakan instrumen ObjectAlloc untuk ini. Pilih instrumen ObjectAlloc dalam dokumen Instrumen Anda, dan buka detail instrumen (jika belum ditampilkan) dengan memilih View> Detail (harus memiliki tanda centang di sebelahnya). Di bawah "Allokasi Lifespan" di detail ObjectAlloc, pastikan Anda memilih tombol radio di sebelah "Created & Still Living".
Sekarang setiap kali Anda berhenti merekam aplikasi Anda, memilih alat ObjectAlloc akan menunjukkan kepada Anda berapa banyak referensi untuk setiap objek yang masih hidup dalam aplikasi Anda di kolom "# Net". Pastikan Anda tidak hanya melihat kelas Anda sendiri, tetapi juga kelas objek tingkat atas file NIB Anda. Misalnya, jika Anda tidak memiliki jendela di layar, dan Anda melihat referensi ke NSWindow yang masih hidup, Anda mungkin belum merilisnya dalam kode Anda.
Bersihkan di dealloc.
Ini adalah salah satu hal yang paling mudah untuk dilupakan - esp. saat pengkodean pada 150mph. Selalu, selalu, selalu bersihkan atribut / variabel anggota Anda di dealloc.
Saya suka menggunakan atribut Objc 2 - dengan notasi titik baru - jadi ini membuat pembersihan tidak menyakitkan. Seringkali sesederhana:
- (void)dealloc
{
self.someAttribute = NULL;
[super dealloc];
}
Ini akan menangani rilis untuk Anda dan mengatur atribut ke NULL (yang saya anggap pemrograman defensif - jika metode lain lebih jauh di dealloc mengakses variabel anggota lagi - jarang tetapi bisa terjadi).
Dengan GC dihidupkan dalam 10.5, ini tidak diperlukan lagi - tetapi Anda mungkin masih perlu membersihkan sumber daya lain yang Anda buat, Anda bisa melakukannya dengan metode finalisasi.
-init
dan -dealloc
metode dapat ditemukan di sini: mikeash.com/?page=pyblog/…
Semua komentar ini bagus, tapi saya benar-benar terkejut tidak ada yang menyebutkan Panduan Gaya Objective-C Google yang diterbitkan beberapa waktu lalu. Saya pikir mereka telah melakukan pekerjaan yang sangat teliti.
Juga, topik semi-terkait (dengan ruang untuk lebih banyak tanggapan!):
Apa saja tip & trik Xcode kecil yang ingin Anda ketahui 2 tahun yang lalu? .
Satu yang agak jelas untuk digunakan pemula: gunakan fitur indentasi otomatis Xcode untuk kode Anda. Bahkan jika Anda menyalin / menempel dari sumber lain, setelah Anda menempelkan kode, Anda dapat memilih seluruh blok kode, klik kanan padanya, dan kemudian pilih opsi untuk indentasi ulang segala sesuatu di dalam blok itu.
Xcode sebenarnya akan mem-parsing melalui bagian itu dan membuat indentasi berdasarkan kurung, loop, dll. Ini jauh lebih efisien daripada menekan spasi atau tombol tab untuk setiap baris.
Saya tahu saya mengabaikan ini ketika pertama kali masuk ke pemrograman Kakao.
Pastikan Anda memahami tanggung jawab manajemen memori terkait file NIB. Anda bertanggung jawab untuk merilis objek tingkat atas dalam file NIB apa pun yang Anda muat. Baca Dokumentasi Apple tentang masalah ini.
Nyalakan semua peringatan GCC, lalu matikan yang secara teratur disebabkan oleh header Apple untuk mengurangi kebisingan.
Juga sering menjalankan analisis statis Dentang; Anda dapat mengaktifkannya untuk semua build melalui pengaturan build "Run Static Analyzer".
Tulis pengujian unit dan jalankan dengan setiap build.
Variabel dan properti
1 / Menjaga header Anda tetap bersih, menyembunyikan implementasi,
Jangan sertakan variabel instan di header Anda. Variabel pribadi dimasukkan ke dalam kelanjutan kelas sebagai properti. Variabel publik menyatakan sebagai properti publik di header Anda. Jika seharusnya hanya dibaca, mendeklarasikannya sebagai hanya baca dan menimpanya sebagai readwrite dalam lanjutan kelas. Pada dasarnya saya tidak menggunakan variabel sama sekali, hanya properti.
2 / Berikan properti Anda nama variabel non-default, misalnya:
@synthesize property = property_;
Alasan 1: Anda akan menangkap kesalahan yang disebabkan oleh lupa "diri." saat menetapkan properti. Alasan 2: Dari percobaan saya, Leak Analyzer di Instrumen memiliki masalah untuk mendeteksi kebocoran properti dengan nama default.
3 / Jangan pernah menggunakan mempertahankan atau melepaskan langsung pada properti (atau hanya dalam situasi yang sangat luar biasa). Di dealloc Anda, tetapkan saja nihil. Properti retensi dimaksudkan untuk menangani retain / release sendiri. Anda tidak pernah tahu apakah seorang setter tidak, misalnya, menambah atau menghapus pengamat. Anda harus menggunakan variabel secara langsung hanya di dalam setter dan pengambilnya.
Tampilan
1 / Masukkan setiap definisi tampilan ke xib, jika Anda bisa (pengecualian biasanya konten dinamis dan pengaturan layer). Menghemat waktu (lebih mudah daripada menulis kode), mudah diubah dan menjaga kode Anda tetap bersih.
2 / Jangan mencoba mengoptimalkan tampilan dengan mengurangi jumlah tampilan. Jangan membuat UIImageView dalam kode Anda, bukan xib hanya karena Anda ingin menambahkan subview ke dalamnya. Gunakan UIImageView sebagai latar belakang. Kerangka kerja tampilan dapat menangani ratusan tampilan tanpa masalah.
3 / IBOutlet tidak harus selalu dipertahankan (atau kuat). Perhatikan bahwa sebagian besar IBOutlet Anda adalah bagian dari hierarki tampilan Anda dan dengan demikian secara implisit dipertahankan.
4 / Lepaskan semua IBOutlets dalam viewDidUnload
5 / Panggil viewDidUnload dari metode dealloc Anda. Itu tidak secara implisit disebut.
Penyimpanan
1 / Autorelease objek saat Anda membuatnya. Banyak bug disebabkan oleh pemindahan panggilan rilis Anda ke cabang if-else atau setelah pernyataan pengembalian. Pelepasan alih-alih autorelease harus digunakan hanya dalam situasi luar biasa - misalnya ketika Anda menunggu runloop dan Anda tidak ingin objek Anda autoreleased terlalu dini.
2 / Bahkan jika Anda menggunakan Penghitungan Referensi Authomatic, Anda harus memahami dengan sempurna cara kerja metode pelepasan-pelepasan. Menggunakan retain-release secara manual tidak lebih rumit dari ARC, dalam kedua kasus Anda harus memikirkan kebocoran dan mempertahankan-siklus. Pertimbangkan untuk menggunakan retain-release secara manual pada proyek besar atau hierarki objek yang rumit.
Komentar
1 / Jadikan kode Anda didokumentasikan secara otomatis. Setiap nama variabel dan nama metode harus memberi tahu apa yang dilakukannya. Jika kode ditulis dengan benar (Anda perlu banyak latihan dalam hal ini), Anda tidak memerlukan komentar kode apa pun (tidak sama dengan komentar dokumentasi). Algoritma bisa rumit tetapi kode harus selalu sederhana.
2 / Terkadang, Anda perlu komentar. Biasanya untuk menggambarkan perilaku kode yang tidak jelas atau peretasan. Jika Anda merasa harus menulis komentar, pertama-tama cobalah untuk menulis ulang kode menjadi lebih sederhana dan tanpa perlu komentar.
Lekukan
1 / Jangan terlalu meningkatkan indentasi. Sebagian besar kode metode Anda harus diindentasi pada level metode. Blok bersarang (jika, untuk dll.) Mengurangi keterbacaan. Jika Anda memiliki tiga blok bersarang, Anda harus mencoba menempatkan blok dalam ke dalam metode terpisah. Empat atau lebih blok bersarang tidak boleh digunakan. Jika sebagian besar kode metode Anda berada di dalam if, abaikan kondisi if, contoh:
if (self) {
//... long initialization code ...
}
return self;
if (!self) {
return nil;
}
//... long initialization code ...
return self;
Memahami kode C, terutama C struct
Perhatikan bahwa Obj-C hanya lapisan OOP ringan di atas bahasa C. Anda harus memahami bagaimana struktur kode dasar dalam pekerjaan C (enum, struct, array, pointer dll). Contoh:
view.frame = CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, view.frame.size.height + 20);
sama dengan:
CGRect frame = view.frame;
frame.size.height += 20;
view.frame = frame;
Dan masih banyak lagi
Lindungi dokumen standar pengodean Anda sendiri dan seringlah perbarui. Cobalah belajar dari bug Anda. Pahami mengapa bug dibuat dan cobalah menghindarinya menggunakan standar pengkodean.
Standar pengkodean kami saat ini memiliki sekitar 20 halaman, campuran dari Standar Java Coding, Google Obj-C / C ++ Standar dan tambahan kami sendiri. Dokumentasikan kode Anda, gunakan indentasi standar standar, spasi putih dan garis kosong di tempat yang tepat, dll.
Lebih fungsional .
Objective-C adalah bahasa berorientasi objek, tetapi kerangka kerja Kakao gaya-fungsional sadar, dan dirancang gaya fungsional dalam banyak kasus.
Ada pemisahan sifat berubah-ubah. Gunakan kelas yang tidak berubah sebagai primer, dan objek yang bisa berubah sebagai sekunder. Misalnya, gunakan NSArray terutama, dan gunakan NSMutableArray hanya ketika Anda membutuhkannya.
Ada fungsi murni. Tidak banyak, beli banyak framework API yang didesain seperti fungsi murni. Lihatlah fungsi seperti CGRectMake()
atau CGAffineTransformMake()
. Jelas bentuk pointer terlihat lebih efisien. Namun argumen tidak langsung dengan pointer tidak dapat menawarkan efek samping bebas. Merancang struktur semaksimal mungkin. Pisahkan benda negara. Gunakan -copy
alih-alih -retain
saat memberikan nilai ke objek lain. Karena keadaan bersama dapat memengaruhi mutasi ke nilai di objek lain secara diam-diam. Jadi tidak bisa bebas efek samping. Jika Anda memiliki nilai dari eksternal dari objek, salinlah. Jadi, penting juga merancang keadaan bersama seminimal mungkin.
Namun jangan takut menggunakan fungsi tidak murni juga.
Ada evaluasi malas. Lihat sesuatu seperti -[UIViewController view]
properti. Tampilan tidak akan dibuat saat objek dibuat. Ini akan dibuat saat pemanggil membaca view
properti pada saat pertama. UIImage
tidak akan dimuat sampai benar-benar ditarik. Ada banyak implementasi seperti desain ini. Desain semacam ini sangat membantu untuk manajemen sumber daya, tetapi jika Anda tidak tahu konsep evaluasi malas, tidak mudah untuk memahami perilaku mereka.
Ada penutupan. Gunakan blok C sebanyak mungkin. Ini akan sangat menyederhanakan hidup Anda. Tapi baca sekali lagi tentang manajemen blok-memori sebelum menggunakannya.
Ada semi-otomatis GC. NSAutoreleasePool. Gunakan -autorelease
primer. Gunakan manual -retain/-release
sekunder saat Anda benar-benar membutuhkannya. (mis: optimasi memori, penghapusan sumber daya eksplisit)
autorelease
akan menyimpan memori lebih lama secara umum, dan manual retain/release
dapat mengurangi konsumsi memori dalam case ini. Namun itu harus menjadi panduan untuk optimasi kasus khusus (bahkan Anda selalu merasa!), Tidak bisa menjadi alasan untuk menggeneralisasi optimasi prematur sebagai praktik . Dan nyatanya, saran Anda tidak berlawanan dengan saya. Saya menyebutkannya sebagai kasus yang sangat dibutuhkan :)