A functional `.m` file that contains all the features that are available in MulleObjC.
Edit me

Good Code

Objective-C is a fairly simple language extension. In this file all available Objective-C keywords and concepts will be discussed. Absent will be library features introduced by the Foundation, because this blows the scope of this treatise.

The code will be regular Objective-C, unless specifically noted to be an Objective-C extension.

Forward Declaration and Import

You can #import and forward declare code:

#import <Foundation/Foundation.h>

// forward declarations of a class and a protocol
@protocol SomeProtocol;
@class Foreign;


You can declare a protocol with @optional and @required methods and properties:

// declare a protocol with a required (default)
// and an optional method
@protocol MethodProtocol

- (Foreign *) someMethod;

- (Foreign *) otherMethod;

// properties can be declared in protocols, yet the
// class must redeclare them

@property( assign) NSUInteger  value;


You can extend forward declared classes with your protocol, but this is rarely useful:

// extend Foreign class with this method, so
// we know we can message it with that protocol
@class Foreign< MethodProtocol>;


#pragma clang diagnostic ignored "-Wobjc-root-class"
@interface Foo : NSObject < MethodProtocol>
@public        // The usual visibility modifiers except `@package`
   NSUInteger   _value;    // will be used as property "value" ivar

// properties and all supported property attributes
@property( readwrite, assign) NSUInteger  value;      // reimplement Protocol
@property( nonatomic, retain) Foreign     *foreign;   // creates own ivar
@property( readonly, nonnull) NSString    *backedByIvar; // creates own ivar


The implementation can @synthesize a property but it is superflous. The name of the instance variable is fixed by the compiler to be '_'<name>. Foo implements the required method from MethodProtocol.

@implementation Foo

@synthesize foreign = _foreign;

- (Foreign *) someMethod;
   return( _foreign);


@defs is available and great for writing fast accessors, when you don’t want your instance variables to be @public:

static inline Foreign  *FooGetForeign( Foo *self)
   return( ((struct{ @defs( Foo); } *) self)->_foreign);


@compatibility_alias will work as expected.

// use Foo under alias Foobar
@compatibility_alias Foobar Foo;


You can declare protocolclasses. This is a MulleObjC extension to the Objective-C language. This will not work with other runtimes (though it will compile):

// protocolclass Description with default implementation of -description
@class Description;
@protocol Description
- (NSString *) description;

// properties can not be declared in protocolclases yet
// @property( assign) NSUInteger  value;
#pragma clang diagnostic ignored "-Wobjc-root-class"

// protocolclass must implement Protocol of same name
@interface Description< Description>

// implementation will serve the default implementation of description
@implementation Description

- (NSString *) description
   return( @"VfL Bochum 1848");

Your classes can now inherit the description protocol, but it doesn’t have to implement -description. It can override it though if desired:

@interface Bar : Foo < Description>

@implementation Bar

// call super on protocolclass (not superclass)
- (NSString *) description
   return( [super description]);  // unvoidable warning for now



PROTOCOL is a compiler keyword. Objective-C’s Protocol * does not work, as PROTOCOL is a kind of @selector in MulleObjC:

- (BOOL) knowsThisProtocol:(PROTOCOL) proto
   return( @protocol( Description) == proto);


instancetype behaves normally:

// instancetype keyword
- (instancetype) init
   return( self);


@encode behaves normally and is 90% compatible with the Apple runtime:

// @encode keyword
+ (char *) type
   return( @encode( Bar));


You can use @autoreleasepool:

// keyword autoreleasepool
- (void) autoreleasepool

@try …

Exception handling can be done with @try,@catch,@finally:

- (void) trycatchfinally
   @catch( NSException *e)



// exception handling with nsduring
- (void) nsduring
   [localException raise];

inout …

These @encode adornments should still work and should be properly encoded and decoded, but noone uses them:

  • in
  • out
  • inout
  • bycopy
  • byref
  • oneway



Literals are supported except @YES and @NO, but boxed versions of those are fine.


- (NSNumber *) literalInteger
   return( @1848);

- (NSNumber *) literalDouble
   return( @18.48);

- (NSNumber *) literalCharacter
   return( @'A');

- (NSNumber *) literalBOOL
   return( @(YES));

@{} and @[]

- (NSDictionary *) literalDictionary
   return( @{ @"VfL Bochum" : @1848 });

- (NSArray *) literalArray
   return( @[ @1848, @"VfL Bochum" ]);


- (PROTOCOL) literalProtocol
   return( @protocol( Description));


- (SEL) literalSelector
   return( @selector( whatever:));

Fast Enumeration

Fast Enumeration is supported:

// fast enumeration
- (void) fastEnumerate:(NSArray *) array
   for( id p in array)


Checked against the list of NSHipster’s compiler directive

Putting all the pieces together

Run the main function, to verify the truth of what’s been written (good-code.m).

int main()
   Bar   *bar;

   // don't need an enclosing @autoreleasepool in MulleObjC

   bar = [Bar new];

   [bar fastEnumerate:[NSArray arrayWithObject:@"foo"]];

   NSLog( @"description: %@", [bar description]);
   NSLog( @"literalInteger: %@", [bar literalInteger]);
   NSLog( @"literalDouble: %@", [bar literalDouble]);
   NSLog( @"literalCharacter: %@", [bar literalCharacter]);
   NSLog( @"literalArray: %@", [bar literalArray]);
   NSLog( @"literalDictionary: %@", [bar literalDictionary]);

// NSStringFromProtocol is a 8.0.0 feature
#if MULLE_FOUNDATION_VERSION  >= ((0 << 20) | (15 << 8) | 0)
   NSLog( @"literalProtocol: %@", NSStringFromProtocol( [bar literalProtocol]));
   NSLog( @"literalSelector: %@", NSStringFromSelector( [bar literalSelector]));

   return( 0);

Expected output

description: VfL Bochum 1848
literalInteger: 1848
literalDouble: 18.480000
literalCharacter: 65
literalArray: (
    VfL Bochum
literalDictionary: {
    VfL Bochum = 1848;
literalSelector: <invalid selector>


The followup to “good code” is of course bad code

Tags: language