cocoa - How do I create a reusable class-level property construct in Objective-C? -
i'd have class-level properties, , found solution https://stackoverflow.com/a/15811719/157384
@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
and you're able call through property accessors, so:
model.value = 1 model.value // => 1
fantastic!
now, want make chunk of code reusable, in form of macro or meta-programming, takes property name , type. how can write it?
with example above, value
, (int)
(and model
) should dynamic.
update
thanks @rich have this:
// common.h #define class_property_interface(type, method, cmethod) \ + (type) method; \ + (void) set##cmethod:(type)val; \ #define class_property_implementation(type, method, cmethod) \ static type _##method; \ + (type) method \ { @synchronized(self) { return _##method; } } \ + (void) set##cmethod:(type)val \ { @synchronized(self) { _##method = val; } } \ // user.h @interface user : nsobject class_property_interface(user *, me, me) @end // user.m @implementation user class_property_implementation(user *, me, me) @end user.me = currentuser; user.me // => currentuser
one thing left done automatically capitalize method name passed macro, if @ possible.
but it's more succinct boilerplate stands!
the macro way...
note: bit horrible , don't recommend using playing around defining them in macros...
the caveat (aside not being "nice") setter method of form set_xxx:
format.
#define class_interface(cls_name, method, type) @interface cls_name : nsobject \ + (type) method; \ + (void) set_##method:(type)val; \ @end \ #define class_implementation(cls_name, method, type) @implementation cls_name \ static type method; \ + (type) method \ { @synchronized(self) { return method; } } \ + (void) set_##method:(type)val \ { @synchronized(self) { method = val; } } \ @end \
place following in header files:
class_interface(test, value, int)
and in .m
files:
class_implementation(test, value, int)
then use test
class:
[test set_value:4]; int = [test value];
again pretty horrible work...!
edit:
with singletons
as mentioned in comments think use of singleton better, has made me write more horrible code :(
now have (sick bag ready):
#define singleton_interface_start(cls_name) @interface cls_name : nsobject \ +(instancetype) sharedinstance; \ #define singleton_interface_end(cls_name) \ @end \ static inline cls_name * cls_name##global () { return [cls_name sharedinstance]; } #define singleton_implementation(cls_name) @implementation cls_name \ +(instancetype) sharedinstance \ { \ static id instance; \ static dispatch_once_t oncetoken; \ dispatch_once(&oncetoken, ^{ \ instance = [self new]; \ }); \ return instance; \ } \ @end \
in headers:
singleton_interface_start(test) @property (atomic, assign) nsuinteger value; singleton_interface_end(test)
and in .m
:
singleton_implementation(test)
and use (yes more sick can produced):
testglobal().value = 1; int = testglobal().value;
or "nicer" objective-c way:
[test sharedinstance].value = 1; int = [test sharedinstance].value;
you (team america amounts of sick right now) have #define
properties in interface.
note i've left @property
definitions in @interface
atomic
because op seems love using @synchronized
. not needed set atomic
.
and know op wants class "properties" (just saying makes me shiver), there other better options!
Comments
Post a Comment