Câu trả lời:
Có một vài điều tôi đã bắt đầu làm mà tôi không nghĩ là chuẩn:
1) Với sự ra đời của các thuộc tính, tôi không còn sử dụng các biến lớp "_" để tiền tố "riêng tư". Rốt cuộc, nếu một biến khác có thể được truy cập bởi các lớp khác thì không nên có thuộc tính cho nó? Tôi luôn không thích tiền tố "_" để làm cho mã xấu hơn, và bây giờ tôi có thể loại bỏ nó.
2) Nói về những điều riêng tư, tôi thích đặt các định nghĩa phương thức riêng tư trong tệp .m trong một phần mở rộng lớp như vậy:
#import "MyClass.h"
@interface MyClass ()
- (void) someMethod;
- (void) someOtherMethod;
@end
@implementation MyClass
Tại sao làm lộn xộn tệp .h với những thứ mà người ngoài không nên quan tâm? Trống () hoạt động cho các danh mục riêng tư trong tệp .m và đưa ra các cảnh báo biên dịch nếu bạn không triển khai các phương thức được khai báo.
3) Tôi đã thực hiện đặt dealloc ở đầu tệp .m, ngay bên dưới các chỉ thị @synthesize. Không phải những gì bạn giải quyết sẽ đứng đầu danh sách những điều bạn muốn nghĩ về một lớp học? Điều đó đặc biệt đúng trong một môi trường như iPhone.
3.5) Trong các ô của bảng, làm cho mọi phần tử (bao gồm cả chính ô) mờ đi để thực hiện. Điều đó có nghĩa là thiết lập màu nền thích hợp trong mọi thứ.
3.6) Khi sử dụng kết nối NSURLC, theo quy tắc, bạn có thể muốn thực hiện phương thức ủy nhiệm:
- (NSCachedURLResponse *)connection:(NSURLConnection *)connection
willCacheResponse:(NSCachedURLResponse *)cachedResponse
{
return nil;
}
Tôi thấy hầu hết các cuộc gọi web đều rất đơn lẻ và đó là ngoại lệ hơn so với quy tắc bạn sẽ muốn phản hồi được lưu trong bộ nhớ cache, đặc biệt là đối với các cuộc gọi dịch vụ web. Việc thực hiện phương pháp như được hiển thị sẽ vô hiệu hóa bộ đệm ẩn của các phản hồi.
Cũng đáng quan tâm, là một số lời khuyên cụ thể về iPhone tốt từ Joseph Mattiello (nhận được trong danh sách gửi thư của iPhone). Có nhiều hơn, nhưng đây là những thứ hữu ích nhất mà tôi nghĩ (lưu ý rằng một vài bit hiện đã được chỉnh sửa một chút so với bản gốc để bao gồm các chi tiết được cung cấp trong phản hồi):
4) Chỉ sử dụng độ chính xác gấp đôi nếu bạn phải, chẳng hạn như khi làm việc với CoreLocation. Hãy chắc chắn rằng bạn kết thúc các hằng số của mình trong 'f' để làm cho gcc lưu trữ chúng dưới dạng phao.
float val = someFloat * 2.2f;
Điều này chủ yếu quan trọng khi someFloat
thực sự có thể là gấp đôi, bạn không cần toán học ở chế độ hỗn hợp, vì bạn đang mất độ chính xác trong 'val' khi lưu trữ. Mặc dù số dấu phẩy động được hỗ trợ trong phần cứng trên iPhone, nhưng vẫn có thể mất nhiều thời gian hơn để thực hiện số học có độ chính xác kép so với độ chính xác đơn. Người giới thiệu:
Trên các điện thoại cũ được cho là các phép tính hoạt động ở cùng tốc độ nhưng bạn có thể có nhiều thành phần chính xác đơn hơn trong các thanh ghi hơn gấp đôi, do đó, đối với nhiều phép tính, độ chính xác đơn sẽ kết thúc nhanh hơn.
5) Đặt thuộc tính của bạn là nonatomic
. Họ đang atomic
theo mặc định và sau khi tổng hợp, semaphore mã sẽ được tạo ra để ngăn chặn vấn đề đa luồng. 99% trong số bạn có thể không cần phải lo lắng về điều này và mã ít bị cồng kềnh và tiết kiệm bộ nhớ hơn khi được đặt thành không phổ biến.
6) SQLite có thể là một cách rất, rất nhanh để lưu trữ các tập dữ liệu lớn. Ví dụ, một ứng dụng bản đồ có thể lưu trữ các ô của nó vào các tệp SQLite. Phần đắt nhất là đĩa I / O. Tránh viết nhiều bằng cách gửi BEGIN;
và COMMIT;
giữa các khối lớn. Chúng tôi sử dụng bộ đếm thời gian 2 giây, ví dụ, đặt lại trên mỗi lần gửi mới. Khi nó hết hạn, chúng tôi gửi CAM KẾT; , khiến cho tất cả các bài viết của bạn đi trong một đoạn lớn. SQLite lưu trữ dữ liệu giao dịch vào đĩa và thực hiện gói Bắt đầu / Kết thúc này để tránh tạo nhiều tệp giao dịch, nhóm tất cả các giao dịch vào một tệp.
Ngoài ra, SQL sẽ chặn GUI của bạn nếu nó nằm trên luồng chính của bạn. Nếu bạn có một truy vấn rất dài, thì nên lưu trữ các truy vấn của bạn dưới dạng các đối tượng tĩnh và chạy SQL của bạn trên một luồng riêng biệt. Đảm bảo bọc bất cứ thứ gì sửa đổi cơ sở dữ liệu cho các chuỗi truy vấn theo @synchronize() {}
khối. Đối với các truy vấn ngắn, chỉ cần để lại những thứ trên luồng chính để thuận tiện hơn.
Có nhiều mẹo tối ưu hóa SQLite hơn ở đây, mặc dù tài liệu xuất hiện rất nhiều điểm có thể vẫn còn tốt;
http://web.utk.edu/~jplyon/sqlite/SQLite_optimization_FAQ.html
Khi các phương thức hoặc hàm có một đối số chuỗi định dạng, bạn nên đảm bảo rằng bạn có quyền kiểm soát nội dung của chuỗi định dạng.
Ví dụ: khi ghi nhật ký chuỗi, việc truyền biến chuỗi là đối số duy nhất cho NSLog
:
NSString *aString = // get a string from somewhere;
NSLog(aString);
Vấn đề với điều này là chuỗi có thể chứa các ký tự được hiểu là chuỗi định dạng. Điều này có thể dẫn đến đầu ra sai, sự cố và vấn đề bảo mật. Thay vào đó, bạn nên thay thế biến chuỗi thành chuỗi định dạng:
NSLog(@"%@", aString);
Sử dụng các quy ước và thuật ngữ định dạng và đặt tên ca cao tiêu chuẩn hơn là bất cứ điều gì bạn đã sử dụng từ môi trường khác. Có rất nhiều các nhà phát triển ca cao trên mạng, và khi người khác trong số họ bắt đầu làm việc với mã của bạn, nó sẽ được nhiều dễ tiếp cận hơn nếu nó trông và cảm thấy tương tự để mã Cocoa khác.
Ví dụ về những việc cần làm và không nên làm:
id m_something;
trong giao diện của đối tượng và gọi nó là biến thành viên hoặc trường ; sử dụng something
hoặc _something
cho tên của nó và gọi nó là một biến thể hiện .-getSomething
; tên ca cao thích hợp là chỉ -something
.-something:
; nó nên-setSomething:
-[NSObject performSelector:withObject:]
, không phải NSObject::performSelector
.Dù bạn có làm gì đi nữa, đừng sử dụng ký hiệu Hungary kiểu Win16 / Win32. Ngay cả Microsoft đã từ bỏ điều đó với việc chuyển sang nền tảng .NET.
Trong lịch sử, quản lý bộ nhớ của các cửa hàng là kém. Thực tiễn tốt nhất hiện nay là khai báo các cửa hàng là tài sản:
@interface MyClass :NSObject {
NSTextField *textField;
}
@property (nonatomic, retain) IBOutlet NSTextField *textField;
@end
Sử dụng các thuộc tính làm cho ngữ nghĩa quản lý bộ nhớ rõ ràng; nó cũng cung cấp một mẫu nhất quán nếu bạn sử dụng tổng hợp biến thể hiện.
LƯU Ý: Trong Xcode 4, phần này hiện được tích hợp vào IDE.
Bạn sử dụng Trình phân tích tĩnh Clang để - không ngạc nhiên - phân tích mã C và Objective-C của bạn (chưa có C ++) trên Mac OS X 10.5. Việc cài đặt và sử dụng không quan trọng
cd
đến thư mục dự án của bạn.scan-build -k -V xcodebuild
.(Có một số ràng buộc bổ sung, v.v., đặc biệt bạn nên phân tích một dự án trong cấu hình "Gỡ lỗi" của nó - xem http://clang.llvm.org/StaticAnalysisUsage.html để biết chi tiết - nhưng ít nhiều những gì nó sôi lên.)
Sau đó, bộ phân tích tạo ra một tập hợp các trang web cho bạn thấy khả năng quản lý bộ nhớ và các vấn đề cơ bản khác mà trình biên dịch không thể phát hiện được.
Đây là một trong những tinh tế nhưng tiện dụng một. Nếu bạn tự chuyển mình làm đại biểu cho đối tượng khác, hãy đặt lại đại biểu của đối tượng đó trước bạn dealloc
.
- (void)dealloc
{
self.someObject.delegate = NULL;
self.someObject = NULL;
//
[super dealloc];
}
Bằng cách này, bạn đảm bảo rằng sẽ không có thêm phương thức ủy nhiệm nào được gửi. Khi bạn sắp dealloc
và biến mất trong ether, bạn muốn chắc chắn rằng không có gì có thể gửi cho bạn thêm bất kỳ tin nhắn nào một cách tình cờ. Hãy nhớ self.someObject có thể được giữ lại bởi một đối tượng khác (nó có thể là một người độc thân hoặc trên nhóm tự động hoặc bất cứ điều gì) và cho đến khi bạn nói với nó "ngừng gửi tin nhắn cho tôi!", Nó nghĩ rằng đối tượng sắp bị xử lý của bạn là trò chơi công bằng.
Tập thói quen này sẽ giúp bạn tránh khỏi nhiều sự cố kỳ lạ gây khó chịu.
Hiệu trưởng tương tự áp dụng cho Quan sát giá trị chính và NSNotifying cũng vậy.
Biên tập:
Thậm chí phòng thủ hơn, thay đổi:
self.someObject.delegate = NULL;
vào:
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
. Chúng giống hệt nhau ngoại trừ đó nil
là một id
và NULL
là một void *
. Tuyên bố của bạn không đúng.
@kendell
Thay vì:
@interface MyClass (private)
- (void) someMethod
- (void) someOtherMethod
@end
Sử dụng:
@interface MyClass ()
- (void) someMethod
- (void) someOtherMethod
@end
Mới trong Mục tiêu-C 2.0.
Các tiện ích mở rộng lớp được mô tả trong Tài liệu tham khảo Objective-C 2.0 của Apple.
"Tiện ích mở rộng lớp cho phép bạn khai báo API cần thiết bổ sung cho một lớp ở các vị trí khác ngoài khối chính @interface"
Vì vậy, chúng là một phần của lớp thực tế - và KHÔNG phải là một loại (riêng tư) ngoài lớp. Sự khác biệt tinh tế nhưng quan trọng.
()
thay vì(Private)
(hoặc một số tên danh mục khác): Bạn có thể xác định lại các thuộc tính dưới dạng đọc trong khi công khai chúng chỉ đọc. :)
Vì bạn thường (1) không có quyền kiểm soát trực tiếp trong suốt cuộc đời của họ, các đối tượng được tự động phát hành có thể tồn tại trong một thời gian tương đối dài và làm tăng một cách không cần thiết bộ nhớ ứng dụng của bạn. Trong khi trên máy tính để bàn, điều này có thể gây ra ít hậu quả, trên các nền tảng bị hạn chế hơn, đây có thể là một vấn đề quan trọng. Do đó, trên tất cả các nền tảng và đặc biệt là trên các nền tảng bị hạn chế hơn, nên tránh sử dụng các phương pháp dẫn đến các đối tượng tự động và thay vào đó, bạn nên sử dụng mô hình cấp phát / init.
Do đó, thay vì:
aVariable = [AClass convenienceMethod];
nơi có thể, thay vào đó bạn nên sử dụng:
aVariable = [[AClass alloc] init];
// do things with aVariable
[aVariable release];
Khi bạn đang viết các phương thức của riêng mình để trả về một đối tượng mới được tạo, bạn có thể tận dụng quy ước đặt tên của Cacao để gắn cờ cho người nhận rằng nó phải được phát hành bằng cách thêm tên phương thức bằng "mới".
Do đó, thay vì:
- (MyClass *)convenienceMethod {
MyClass *instance = [[[self alloc] init] autorelease];
// configure instance
return instance;
}
bạn có thể viết:
- (MyClass *)newInstance {
MyClass *instance = [[self alloc] init];
// configure instance
return instance;
}
Vì tên phương thức bắt đầu bằng "mới", người tiêu dùng API của bạn biết rằng họ chịu trách nhiệm giải phóng đối tượng đã nhận (ví dụ: xem, ví dụ: newObject
phương thức của NSObjectContoder ).
(1) Bạn có thể kiểm soát bằng cách sử dụng nhóm tự động điền địa phương của riêng bạn. Để biết thêm về điều này, xem Autorelease Pools .
NSAutoreleasePool
. Nhưng chỉ sau khi bạn xác nhận rằng đây thực sự là một vấn đề. Tối ưu hóa sớm và tất cả những thứ đó ...
Một số trong số này đã được đề cập, nhưng đây là những gì tôi có thể nghĩ ra khỏi đỉnh đầu:
#pragma mark [section]
. Thông thường tôi nhóm theo các phương thức của riêng tôi, các phần ghi đè của mỗi lớp con và bất kỳ thông tin hoặc giao thức chính thức nào. Điều này làm cho nó dễ dàng hơn nhiều để chuyển đến chính xác những gì tôi đang tìm kiếm. Trong cùng một chủ đề, nhóm các phương thức tương tự (như các phương thức ủy nhiệm của chế độ xem bảng) với nhau, không chỉ dán chúng ở bất cứ đâu.#define
sẽ làm hoặc lưu trữ một mảng thay vì sắp xếp nó mỗi khi cần dữ liệu. Có rất nhiều điều tôi có thể nói về điều này, nhưng điểm mấu chốt là không viết mã cho đến khi bạn cần nó, hoặc trình hồ sơ cho bạn biết. Nó làm cho mọi thứ dễ dàng hơn nhiều để duy trì trong thời gian dài.NSLog( @"stub" )
bên trong, hoặc tuy nhiên bạn muốn theo dõi mọi thứ.Finish what you start
bạn cũng có thể sử dụng // TODO:
để đánh dấu mã để hoàn thành sẽ hiển thị trong trình đơn thả xuống.
Viết bài kiểm tra đơn vị. Bạn có thể kiểm tra rất nhiều thứ trong Ca cao có thể khó hơn trong các khung khác. Ví dụ: với mã UI, bạn thường có thể xác minh rằng mọi thứ được kết nối như bình thường và tin tưởng rằng chúng sẽ hoạt động khi được sử dụng. Và bạn có thể thiết lập trạng thái & gọi các phương thức ủy nhiệm một cách dễ dàng để kiểm tra chúng.
Bạn cũng không có khả năng hiển thị công khai so với bảo vệ so với phương thức riêng tư trong cách viết bài kiểm tra cho nội bộ của bạn.
Nguyên tắc vàng: Nếu bạn alloc
thì bạn release
!
CẬP NHẬT: Trừ khi bạn đang sử dụng ARC
copy
, mutableCopy
, new
hoặc retain
.
Đừng viết Objective-C như thể nó là Java / C # / C ++ / etc.
Tôi đã từng thấy một nhóm được sử dụng để viết các ứng dụng web Java EE cố gắng viết một ứng dụng máy tính để bàn. Như thể đó là một ứng dụng web Java EE. Có rất nhiều AbstractFooFactory và FooFactory và IFoo và Foo bay xung quanh khi tất cả những gì họ thực sự cần là một lớp Foo và có thể là một giao thức Fooable.
Một phần của việc đảm bảo bạn không làm điều này là thực sự hiểu được sự khác biệt trong ngôn ngữ. Ví dụ, bạn không cần các lớp nhà máy và nhà máy trừu tượng ở trên vì các phương thức lớp Objective-C được gửi một cách linh hoạt như các phương thức cá thể và có thể được ghi đè trong các lớp con.
Hãy chắc chắn rằng bạn đánh dấu trang gỡ lỗi Magic . Đây phải là điểm dừng đầu tiên của bạn khi đập đầu vào tường trong khi cố gắng tìm ra nguồn gốc của lỗi Cacao.
Ví dụ, nó sẽ cho bạn biết cách tìm phương thức mà lần đầu tiên bạn cấp phát bộ nhớ mà sau đó gây ra sự cố (như trong khi chấm dứt ứng dụng).
Cố gắng tránh những gì tôi đã quyết định gọi Newbiec Categoryaholism. Khi những người mới tham gia Objective-C khám phá các danh mục, họ thường phát cuồng, thêm các danh mục nhỏ hữu ích cho mọi lớp đang tồn tại ( "Cái gì? Tôi có thể thêm một phương thức để chuyển đổi một số thành chữ số La Mã thành đá NSNumber trên!" ).
Đừng làm điều này.
Mã của bạn sẽ dễ mang theo hơn và dễ hiểu hơn với hàng tá phương thức danh mục nhỏ được rắc lên trên hai chục lớp nền tảng.
Hầu hết thời gian khi bạn thực sự nghĩ rằng bạn cần một phương pháp danh mục để giúp hợp lý hóa một số mã bạn sẽ thấy bạn sẽ không bao giờ sử dụng lại phương thức đó.
Cũng có những mối nguy hiểm khác, trừ khi bạn đặt tên cho các phương thức danh mục của mình (và ai ngoài ddribin hoàn toàn điên rồ thì sao?) Có khả năng Apple, hoặc một plugin, hoặc một thứ khác chạy trong không gian địa chỉ của bạn cũng sẽ xác định cùng một danh mục phương pháp có cùng tên với một tác dụng phụ hơi khác nhau ....
ĐỒNG Ý. Bây giờ bạn đã được cảnh báo, bỏ qua "không làm phần này". Nhưng tập thể dục cực hạn.
Chống lại phân lớp thế giới. Trong Ca cao rất nhiều được thực hiện thông qua ủy quyền và sử dụng thời gian chạy cơ bản mà trong các khung công tác khác được thực hiện thông qua phân lớp.
Ví dụ, trong Java, bạn sử dụng các thể hiện của các *Listener
lớp con ẩn danh rất nhiều và trong .NET bạn sử dụng các EventArgs
lớp con của mình rất nhiều. Trong Ca cao, bạn cũng không làm - hành động đích được sử dụng thay thế.
Khi bạn sắp xếp các chuỗi để trình bày cho người dùng, bạn không nên sử dụng compare:
phương thức đơn giản . Thay vào đó, bạn nên luôn luôn sử dụng các phương pháp so sánh cục bộ như localizedCompare:
hoặc localizedCaseInsensitiveCompare:
.
Để biết thêm chi tiết, xem Tìm kiếm, So sánh và Sắp xếp Chuỗi .
Thông thường bạn nên sử dụng tính năng Thuộc tính khai báo Objective-C 2.0 cho tất cả các thuộc tính của bạn. Nếu chúng không công khai, hãy thêm chúng trong phần mở rộng lớp. Việc sử dụng các thuộc tính khai báo làm cho ngữ nghĩa quản lý bộ nhớ rõ ràng ngay lập tức và giúp bạn dễ dàng kiểm tra phương thức dealloc của mình hơn - nếu bạn nhóm các khai báo thuộc tính của mình lại với nhau, bạn có thể nhanh chóng quét chúng và so sánh với việc thực hiện phương thức dealloc của bạn.
Bạn nên suy nghĩ kỹ trước khi không đánh dấu các thuộc tính là 'nonatomic'. Như Hướng dẫn ngôn ngữ lập trình mục tiêu C ghi chú, các thuộc tính được mặc định là nguyên tử và chịu chi phí đáng kể. Hơn nữa, chỉ đơn giản là làm cho tất cả các thuộc tính nguyên tử của bạn không làm cho luồng ứng dụng của bạn an toàn. Tất nhiên cũng lưu ý rằng, nếu bạn không chỉ định 'nonatomic' và thực hiện các phương thức truy cập của riêng bạn (thay vì tổng hợp chúng), bạn phải thực hiện chúng theo kiểu nguyên tử.
Như câu hỏi này lưu ý, các thông báo nil
có giá trị trong Objective-C. Mặc dù điều này thường là một lợi thế - dẫn đến mã sạch hơn và tự nhiên hơn - tính năng đôi khi có thể dẫn đến các lỗi đặc biệt và khó theo dõi nếu bạn nhận được nil
giá trị khi bạn không mong đợi.
Sử dụng NSAssert và bạn bè. Tôi sử dụng nil làm đối tượng hợp lệ mọi lúc ... đặc biệt là gửi tin nhắn đến nil là hoàn toàn hợp lệ trong Obj-C. Tuy nhiên nếu tôi thực sự muốn chắc chắn về trạng thái của một biến, tôi sử dụng NSAssert và NSParameterAssert, giúp dễ dàng theo dõi các vấn đề.
Đơn giản nhưng quên một. Theo thông số kỹ thuật:
Nói chung, các phương thức trong các lớp khác nhau có cùng bộ chọn (cùng tên) cũng phải chia sẻ cùng loại trả về và loại đối số. Ràng buộc này được áp đặt bởi trình biên dịch để cho phép liên kết động.
trong trường hợp đó, tất cả các bộ chọn có cùng tên, ngay cả trong các lớp khác nhau , sẽ được coi là có các kiểu trả về / đối số giống hệt nhau. Đây là một ví dụ đơn giản.
@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;
}
Nếu bạn đang sử dụng Leopard (Mac OS X 10.5) trở lên, bạn có thể sử dụng ứng dụng Dụng cụ để tìm và theo dõi rò rỉ bộ nhớ. Sau khi xây dựng chương trình của bạn trong Xcode, chọn Chạy> Bắt đầu với Công cụ hiệu suất> Rò rỉ.
Ngay cả khi ứng dụng của bạn không hiển thị bất kỳ rò rỉ nào, bạn có thể giữ các vật thể xung quanh quá lâu. Trong Dụng cụ, bạn có thể sử dụng công cụ ObjectAlloc cho việc này. Chọn công cụ ObjectAlloc trong tài liệu Công cụ của bạn và hiển thị chi tiết của công cụ (nếu nó chưa hiển thị) bằng cách chọn Xem> Chi tiết (cần có dấu kiểm bên cạnh). Trong phần "Tuổi thọ phân bổ" trong chi tiết ObjectAlloc, đảm bảo bạn chọn nút radio bên cạnh "Đã tạo và vẫn sống".
Bây giờ, bất cứ khi nào bạn dừng ghi ứng dụng của mình, việc chọn công cụ ObjectAlloc sẽ cho bạn thấy có bao nhiêu tài liệu tham khảo cho mỗi đối tượng còn sống trong ứng dụng của bạn trong cột "# Net". Hãy chắc chắn rằng bạn không chỉ nhìn vào các lớp của riêng bạn, mà cả các lớp của các đối tượng cấp cao nhất của tệp NIB. Ví dụ: nếu bạn không có cửa sổ trên màn hình và bạn thấy các tài liệu tham khảo về một trại giam vẫn còn sống, bạn có thể chưa phát hành nó trong mã của mình.
Dọn dẹp trong dealloc.
Đây là một trong những điều dễ quên nhất - đặc biệt. khi mã hóa ở tốc độ 150mph. Luôn luôn, luôn luôn, luôn dọn sạch các thuộc tính / biến thành viên của bạn trong dealloc.
Tôi thích sử dụng các thuộc tính Objc 2 - với ký hiệu dấu chấm mới - vì vậy điều này làm cho việc dọn dẹp không gây đau đớn. Thường đơn giản như:
- (void)dealloc
{
self.someAttribute = NULL;
[super dealloc];
}
Điều này sẽ chăm sóc của việc phát hành cho bạn và thiết lập các thuộc tính để NULL (mà tôi cân nhắc chương trình phòng thủ - trong trường hợp phương pháp khác tiếp tục xuống trong dealloc truy cập các biến thành viên một lần nữa - hiếm gặp nhưng có thể xảy ra).
Với GC được bật trong 10.5, điều này không còn cần thiết nữa - nhưng bạn vẫn có thể cần phải dọn sạch các tài nguyên khác mà bạn tạo, thay vào đó bạn có thể làm điều đó trong phương pháp hoàn thiện.
-init
và -dealloc
các phương thức có thể được tìm thấy ở đây: mikeash.com/?page=pyblog/ Kẻ
Tất cả những nhận xét này đều tuyệt vời, nhưng tôi thực sự ngạc nhiên khi không ai đề cập đến Hướng dẫn về Phong cách Mục tiêu-C của Google đã được xuất bản một thời gian trước. Tôi nghĩ rằng họ đã làm một công việc rất kỹ lưỡng.
Ngoài ra, chủ đề liên quan đến bán (có chỗ cho nhiều phản hồi hơn!):
Những mẹo & thủ thuật Xcode nhỏ mà bạn muốn bạn biết về 2 năm trước là gì? .
Một điều khá rõ ràng cho người mới bắt đầu sử dụng: sử dụng tính năng tự động thụt lề của Xcode cho mã của bạn. Ngay cả khi bạn đang sao chép / dán từ một nguồn khác, một khi bạn đã dán mã, bạn có thể chọn toàn bộ khối mã, nhấp chuột phải vào mã đó, sau đó chọn tùy chọn để thụt lại mọi thứ trong khối đó.
Xcode thực sự sẽ phân tích cú pháp qua phần đó và thụt lề dựa trên dấu ngoặc, vòng lặp, v.v ... Nó hiệu quả hơn nhiều so với việc nhấn phím cách hoặc phím tab cho mỗi dòng.
Tôi biết tôi đã bỏ qua điều này khi lần đầu tiên tham gia vào lập trình Cacao.
Hãy chắc chắn rằng bạn hiểu trách nhiệm quản lý bộ nhớ liên quan đến các tệp NIB. Bạn chịu trách nhiệm phát hành các đối tượng cấp cao nhất trong bất kỳ tệp NIB nào bạn tải. Đọc Tài liệu của Apple về chủ đề này.
Bật tất cả các cảnh báo GCC, sau đó tắt những cảnh báo thường xuyên gây ra bởi các tiêu đề của Apple để giảm tiếng ồn.
Cũng chạy phân tích tĩnh Clang thường xuyên; bạn có thể kích hoạt nó cho tất cả các bản dựng thông qua cài đặt bản dựng "Chạy phân tích tĩnh".
Viết bài kiểm tra đơn vị và chạy chúng với mỗi bản dựng.
Các biến và thuộc tính
1 / Giữ các tiêu đề của bạn sạch sẽ, ẩn việc thực hiện
Đừng bao gồm các biến thể hiện trong tiêu đề của bạn. Các biến riêng đưa vào lớp tiếp tục như các thuộc tính. Biến công khai khai báo là thuộc tính công khai trong tiêu đề của bạn. Nếu nó chỉ nên được đọc, hãy khai báo nó là chỉ đọc và ghi đè lên nó thành readwrite trong lớp tiếp theo. Về cơ bản tôi không sử dụng biến nào cả, chỉ thuộc tính.
2 / Đặt cho thuộc tính của bạn một tên biến không mặc định, ví dụ:
@synthesize property = property_;
Lý do 1: Bạn sẽ bắt lỗi do quên "bản thân". khi giao tài sản. Lý do 2: Từ các thử nghiệm của tôi, Phân tích rò rỉ trong dụng cụ có vấn đề để phát hiện tài sản bị rò rỉ với tên mặc định.
3 / Không bao giờ sử dụng giữ lại hoặc phát hành trực tiếp trên các thuộc tính (hoặc chỉ trong các tình huống rất đặc biệt). Trong dealloc của bạn chỉ cần gán cho họ một con số không. Giữ lại các thuộc tính có nghĩa là để tự xử lý giữ / phát hành. Bạn không bao giờ biết nếu một setter không, ví dụ, thêm hoặc xóa các quan sát viên. Bạn chỉ nên sử dụng biến trực tiếp bên trong setter và getter của nó.
Lượt xem
1 / Đặt mọi định nghĩa chế độ xem vào xib, nếu bạn có thể (ngoại lệ thường là cài đặt nội dung động và cài đặt lớp). Nó tiết kiệm thời gian (dễ hơn viết mã), dễ dàng thay đổi và giữ cho mã của bạn sạch sẽ.
2 / Đừng cố tối ưu hóa lượt xem bằng cách giảm số lượt xem. Đừng tạo UIImageView trong mã của bạn thay vì xib chỉ vì bạn muốn thêm các lượt xem vào nó. Sử dụng UIImageView làm nền thay thế. Khung nhìn có thể xử lý hàng trăm lượt xem mà không gặp vấn đề gì.
3 / IBOutlets không phải luôn được giữ lại (hoặc mạnh). Lưu ý rằng hầu hết các IBOutlets của bạn là một phần của hệ thống phân cấp chế độ xem của bạn và do đó hoàn toàn được giữ lại.
4 / Phát hành tất cả IBOutlets trong viewDidUnload
5 / Gọi viewDidUnload từ phương thức dealloc của bạn. Nó không được gọi ngầm.
Ký ức
1 / Autorelease object khi bạn tạo chúng. Nhiều lỗi xảy ra do chuyển cuộc gọi phát hành của bạn sang một nhánh if-other hoặc sau câu lệnh return. Phát hành thay vì autorelease chỉ nên được sử dụng trong các tình huống đặc biệt - ví dụ: khi bạn đang chờ đợi một runloop và bạn không muốn đối tượng của mình được tự động phát hành quá sớm.
2 / Ngay cả khi bạn đang sử dụng Đếm tham chiếu tự động, bạn phải hiểu một cách hoàn hảo cách các phương thức phát hành giữ lại hoạt động. Sử dụng phát hành giữ lại thủ công không phức tạp hơn ARC, trong cả hai trường hợp, bạn phải biết về rò rỉ và chu kỳ giữ lại. Xem xét sử dụng phát hành giữ lại thủ công trên các dự án lớn hoặc phân cấp đối tượng phức tạp.
Bình luận
1 / Làm cho mã của bạn tự động được ghi lại. Mỗi tên biến và tên phương thức sẽ cho biết nó đang làm gì. Nếu mã được viết chính xác (bạn cần thực hành nhiều trong phần này), bạn sẽ không cần bất kỳ nhận xét mã nào (không giống như nhận xét tài liệu). Các thuật toán có thể phức tạp nhưng mã phải luôn đơn giản.
2 / Đôi khi, bạn sẽ cần một bình luận. Thông thường để mô tả một hành vi mã không rõ ràng hoặc hack. Nếu bạn cảm thấy mình phải viết bình luận, trước tiên hãy thử viết lại mã để đơn giản hơn và không cần bình luận.
Lõm
1 / Đừng tăng thụt quá nhiều. Hầu hết mã phương thức của bạn nên được thụt vào ở mức phương thức. Các khối lồng nhau (nếu, v.v.) làm giảm khả năng đọc. Nếu bạn có ba khối lồng nhau, bạn nên cố gắng đặt các khối bên trong thành một phương thức riêng biệt. Bốn hoặc nhiều khối lồng nhau không bao giờ nên được sử dụng. Nếu hầu hết mã phương thức của bạn nằm trong if, hãy phủ nhận điều kiện if, ví dụ:
if (self) {
//... long initialization code ...
}
return self;
if (!self) {
return nil;
}
//... long initialization code ...
return self;
Hiểu mã C, chủ yếu là cấu trúc C
Lưu ý rằng Obj-C chỉ là lớp OOP nhẹ trên ngôn ngữ C. Bạn nên hiểu cách các cấu trúc mã cơ bản trong C hoạt động (enums, structs, mảng, con trỏ, v.v.). Thí dụ:
view.frame = CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, view.frame.size.height + 20);
giống như:
CGRect frame = view.frame;
frame.size.height += 20;
view.frame = frame;
Và nhiều thứ khác nữa
Mantain tài liệu tiêu chuẩn mã hóa của riêng bạn và cập nhật nó thường xuyên. Cố gắng học hỏi từ các lỗi của bạn. Hiểu lý do tại sao một lỗi được tạo ra và cố gắng tránh nó bằng cách sử dụng các tiêu chuẩn mã hóa.
Các tiêu chuẩn mã hóa của chúng tôi hiện có khoảng 20 trang, kết hợp các Tiêu chuẩn mã hóa Java, Tiêu chuẩn Google Obj-C / C ++ và các phần bổ sung của chúng tôi. Tài liệu mã của bạn, sử dụng thụt tiêu chuẩn tiêu chuẩn, khoảng trắng và dòng trống vào đúng nơi, v.v.
Có nhiều chức năng hơn .
Objective-C là ngôn ngữ hướng đối tượng, nhưng nhận thức theo kiểu chức năng của khung công tác và được thiết kế theo kiểu chức năng trong nhiều trường hợp.
Có sự tách biệt của tính đột biến. Sử dụng các lớp bất biến làm đối tượng chính và đối tượng có thể thay đổi làm phụ. Chẳng hạn, sử dụng NSArray là chủ yếu và chỉ sử dụng NSMutableArray khi bạn cần.
Có chức năng thuần túy. Không quá nhiều, mua nhiều API khung được thiết kế giống như hàm thuần túy. Nhìn vào các chức năng như CGRectMake()
hoặc CGAffineTransformMake()
. Rõ ràng hình thức con trỏ trông hiệu quả hơn. Tuy nhiên, đối số gián tiếp với con trỏ không thể cung cấp hiệu ứng phụ. Thiết kế cấu trúc hoàn toàn càng nhiều càng tốt. Riêng các đối tượng nhà nước. Sử dụng -copy
thay vì -retain
khi truyền một giá trị cho đối tượng khác. Bởi vì trạng thái chia sẻ có thể ảnh hưởng đột biến đến giá trị trong đối tượng khác một cách âm thầm. Vì vậy, không thể có tác dụng phụ. Nếu bạn có một giá trị từ bên ngoài từ đối tượng, sao chép nó. Vì vậy, nó cũng quan trọng thiết kế trạng thái chia sẻ tối thiểu nhất có thể.
Tuy nhiên, đừng sợ sử dụng các chức năng không tinh khiết quá.
Có đánh giá lười biếng. Xem một cái gì đó như -[UIViewController view]
tài sản. Khung nhìn sẽ không được tạo khi đối tượng được tạo. Nó sẽ được tạo khi người gọi đọc thuộc view
tính lần đầu tiên. UIImage
sẽ không được tải cho đến khi nó thực sự được rút ra. Có rất nhiều thực hiện như thiết kế này. Kiểu thiết kế này rất hữu ích cho việc quản lý tài nguyên, nhưng nếu bạn không biết khái niệm đánh giá lười biếng, thì không dễ để hiểu hành vi của chúng.
Có đóng cửa. Sử dụng khối C càng nhiều càng tốt. Điều này sẽ đơn giản hóa cuộc sống của bạn rất nhiều. Nhưng hãy đọc một lần nữa về quản lý bộ nhớ khối trước khi sử dụng nó.
Có bán tự động. NSAutoreleasePool. Sử dụng -autorelease
chính. Sử dụng -retain/-release
thứ cấp thủ công khi bạn thực sự cần. (ví dụ: tối ưu hóa bộ nhớ, xóa tài nguyên rõ ràng)
autorelease
sẽ giữ bộ nhớ lâu hơn và thủ công retain/release
có thể giảm mức tiêu thụ bộ nhớ trong trường hợp này. Tuy nhiên, đó phải là hướng dẫn để tối ưu hóa trường hợp đặc biệt (ngay cả khi bạn luôn cảm thấy!), Không thể là lý do để khái quát hóa tối ưu hóa sớm như thực tiễn . Và trên thực tế, đề nghị của bạn không đối nghịch với tôi. Tôi đã đề cập đến nó như một trường hợp thực sự cần thiết :)