Câu trả lời:
các thuộc tính có một ý nghĩa cụ thể trong Objective-C, nhưng tôi nghĩ bạn có ý nghĩa gì đó tương đương với một biến tĩnh? Ví dụ: chỉ có một ví dụ cho tất cả các loại Foo?
Để khai báo các hàm lớp trong Objective-C, bạn sử dụng tiền tố + thay vì - vì vậy việc triển khai của bạn sẽ trông giống như:
// Foo.h
@interface Foo {
}
+ (NSDictionary *)dictionary;
// Foo.m
+ (NSDictionary *)dictionary {
static NSDictionary *fooDict = nil;
if (fooDict == nil) {
// create dict
}
return fooDict;
}
.
cú pháp -accessor không gắn với tài sản trong Objective-C, nó chỉ là một biên soạn trong phím tắt cho bất kỳ phương pháp mà lợi nhuận một cái gì đó mà không cần dùng bất kỳ args. Trong trường hợp này, tôi thích nó hơn. Cá nhân tôi thích .
cú pháp cho bất kỳ việc sử dụng nào trong đó mã máy khách dự định nhận một cái gì đó, không thực hiện một hành động (ngay cả khi mã thực thi có thể tạo ra một cái gì đó một lần hoặc thực hiện các hành động tác dụng phụ) . .
Cú pháp sử dụng nhiều cũng dẫn đến mã dễ đọc hơn: sự hiện diện của […]
s có nghĩa là một cái gì đó quan trọng đang được thực hiện khi tìm nạp sử dụng .
cú pháp thay thế.
Tôi đang sử dụng giải pháp này:
@interface Model
+ (int) value;
+ (void) setValue:(int)val;
@end
@implementation Model
static int value;
+ (int) value
{ @synchronized(self) { return value; } }
+ (void) setValue:(int)val
{ @synchronized(self) { value = val; } }
@end
Và tôi thấy nó cực kỳ hữu ích khi thay thế mẫu Singleton.
Để sử dụng nó, chỉ cần truy cập dữ liệu của bạn bằng ký hiệu dấu chấm:
Model.value = 1;
NSLog(@"%d = value", Model.value);
self
nghĩa là bên trong một phương thức lớp?
self
là đối tượng nhận được tin nhắn . Và vì các lớp cũng là đối tượng , trong trường hợp này self
có nghĩa làModel
@synchronized
?
Như đã thấy trong WWDC 2016 / XCode 8 (có gì mới trong phiên LLVM @ 5: 05). Các thuộc tính lớp có thể được khai báo như sau
@interface MyType : NSObject
@property (class) NSString *someString;
@end
NSLog(@"format string %@", MyType.someString);
Lưu ý rằng các thuộc tính lớp không bao giờ được tổng hợp
@implementation
static NSString * _someString;
+ (NSString *)someString { return _someString; }
+ (void)setSomeString:(NSString *)newString { _someString = newString; }
@end
static
biến ( ) vẫn phải được khai báo và sử dụng và các phương thức được triển khai rõ ràng, giống như trước đây. Cú pháp chấm đã làm việc trước đây, quá. Trong tất cả, điều này nghe có vẻ như một thỏa thuận lớn hơn thực tế.
Nếu bạn đang tìm kiếm tương đương cấp lớp @property
, thì câu trả lời là "không có điều đó". Nhưng hãy nhớ,@property
, dù sao cũng chỉ là cú pháp; nó chỉ tạo ra các phương thức đối tượng được đặt tên thích hợp.
Bạn muốn tạo các phương thức lớp truy cập các biến tĩnh, như những người khác đã nói, chỉ có một cú pháp hơi khác nhau.
UIDevice.currentDevice.identifierForVendor
làm việc cho tôi
Đây là một cách an toàn để làm điều đó:
// Foo.h
@interface Foo {
}
+(NSDictionary*) dictionary;
// Foo.m
+(NSDictionary*) dictionary
{
static NSDictionary* fooDict = nil;
static dispatch_once_t oncePredicate;
dispatch_once(&oncePredicate, ^{
// create dict
});
return fooDict;
}
Những chỉnh sửa này đảm bảo rằng fooDict chỉ được tạo một lần.
Từ tài liệu của Apple : "Clark_once - Thực thi một đối tượng khối một lần và chỉ một lần trong suốt vòng đời của một ứng dụng."
Initializer element is not a compile-time constant
.
Kể từ Xcode 8 Objective-C hiện hỗ trợ các thuộc tính lớp:
@interface MyClass : NSObject
@property (class, nonatomic, assign, readonly) NSUUID* identifier;
@end
Vì các thuộc tính lớp không bao giờ được tổng hợp, bạn cần phải viết triển khai của riêng bạn.
@implementation MyClass
static NSUUID*_identifier = nil;
+ (NSUUID *)identifier {
if (_identifier == nil) {
_identifier = [[NSUUID alloc] init];
}
return _identifier;
}
@end
Bạn truy cập các thuộc tính lớp bằng cú pháp dấu chấm bình thường trên tên lớp:
MyClass.identifier;
Các thuộc tính chỉ có giá trị trong các đối tượng, không phải các lớp.
Nếu bạn cần lưu trữ một cái gì đó cho tất cả các đối tượng của một lớp, bạn phải sử dụng một biến toàn cục. Bạn có thể ẩn nó bằng cách khai báo nó static
trong tệp thực hiện.
Bạn cũng có thể xem xét sử dụng các mối quan hệ cụ thể giữa các đối tượng của mình: bạn gán một vai trò chủ cho một đối tượng cụ thể của lớp và liên kết các đối tượng khác với chủ này. Các chủ sẽ giữ từ điển như một tài sản đơn giản. Tôi nghĩ về một cái cây giống như cái cây được sử dụng cho hệ thống phân cấp khung nhìn trong các ứng dụng Cacao.
Một tùy chọn khác là tạo một đối tượng của một lớp chuyên dụng bao gồm cả từ điển 'lớp' của bạn và một tập hợp tất cả các đối tượng liên quan đến từ điển này. Đây là một cái gì đó giống như NSAutoreleasePool
trong ca cao.
Bắt đầu từ Xcode 8, bạn có thể sử dụng thuộc tính thuộc tính lớp như được trả lời bởi Berbie.
Tuy nhiên, trong quá trình triển khai, bạn cần định nghĩa cả lớp getter và setter cho thuộc tính lớp bằng cách sử dụng biến tĩnh thay cho iVar.
Mẫu.h
@interface Sample: NSObject
@property (class, retain) Sample *sharedSample;
@end
Mẫu.m
@implementation Sample
static Sample *_sharedSample;
+ ( Sample *)sharedSample {
if (_sharedSample==nil) {
[Sample setSharedSample:_sharedSample];
}
return _sharedSample;
}
+ (void)setSharedSample:(Sample *)sample {
_sharedSample = [[Sample alloc]init];
}
@end
Nếu bạn có nhiều thuộc tính cấp lớp thì một mẫu đơn có thể theo thứ tự. Một cái gì đó như thế này:
// Foo.h
@interface Foo
+ (Foo *)singleton;
@property 1 ...
@property 2 ...
@property 3 ...
@end
Và
// Foo.m
#import "Foo.h"
@implementation Foo
static Foo *_singleton = nil;
+ (Foo *)singleton {
if (_singleton == nil) _singleton = [[Foo alloc] init];
return _singleton;
}
@synthesize property1;
@synthesize property2;
@synthesise property3;
@end
Bây giờ truy cập các thuộc tính cấp lớp của bạn như thế này:
[Foo singleton].property1 = value;
value = [Foo singleton].property2;
dispatch_once
ở đây.
[Thử giải pháp này thật đơn giản] Bạn có thể tạo một biến tĩnh trong lớp Swift sau đó gọi nó từ bất kỳ lớp Objective-C nào.