Khả năng đặt các biến phiên bản trong @implementation
khối hoặc trong phần mở rộng lớp, là một tính năng của “thời gian chạy Objective-C hiện đại”, được sử dụng bởi mọi phiên bản iOS và các chương trình Mac OS X 64 bit.
Nếu bạn muốn viết các ứng dụng Mac OS X 32 bit, bạn phải đặt các biến phiên bản của mình trong phần @interface
khai báo. Tuy nhiên, rất có thể bạn không cần hỗ trợ phiên bản 32-bit của ứng dụng. OS X đã hỗ trợ các ứng dụng 64-bit kể từ phiên bản 10.5 (Leopard), được phát hành hơn 5 năm trước.
Vì vậy, giả sử bạn chỉ viết ứng dụng sẽ sử dụng thời gian chạy hiện đại. Bạn nên đặt ivars của mình ở đâu?
Tùy chọn 0: Trong @interface
(Không làm điều đó)
Đầu tiên, hãy xem xét lý do tại sao chúng ta không muốn đặt các biến cá thể trong một @interface
khai báo.
Việc đưa các biến cá thể vào một trình @interface
bày chi tiết về việc triển khai cho người dùng của lớp. Điều này có thể khiến những người dùng đó (ngay cả chính bạn khi sử dụng các lớp của riêng bạn!) Dựa vào các chi tiết triển khai mà họ không nên làm. (Điều này không phụ thuộc vào việc chúng tôi có khai báo ivars hay không @private
.)
Việc đưa các biến cá thể vào trong @interface
làm cho quá trình biên dịch mất nhiều thời gian hơn, bởi vì bất cứ khi nào chúng tôi thêm, thay đổi hoặc xóa khai báo ivar, chúng tôi phải biên dịch lại mọi .m
tệp nhập giao diện.
Vì vậy, chúng tôi không muốn đặt các biến cá thể trong @interface
. Chúng ta nên đặt chúng ở đâu?
Tùy chọn 2: Không @implementation
có dấu ngoặc nhọn (Không làm điều đó)
Tiếp theo, hãy thảo luận về tùy chọn 2 của bạn, “Đặt iVars dưới @implementantion mà không có khối dấu ngoặc nhọn”. Điều này không khai báo các biến cá thể! Bạn đang nói về điều này:
@implementation Person
int age;
NSString *name;
...
Mã đó xác định hai biến toàn cục. Nó không khai báo bất kỳ biến cá thể nào.
Bạn có thể xác định các biến toàn cục trong .m
tệp của mình , ngay cả trong tệp của mình @implementation
, nếu bạn cần các biến toàn cục - ví dụ: vì bạn muốn tất cả các phiên bản của mình chia sẻ một số trạng thái, chẳng hạn như bộ nhớ cache. Nhưng bạn không thể sử dụng tùy chọn này để khai báo ivars, vì nó không khai báo ivars. (Ngoài ra, các biến toàn cục riêng tư đối với việc triển khai của bạn thường nên được khai báo static
để tránh làm ô nhiễm không gian tên chung và có nguy cơ mắc lỗi thời gian liên kết.)
Điều đó để lại các tùy chọn 1 và 3 của bạn.
Tùy chọn 1: Trong @implementation
dấu ngoặc nhọn (Do It)
Thông thường, chúng tôi muốn sử dụng tùy chọn 1: đặt chúng vào @implementation
khối chính của bạn , trong dấu ngoặc nhọn, như sau:
@implementation Person {
int age;
NSString *name;
}
Chúng tôi đặt chúng ở đây vì nó giữ cho sự tồn tại của chúng ở chế độ riêng tư, ngăn ngừa các vấn đề mà tôi đã mô tả trước đó và bởi vì thường không có lý do gì để đặt chúng vào một phần mở rộng lớp.
Vậy khi nào chúng tôi muốn sử dụng tùy chọn 3 của bạn, đưa chúng vào phần mở rộng lớp?
Tùy chọn 3: Trong phần mở rộng lớp học (Chỉ thực hiện khi cần thiết)
Hầu như không bao giờ có lý do để đặt chúng trong phần mở rộng lớp trong cùng tệp với của lớp @implementation
. Chúng tôi cũng có thể đặt chúng vào @implementation
trường hợp đó.
Nhưng đôi khi chúng ta có thể viết một lớp đủ lớn để chúng ta muốn chia mã nguồn của nó thành nhiều tệp. Chúng tôi có thể làm điều đó bằng cách sử dụng các danh mục. Ví dụ: nếu chúng tôi đang triển khai UICollectionView
(một lớp khá lớn), chúng tôi có thể quyết định rằng chúng tôi muốn đặt mã quản lý hàng đợi các chế độ xem có thể sử dụng lại (ô và các chế độ xem bổ sung) trong một tệp nguồn riêng biệt. Chúng tôi có thể làm điều đó bằng cách tách các thư đó thành một danh mục:
@interface UICollectionView : UIScrollView
- (id)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout;
@property (nonatomic, retain) UICollectionView *collectionViewLayout;
@end
@interface UICollectionView (ReusableViews)
- (void)registerClass:(Class)cellClass forCellWithReuseIdentifier:(NSString *)identifier;
- (void)registerNib:(UINib *)nib forCellWithReuseIdentifier:(NSString *)identifier;
- (void)registerClass:(Class)viewClass forSupplementaryViewOfKind:(NSString *)elementKind withReuseIdentifier:(NSString *)identifier;
- (void)registerNib:(UINib *)nib forSupplementaryViewOfKind:(NSString *)kind withReuseIdentifier:(NSString *)identifier;
- (id)dequeueReusableCellWithReuseIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath*)indexPath;
- (id)dequeueReusableSupplementaryViewOfKind:(NSString*)elementKind withReuseIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath*)indexPath;
@end
OK, bây giờ chúng ta có thể triển khai các UICollectionView
phương thức chính trong UICollectionView.m
và chúng ta có thể triển khai các phương thức quản lý các khung nhìn có thể sử dụng lại trong UICollectionView+ReusableViews.m
đó, điều này làm cho mã nguồn của chúng ta dễ quản lý hơn một chút.
Nhưng mã quản lý chế độ xem có thể tái sử dụng của chúng tôi cần một số biến phiên bản. Những biến phải được tiếp xúc với những lớp học chính @implementation
trong UICollectionView.m
, do đó trình biên dịch sẽ phát ra chúng trong .o
tập tin. Và chúng ta cũng cần hiển thị các biến cá thể đó với mã trong UICollectionView+ReusableViews.m
, để các phương thức đó có thể sử dụng ivars.
Đây là nơi chúng ta cần một phần mở rộng lớp. Chúng tôi có thể đặt các ivars quản lý chế độ xem có thể tái sử dụng trong phần mở rộng lớp trong tệp tiêu đề riêng tư:
@interface UICollectionView () {
NSMutableDictionary *registeredCellSources;
NSMutableDictionary *spareCellsByIdentifier;
NSMutableDictionary *registeredSupplementaryViewSources;
NSMutableDictionary *spareSupplementaryViewsByIdentifier;
}
- (void)initReusableViewSupport;
@end
Chúng tôi sẽ không gửi tệp tiêu đề này cho người dùng thư viện của chúng tôi. Chúng tôi sẽ chỉ nhập nó vào UICollectionView.m
và vào UICollectionView+ReusableViews.m
để mọi thứ cần xem các ivars này đều có thể nhìn thấy chúng. Chúng tôi cũng đã đưa vào một phương thức mà chúng tôi muốn init
phương thức chính gọi để khởi tạo mã quản lý chế độ xem có thể tái sử dụng. Chúng tôi sẽ gọi phương thức đó từ -[UICollectionView initWithFrame:collectionViewLayout:]
trong UICollectionView.m
và chúng tôi sẽ triển khai nó trong UICollectionView+ReusableViews.m
.