Dustin Bachrach

mobile engineer / developer platform enthusiast / dog lover

AtSugar: Sugar for Your @

We just released a small Header-Only library called AtSugar. AtSugar provides a few macros for Objective-C that make writing things easier and more declarative. The intention is to continue expanding this to form a great collection of helper utilities.

All macros in AtSugar hook into the @ sign, so they feel like Objective-C extensions. This is just a compiler trick. It’s not hooking into the runtime or doing anything funky. Before using AtSugar, I suggest taking a look at the individual header files to see how they work.

Let’s take a tour of what AtSugar simplifies.

Weak references

We typically need weak references when we are going to capture references to use later inside a block (to break the retain cycle). Here’s how we would do that with AtSugar:

1
2
3
4
@weakSelf()
[self saveBlock:^{
    [weakSelf go]; // `weakSelf` will be captured weakly
}];

Sometimes we want to weakly capture something besides self:

1
2
3
4
5
6
id obj = /* an object */;

@weakify(obj)
[self saveBlock:^{
    [weak_obj go];
}];

Singletons

However much we like to bash on them, we still use(need) singletons. With the @singleton directive we can declare our singleton intent clearly:

1
2
3
4
5
@interface MyClass : NSObject

+ (instancetype)sharedInstance;

@end
1
2
3
4
5
@implementation MyClass

@singleton(sharedInstance)

@end

Note that AtSugar is only aiding in the implementation. AtSugar is all about making your implementations clearer without changing your interfaces. Consumers of your classes shouldn’t care, or even be aware, of your AtSugar use.

Associated Objects

Associated objects are a great feature of Objective-C that allow us to add properties to categories. But using associated objects is harder than just declaring a property. AtSugar adds an associated_object directive to simplify the process.

1
2
3
4
5
@interface UIImage (MyCategory)

@property (strong, nonatomic) NSString* myProperty;

@end
1
2
3
4
5
6
7
#import <objc/runtime.h>

@implementation UIImage (MyCategory)

@associated_object (myProperty, setMyProperty)

@end

When using associated_object you need to specify the getter and setter. Ideally you could just do:

1
@associated_object (myProperty)

But the C preprocessor does not allow case translation, so we can’t turn myProperty into setMyProperty.

If you need to change the memory management rules for the associated object you can use the various other flavors:

  • associated_object_assign
  • associated_object_copy
  • associated_object_with_association

Declarative Class Properties

In our codebase, lots of our classes have constant properties about them. For example, all of our different models have a specific identifier prefix. All movie IDs begin with mov, and all user IDs begin with usr. So our root model object declares a class method:

1
2
3
4
5
@interface RootModel : NSObject

+ (NSString*)prefix;

@end

Each model subclass then needs to implement this method and return its constant prefix string. To make this very declarative, AtSugar provides declare_class_property:

1
2
3
4
5
@implementation Movie

@declare_class_property (prefix, @"mov")

@end
1
2
3
4
5
@implementation User

@declare_class_property (prefix, @"usr")

@end

Contribute

We’d love to see contributions to AtSugar from the community. Please fork and send us a pull request.