Objc-shorthand is a project mainly written in RUBY and SHELL, based on the MIT license.
A Ruby DSL for writing boilerplate Objective-C concisely.
This tiny library allows boilerplate Objective-C code (in particular, property synthesis and memory management code) to be produced from a very compact Ruby DSL-ish representation of the class.
For example:
#!/usr/bin/env ruby
require 'objc_shorthand'
objc_class :PersonController do
framework 'AppKit'
import 'PersonControllerDelegate.h'
name
surname
marriedTo :Person, :will_set
displayLabel :NSTextField, :outlet
delegate 'id <PersonControllerDelegate>'
end
describes a class whose generated header, once expanded from shorthand, is:
// ----------------------------
// AUTOGENERATED FROM:
// /Users/millenomi/BLAHBLAH/Shorthand/x.m.rb
// ----------------------------
#import <AppKit/AppKit.h>
#import "PersonControllerDelegate.h"
@interface PersonController : NSObject
@property(assign,nonatomic) id <PersonControllerDelegate> delegate;
@property(retain,nonatomic) id surname;
@property(retain,nonatomic) Person* marriedTo;
- (void) marriedToWillChangeToValue:(Person*) aNewValue fromValue:(Person*) anOldValue;
@property(retain,nonatomic) IBOutlet NSTextField* displayLabel;
@property(retain,nonatomic) id name;
@end
and a corresponding implementation file. marriedToWillChangeToValue:fromValue:
will be called as part of the setter of marriedTo
, as you might imagine, and note how delegate
is declared assign
by convention. Files generated by expanding shorthand scripts are meant to be used with the generation gap organizational strategy, and provide override points for your actual subclass (like the willChange… method above).
A more complete example is found in the examples
directory.
To expand shorthand, just run the objc_generate_from_shorthand.rb
script passing your shorthand script as argument, ie.
$ ruby -I. objc_generate_from_shorthand.rb my_class.m.rb
A shorthand file may contain multiple classes; expanding will produce dedicated .h
s and .m
s for each.
This library the most recent version of the mustache
gem.
objc_class(name) do …
name
: (anything responding to to_s
)ObjCClass
instanceProduces a new Objective-C class definition. You must pass a block, which will execute within the context of a ObjCClass
instance.
ObjCClass.framework(name)
, ObjCClass.import(name)
These methods add an import statement at the top of the class's file. If you specify no framework imports, Foundation
will be imported by default.
You need only specify the framework's name, without repeating; ie.
framework 'Cocoa'
ObjCClass.subclass_of(name)
Sets the superclass of this class. If not used, the class will inherit from NSObject
. For example:
subclass_of :UIViewController
You might need to use framework
or import
to make sure the superclass's interface is imported.
ObjCClass.ivar(name, type = nil, *options)
name
: (anything responding to to_s
)type
: (a String
or Symbol
)options
: (an array of Symbol
s or special objects; see below)Creates a new instance variable and property pair for this class with the specified arguments. Note that ObjCClass
implements method_missing
so that:
ivar :name, :NSString, :copy
can be shortened to
name :NSString, :copy
whenever the ivar name does not conflict with another ObjCClass
method.
The name
you give is the name of the property, whereas the name of the backing instance variable will be name
followed by an underscore (eg name_
). Ivars generated this way are @protected
.
The type can be a symbol, in which case it's generally regarded to as a method name, or a string, which will be used verbatim. Special symbols you can pass are:
:int
: short for "NSInteger"
:uint
: short for "NSUInteger"
:str
: short for :NSString
:bool
: short for "BOOL"
:id
and :Class
The type passed in will be considered an object type if you used a symbol (other than those above) or if you used "id"
or "id<…>"
as the string (with any amount of spacing). You can force types to be used as object types (useful for eg. block types); see below.
The rest of the parameters form the options for the ivar. The generator understands the following options:
:retain
, :copy
, :assign
: Force a particular memory management mode for a property. If none is specified, the expander will try to infer a mode (eg. non-object types will get assign; properties named delegate
or …Delegate
will get assign etc.).
:ro
will cause the property to be created readonly
.
:object
: Require the type to be treated as an ObjC object type. This may be useful if you're dealing with Core Foundation or typedef'd block types.
:atomic
: Marks a property as atomic. By default, all properties are generated nonatomic. You can't mix this and :will_set
, :did_set
or anything else that requires generating an explicit accessor.
:will_set
, :did_set
: Generate override points before and after a property's ivar is assigned in the setter. This will generate an explicit setter accessor implementation (not @synthesize
).
:will_get
: Generate override point before the property accessor will return the property's value. This will generate an explicit getter accessor implementation (not @synthesize
).
getter(name)
: Indicates that you want the getter to have a different name. Note that this is a function call, not a symbol. Eg:
clean :bool, :did_set, getter(:isClean)