WSCoreLaziness
From time to time I often find myself repeating certain small amounts of code which consists of a few lines. In the beginning it was ok, since I didn’t mind it because of my lack of experience in Cocoa coding. Afterwards it got really annoying. Coming from Ruby (and Rails) background I remembered how awesome it was to have ActiveSupport around. It had so many helpful classes and functions that would improve developers’ productivity and clear up the code!
WSCoreLaziness is a shot at making ActiveSupport for Cocoa frameworks. The idea is simple - create a collection of (as of this writing) Foundation framework categories that aim to shorten the amount of your typing and increase the amount of hitting Esc and Tab keys, provide familiar API and sensible defaults.
The framework is being developed using TDD using standard SenTestingKit.framework that comes together with Xcode.
Installation
Installation process is pretty much the same as for any other framework out there (Sparkle, Growl anyone?) except it does not require any framework specific tweaks. Here’s how I do it:
- Copy the WSCoreLaziness.framework bundle to
$(SRCROOT)/Frameworks. - Add the bundle (or whole
Frameworksdirectory) to Xcode project (⌘+⌥+A, drag’n’drop or right-click and “Add files to project…”). - Add “Copy files” build phase right before the “Link Binary With Libraries” phase. Make sure framework is added there as well as operation’s destination is set to Frameworks.
- Link your project with WSCoreLaziness.framework by adding it to “Link Binary With Libraries” phase.
- Add the import statement to your
Prefix.pchfile:#import "WSCoreLaziness/WSCoreLaziness.h".
General convention
Since the classes I write categories for are not owned, every method is prefixed with ws_. It’s recommended practice. Although it makes code look a bit uglier, but it’s better to be safe than sorry.
What’s covered
There are very few methods currently. Since the documentation is yet to be written, here are the classes with their respective methods:
- NSString
- (BOOL)ws_stringIsEmpty- returns YES if string is equal to@"". Otherwise returns no;- (BOOL)ws_stringIsBlank- returns YES if string empty or it contains only whitespace characters (" ",\nand\t);
- NSArray
- (void)ws_enumerateObjectsWithIndexesUsingBlock:(void (^)(id, NSInteger))block;- iterates through array with passed in block which receives object and it’s index.- (id)ws_selectObjectUsingBlock:(BOOL (^)(id))block;- returns object that makes passed in block returnYES;- (NSInteger)ws_integerValueAtIndex:(NSInteger)integer;- returnsNSIntegervalue for an object at index. Useful for arrays consisting ofNSNumbers. Returns0if object does not respond tointegerValue;- (CGFloat)ws_floatValueAtIndex:(NSInteger)integer;- returnsCGFloatvalue for an object at index. Useful for arrays consisting ofNSNumbers. Returns0.0fif object does not respond tofloatValue;- (NSString *)ws_stringValueAtIndex:(NSInteger)integer;- returnsstringValuefor an object at index. Useful for arrays consisting ofNSNumbers and other objects. If object does not respond tostringValue,descriptionmethod is being called;
- NSMutableArray
- (void)ws_mapEachObjectUsingBlock:(id (^)(id))block- replaces each object of array by an object returned from the block;
- NSDictionary
- (NSArray *)ws_sortedKeysUsingDescriptors:(NSArray *)sortDescriptors;- returns array of sorted keys using passed in descriptors;- (NSArray *)ws_sortedValuesUsingDescriptors:(NSArray *)sortDescriptors;- returns array of sorted values using passed in descriptors;- (NSInteger)ws_integerValueForKey:(NSString *)key;- returnsNSIntegerfor given key. Useful for dictionaries having keys withNSNumbervalues. Returns0if object does not respond tointegerValue;- (CGFloat)ws_floatValueForKey:(NSString *)key;- returnsCGFloatfor given key. Useful for dictionaries having keys withNSNumbervalues. Returns0.0fif object does not respond tofloatValue.- (NSString *)ws_stringValueForKey:(NSString *)key;- returnsstringValuefor given key. Useful for dictionaries withNSNumbers and other type values. If object does not respond tostringValue,descriptionis being called instead.
- NSMutableDictionary
- (void)ws_updateValueForKey:(NSString *)key usingBlock:(id (^)(id, NSString *))block;- modifies value at given key by using returned object from provided block which accepts existing value;- (id)ws_extractValueForKey:(NSString *)key;- returns and removes object at given key;
Framework’s file structure
Each framework should have it’s own directory. In directory of a framework, files named NSClass+WSCoreLaziness.h and NSClass+WSCoreLaziness.m should reside showing that NSClass has a category from WSCoreLaziness. Since it’s very fresh and has less than 20 methods it has only categories for most generic Cocoa classes like NSString, NSArray, NSDictionary and their mutable children. Same goes for tests covering the aforementioned categories. Here’s the outline of a framework having foundation classes extended with categories:
- /WSCoreLaziness
- /Foundation
- /NSString+WSCoreLaziness.h
- /NSString+WSCoreLaziness.m
- /NSArray+WSCoreLaziness.h
- /NSArray+WSCoreLaziness.m
- …
- /Foundation
- /WSCoreLazinessTest
- /Foundation
- /NSStringWSCoreLazinessTest.h
- /NSStringWSCoreLazinessTest.m
- /NSArrayWSCoreLazinessTest.h
- /NSArrayWSCoreLazinessTest.m
- …
- /Foundation
Resources
Here are some links related to this project:
- Blog post - sort of an announcement.
- GitHub repository - where the code & documentation lays.
- Site’s twitter - general twitter account for this site.
- Personal twitter - my personal twitter account.