Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Attribute-oriented programming in Objective-C

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest. →

Attribute-oriented programming in Objective-C

Describes problems that can be resolved with @op and ways how you can implement it in obj-c
https://github.com/epam/lib-obj-c-attr

Avatar for Yuri Tolstoguzov

Yuri Tolstoguzov

June 29, 2014

Other Decks in Programming

Transcript

  1. Problems • Technical code is tangled with business code •

    Scattered code • No context for code
  2. ROAnnotation //@classAnnotationInHeader( source = simpleValue, output = "value with spaces")

    //@testAnnotate @interface Person : NSObject { NSString *name; } ! //@PropertyAnnotationInHeader(key1=value1) //@CustomizedAnnotation(attribute1 = 123, attribute2 = 456, attribute3 = 759) @property (nonatomic, retain) NSString *name; //@PropertyAnnotationInHeader(attributeHavingOnlyValue) @property (nonatomic, retain) NSString *testProperty; ! //@MethodAnotationInHeader(a=589) - (void) canDoSomethingAwesomeWith:(NSString *)aName 
 andAThing:(id)thing; - (void) reallyLongMethodName:(CGPoint)withWrappedParameters 
 andAnother:(NSString *)one; ! @end
  3. ROAnnotation //@classAnnotationInHeader( source = simpleValue, output = "value with spaces")

    //@testAnnotate @interface Person : NSObject { NSString *name; } ! //@PropertyAnnotationInHeader(key1=value1) //@CustomizedAnnotation(attribute1 = 123, attribute2 = 456, attribute3 = 759) @property (nonatomic, retain) NSString *name; //@PropertyAnnotationInHeader(attributeHavingOnlyValue) @property (nonatomic, retain) NSString *testProperty; ! //@MethodAnotationInHeader(a=589) - (void) canDoSomethingAwesomeWith:(NSString *)aName 
 andAThing:(id)thing; - (void) reallyLongMethodName:(CGPoint)withWrappedParameters 
 andAnother:(NSString *)one; ! @end
  4. ROAnnotation //@classAnnotationInHeader( source = simpleValue, output = "value with spaces")

    //@testAnnotate @interface Person : NSObject { NSString *name; } ! //@PropertyAnnotationInHeader(key1=value1) //@CustomizedAnnotation(attribute1 = 123, attribute2 = 456, attribute3 = 759) @property (nonatomic, retain) NSString *name; //@PropertyAnnotationInHeader(attributeHavingOnlyValue) @property (nonatomic, retain) NSString *testProperty; ! //@MethodAnotationInHeader(a=589) - (void) canDoSomethingAwesomeWith:(NSString *)aName 
 andAThing:(id)thing; - (void) reallyLongMethodName:(CGPoint)withWrappedParameters 
 andAnother:(NSString *)one; ! @end
  5. libExtObjC @annotateClass(AnnotatedClass, @"version": @"1.1") @interface AnnotatedClass : NSObject ! @annotate(AnnotatedClass,

    @"APIKey": @"full_name", @"other_info": @5) @property (nonatomic, copy) NSString *name; ! @end
  6. libExtObjC @annotateClass(AnnotatedClass, @"version": @"1.1") @interface AnnotatedClass : NSObject ! @annotate(AnnotatedClass,

    @"APIKey": @"full_name", @"other_info": @5) @property (nonatomic, copy) NSString *name; ! @end
  7. libExtObjC @annotateClass(AnnotatedClass, @"version": @"1.1") @interface AnnotatedClass : NSObject ! @annotate(AnnotatedClass,

    @"APIKey": @"full_name", @"other_info": @5) @property (nonatomic, copy) NSString *name; ! @end
  8. libExtObjC @annotateClass(AnnotatedClass, @"version": @"1.1") @interface AnnotatedClass : NSObject ! @annotate(AnnotatedClass,

    @"APIKey": @"full_name", @"other_info": @5) @property (nonatomic, copy) NSString *name; ! @end
  9. libObjCAttr RF_ATTRIBUTE(MyAttribute, stringProperty = @"Hello world") @interface AnnotatedClass : NSObject

    { ! RF_ATTRIBUTE(MyAttribute, numericProperty = @9000) NSObject * _someField; } ! RF_ATTRIBUTE(MyAttribute, blockProperty = ^(int value) { return value; }) - (void)foo; ! RF_ATTRIBUTE(MyAttribute, objectProperty = [NSObject new]) @property NSString *name; ! @end
  10. libObjCAttr RF_ATTRIBUTE(MyAttribute, stringProperty = @"Hello world") @interface AnnotatedClass : NSObject

    { ! RF_ATTRIBUTE(MyAttribute, numericProperty = @9000) NSObject * _someField; } ! RF_ATTRIBUTE(MyAttribute, blockProperty = ^(int value) { return value; }) - (void)foo; ! RF_ATTRIBUTE(MyAttribute, objectProperty = [NSObject new]) @property NSString *name; ! @end
  11. libObjCAttr RF_ATTRIBUTE(MyAttribute, stringProperty = @"Hello world") @interface AnnotatedClass : NSObject

    { ! RF_ATTRIBUTE(MyAttribute, numericProperty = @9000) NSObject * _someField; } ! RF_ATTRIBUTE(MyAttribute, blockProperty = ^(int value) { return value; }) - (void)foo; ! RF_ATTRIBUTE(MyAttribute, objectProperty = [NSObject new]) @property NSString *name; ! @end
  12. libObjCAttr RF_ATTRIBUTE(MyAttribute, stringProperty = @"Hello world") @interface AnnotatedClass : NSObject

    { ! RF_ATTRIBUTE(MyAttribute, numericProperty = @9000) NSObject * _someField; } ! RF_ATTRIBUTE(MyAttribute, blockProperty = ^(int value) { return value; }) - (void)foo; ! RF_ATTRIBUTE(MyAttribute, objectProperty = [NSObject new]) @property NSString *name; ! @end
  13. libObjCAttr RF_ATTRIBUTE(MyAttribute, stringProperty = @"Hello world") @interface AnnotatedClass : NSObject

    { ! RF_ATTRIBUTE(MyAttribute, numericProperty = @9000) NSObject * _someField; } ! RF_ATTRIBUTE(MyAttribute, blockProperty = ^(int value) { return value; }) - (void)foo; ! RF_ATTRIBUTE(MyAttribute, objectProperty = [NSObject new]) @property NSString *name; ! @end
  14. Comparison ROAnnotation libExtObjC libObjCAttr Supports OS X and iOS +

    + + Class attributes + + + Property attributes + + + Method attributes + – + IVar attributes – – + Supports object values – + + Support primitive types – – + Error tracing – – + Cocoapods installation – – + Syntax highlighting – + + Autocompletion – + + Perfomance leader – – + Total 4 6 12
  15. Use case - Serialization ! @interface Person : NSObject !

    @property (nonatomic, copy) NSString *personId; @property (nonatomic, copy) NSString *firstName; @property (nonatomic, copy) NSString *lastName; @property (nonatomic, readonly) NSString *name; @property (nonatomic, strong) NSDate *birthday; @property (nonatomic, strong) Person *spouse; @property (nonatomic, strong) NSArray *children; ! @end
  16. Use case - Serialization RF_ATTRIBUTE(RFSerializable) @interface Person : NSObject !

    @property (nonatomic, copy) NSString *personId; @property (nonatomic, copy) NSString *firstName; @property (nonatomic, copy) NSString *lastName; @property (nonatomic, readonly) NSString *name; @property (nonatomic, strong) NSDate *birthday; @property (nonatomic, strong) Person *spouse; @property (nonatomic, strong) NSArray *children; ! @end
  17. Use case - Serialization RF_ATTRIBUTE(RFSerializable) @interface Person : NSObject !

    RF_ATTRIBUTE(RFSerializable, serializationKey = @"id") @property (nonatomic, copy) NSString *personId; RF_ATTRIBUTE(RFSerializable, serializationKey = @"first_name") @property (nonatomic, copy) NSString *firstName; RF_ATTRIBUTE(RFSerializable, serializationKey = @"last_name") @property (nonatomic, copy) NSString *lastName; @property (nonatomic, readonly) NSString *name; RF_ATTRIBUTE(RFSerializable, serializationKey = @"birthday") @property (nonatomic, strong) NSDate *birthday; RF_ATTRIBUTE(RFSerializable, serializationKey = @"spouse") @property (nonatomic, strong) Person *spouse; RF_ATTRIBUTE(RFSerializable, serializationKey = @"children") @property (nonatomic, strong) NSArray *children; ! @end
  18. Use case - Serialization RF_ATTRIBUTE(RFSerializable) @interface Person : NSObject !

    RF_ATTRIBUTE(RFSerializable, serializationKey = @"id") @property (nonatomic, copy) NSString *personId; RF_ATTRIBUTE(RFSerializable, serializationKey = @"first_name") @property (nonatomic, copy) NSString *firstName; RF_ATTRIBUTE(RFSerializable, serializationKey = @"last_name") @property (nonatomic, copy) NSString *lastName; RF_ATTRIBUTE(RFDerived) @property (nonatomic, readonly) NSString *name; RF_ATTRIBUTE(RFSerializable, serializationKey = @"birthday") @property (nonatomic, strong) NSDate *birthday; RF_ATTRIBUTE(RFSerializable, serializationKey = @"spouse") @property (nonatomic, strong) Person *spouse; RF_ATTRIBUTE(RFSerializable, serializationKey = @"children") @property (nonatomic, strong) NSArray *children; ! @end
  19. Use case - Serialization RF_ATTRIBUTE(RFSerializable) @interface Person : NSObject !

    RF_ATTRIBUTE(RFSerializable, serializationKey = @"id") @property (nonatomic, copy) NSString *personId; RF_ATTRIBUTE(RFSerializable, serializationKey = @"first_name") @property (nonatomic, copy) NSString *firstName; RF_ATTRIBUTE(RFSerializable, serializationKey = @"last_name") @property (nonatomic, copy) NSString *lastName; RF_ATTRIBUTE(RFDerived) @property (nonatomic, readonly) NSString *name; RF_ATTRIBUTE(RFSerializable, serializationKey = @"birthday") RF_ATTRIBUTE(RFSerializableDate, format = @"yyyy-MM-dd'T'HH:mm:ss'Z'") @property (nonatomic, strong) NSDate *birthday; RF_ATTRIBUTE(RFSerializable, serializationKey = @"spouse") @property (nonatomic, strong) Person *spouse; RF_ATTRIBUTE(RFSerializable, serializationKey = @"children") @property (nonatomic, strong) NSArray *children; ! @end
  20. Use case - Serialization RF_ATTRIBUTE(RFSerializable) @interface Person : NSObject !

    RF_ATTRIBUTE(RFSerializable, serializationKey = @"id") @property (nonatomic, copy) NSString *personId; RF_ATTRIBUTE(RFSerializable, serializationKey = @"first_name") @property (nonatomic, copy) NSString *firstName; RF_ATTRIBUTE(RFSerializable, serializationKey = @"last_name") @property (nonatomic, copy) NSString *lastName; RF_ATTRIBUTE(RFDerived) @property (nonatomic, readonly) NSString *name; RF_ATTRIBUTE(RFSerializable, serializationKey = @"birthday") RF_ATTRIBUTE(RFSerializableDate, format = @"yyyy-MM-dd'T'HH:mm:ss'Z'") @property (nonatomic, strong) NSDate *birthday; RF_ATTRIBUTE(RFSerializable, serializationKey = @"spouse") @property (nonatomic, strong) Person *spouse; RF_ATTRIBUTE(RFSerializable, serializationKey = @"children") RF_ATTRIBUTE(RFSerializableCollection, collectionClass = [Person class]) @property (nonatomic, strong) NSArray *children; ! @end
  21. Use cases Dependency injection Aspect-oriented programming Validation Logic configuration Web

    service mapping Serialization mapping Mocking Logging Documenting Service locating Carrying meta data Entity mapping Form generation