MOAssertions


Discussion

A replacement for the assertion macros in NSException.h. This replacement has several improvements. First, it takes advantage of the fact that vararg macros are now supported by both available preprocessors for gcc on OS X to remove the need for the MOAssert1, MOAssert2, etc... style of multiple macros. Second, it provides a funnel function that can be used to set a breakpoint that will catch any assertion prior to it being handed off to the current handler which can be very useful for debugging. Third, the MOAssertionHandler class allows the current handler to be set (which NSAssertionHan dler has no public API for). Finally convenience macros for testing certain properties such as isKindOf, conformance to protocol, etc are provided.



Classes

MOAssertionHandler
Handler class for the MOAssertions macros and functions.


Functions

MOHandleAssertionFailure
Funnel function for MOAssertion macros. Good for breakpoints.

MOHandleAssertionFailure

Funnel function for MOAssertion macros. Good for breakpoints.
MOKIT_EXTERN void MOHandleAssertionFailure(
    BOOL raise,
    SEL selector,
    id object,
    const char *functionName,
    const char *fileName,
    unsigned line,
    NSString *format,
    ...);

This is the funnel point for assertion failures. You never call it directly, but it can be useful for setting breakpoints. The implementation uses +[MOAssertionHandler currentHandler] to get the current assertion handler and sends it either -handleFailureInMethod:object:file:lineNumber:description:arguments: if selector is non-NULL or -handleFailureInFunction:file:lineNumber:description:arguments: if selector is NULL.

Parameter Descriptions
raise
If this is YES then the call represents a real assertion. Otherwise it represent a request for simply logging an error message.
selector
If the assertion came from a method, this is the selector of the method (_cmd). If it came from a function this will be NULL.
object
If the assertion came from a method, this is the receiver of the method (self). If it came from a function this will be nil.
functionName
This is the value of the compiler macro __PRETTY_FUNCTION__ in the scope the assertion came from.
fileName
This is the value of the compiler macro __FILE__ in the scope the assertion came from.
line
This is the value of the compiler macro __LINE__ in the scope the assertion came from.
format
An +[NSString stringWithFormat:]-style format string. The remaining arguments are the replacement arguments for any % directives in the format string.

#defines


MOAbstractClassError

Used to indicate an attempt to instantiate an abstract class.
#define MOAbstractClassError( _class_) \
do { \
Class cls = [_class_ class]; \
MOAssert( ( [self class] != cls), @"Error. Attempt to instantiate abstract class %@.", NSStringFromClass( cls)); \
} while( 0)

This macro causes an assertion failure if self is an instance of class. It is used to indicate that someone is trying to instantiate an abstract class. Usually it is called from an override of +allocWithZone: after the override has determined that the class being allocated is abstract. The macro takes one argument:

_class_: The abstract class. Generally this is the class whose implementation is invoking the macro.


MOAssert

Primitive assertion macro.
#define MOAssert( _condition_, _desc_, _args_...) \
do { \
if ( !( _condition_)) { \
MOHandleAssertionFailure( YES, _cmd, self, __PRETTY_FUNCTION__, __FILE__, __LINE__, ( _desc_), ## _args_); \
} \
} while( 0)

It is the primitive assertion macro. All the other assertion macros wind up invoking this macro one or more times. If MO_BLOCK_ASSERTS is defined, this macro does nothing, otherwise if _condition_ is false it calls MOHandleAssertionFailure(). The macro takes a variable number of arguments:

_condition_: The conditional expression being asserted. This can be any expression that is legal within the parens of an if () statement.

_desc_: The description or format string for the assertion. Any additional arguments (_args_) are replacement arguments for % directives in the format string.


MOAssertClass

Assert an object is a kind of class.
#define MOAssertClass( _object_, _class_) \
do { \
Class cls = [_class_ class]; \
id obj = ( _object_); \
MOAssert( ( obj != nil), @"%s should be an object of class %@, but it is nil.", #_object_, NSStringFromClass( cls)); \
MOAssert( ( [obj isKindOfClass:cls]), @"%s should be an object of class %@, but it is of class %@.", #_object_, NSStringFromClass( cls), NSStringFromClass( [obj class])); \
} while( 0)

This macro makes two assertions: first that _object_ is not nil, and second that [_object_ isKindOfClass:_class_]. The macro takes two arguments:

_object_: The _object being tested.

_class_: The class that the object is required to be a kind of.


MOAssertClassOrNil

Assert an object is nil or a kind of class.
#define MOAssertClassOrNil( _object_, _class_) \
do { \
Class cls = [_class_ class]; \
id obj = ( _object_); \
MOAssert( ( obj == nil || [obj isKindOfClass:cls]), @"%s should be an object of class %@, but it is of class %@.", #_object_, NSStringFromClass( cls), NSStringFromClass( [obj class])); \
} while( 0)

This macro asserts that _object_ is either nil or that [_object_ isKindOfClass:_class_]. The macro takes two arguments:

_object_: The _object being tested.

_class_: The class that the object is required to be a kind of.


MOAssertNonEmptyString

Assert an object is a non-empty string.
#define MOAssertNonEmptyString( _object_) \
do { \
Class cls = [NSString class]; \
id obj = ( _object_); \
MOAssert( ( obj != nil), @"%s should be a non-empty NSString, but it is nil.", #_object_); \
MOAssert( ( [obj isKindOfClass:cls]), @"%s should be a non-empty NSString, but it is of class %@.", #_object_, NSStringFromClass( [obj class])); \
MOAssert( ( ![obj isEqualToString:@""]), @"%s should be a non-empty NSString, but it is empty.", #_object_); \
} while( 0)

This macro makes three assertions: first that _object_ is not nil, second that [_object_ isKindOfClass:[NSString class]], and finally that _object_ is not equal to the empty string. The macro takes one argument:

_object_: The _object being tested.


MOAssertNonEmptyStringOrNil

Assert an object is nil or a non-empty string.
#define MOAssertNonEmptyStringOrNil( _object_) \
do { \
Class cls = [NSString class]; \
id obj = ( _object_); \
MOAssert( ( obj == nil || [obj isKindOfClass:cls]), @"%s should be a non-empty NSString, but it is of class %@.", #_object_, NSStringFromClass( [obj class])); \
MOAssert( ( obj == nil || ![obj isEqualToString:@""]), @"%s should be a non-empty NSString, but it is empty.", #_object_); \
} while( 0)

This macro makes two assertions: first that _object_ is either nil or [_object_ isKindOfClass:[NSString class]], and second that _object_ is not equal to the empty string (if it is non-nil). The macro takes one argument:

_object_: The _object being tested.


MOAssertProtocol

Assert an object conforms to a protocol.
#define MOAssertProtocol( _object_, _protocol_) \
do { \
Protocol *proto = ( _protocol_); \
id obj = ( _object_); \
MOAssert( ( obj != nil), @"%s should be an object conforming to %s, but it is nil.", #_object_, #_protocol_); \
MOAssert( ( [obj conformsToProtocol:proto]), @"%s should be an object conforming to %s, but it does not.", #_object_, #_protocol_); \
} while( 0)

This macro makes two assertions: first that _object_ is not nil, and second that [_object_ conformsToProtocol:_protocol_]. The macro takes two arguments:

_object_: The object being tested.

_protocol_: The protocol it is being asserted to conform to.


MOAssertProtocolOrNil

Assert an object is nil or conforms to a protocol.
#define MOAssertProtocolOrNil( _object_, _protocol_) \
do { \
Protocol *proto = ( _protocol_); \
id obj = ( _object_); \
MOAssert( ( obj == nil || [obj conformsToProtocol:proto]), @"%s should be an object conforming to %s, but it does not.", #_object_, #_protocol_); \
} while( 0)

This macro asserts that _object_ is either nil or that [_object_ conformsToProtocol:_protocol_]. The macro takes two arguments:

_object_: The object being tested.

_protocol_: The protocol it is being asserted to conform to.


MOAssertRespondsToSelector

Assert an object responds to a selector.
#define MOAssertRespondsToSelector( _object_, _selector_) \
do { \
SEL sel = _selector_; \
id obj = ( _object_); \
MOAssert( ( obj != nil), @"%s should be an object responding to %@, but it is nil.", #_object_, NSStringFromSelector( sel)); \
MOAssert( ( [obj respondsToSelector:sel]), @"%s should be an object responding to %@, but it does not.", #_object_, NSStringFromSelector( sel)); \
} while( 0)

This macro makes two assertions: first that _object_ is not nil, and second that [_object_ respondsToSelector:_selector_]. The macro takes two arguments:

_object_: The object being tested.

_selector_: The selector it is being asserted to implement.


MOAssertRespondsToSelectorOrNil

Assert an object is nil or responds to a selector.
#define MOAssertRespondsToSelectorOrNil( _object_, _selector_) \
do { \
SEL sel = _selector_; \
id obj = ( _object_); \
MOAssert( ( obj == nil || [obj respondsToSelector:sel]), @"%s should be an object responding to %@, but it does not.", #_object_, NSStringFromSelector( sel)); \
} while( 0)

This macro asserts that _object_ is either nil or that [_object_ respondsToSelector:_selector_]. The macro takes two arguments:

_object_: The object being tested.

_selector_: The selector it is being asserted to implement.


MOAssertString

Assert an object is a string.
#define MOAssertString( _object_) \
do { \
Class cls = [NSString class]; \
id obj = ( _object_); \
MOAssert( ( obj != nil), @"%s should be an NSString, but it is nil.", #_object_); \
MOAssert( ( [obj isKindOfClass:cls]), @"%s should be an NSString, but it is of class %@.", #_object_, NSStringFromClass( [obj class])); \
} while( 0)

This macro makes two assertions: first that _object_ is not nil, and second that [_object_ isKindOfClass:[NSString class]]. The macro takes one argument:

_object_: The _object being tested.


MOAssertStringOrNil

Assert an object is nil or a string.
#define MOAssertStringOrNil( _object_) \
do { \
Class cls = [NSString class]; \
id obj = ( _object_); \
MOAssert( ( obj == nil || [obj isKindOfClass:cls]), @"%s should be an NSString, but it is of class %@.", #_object_, NSStringFromClass( [obj class])); \
} while( 0)

This macro asserts that _object_ is either nil, or that [_object_ isKindOfClass:[NSString class]]. The macro takes one argument:

_object_: The _object being tested.


MOError

Used to cause an unconditional assertion failure.
#define MOError( _desc_, _args_...) \
do { \
MOHandleAssertionFailure( YES, _cmd, self, __PRETTY_FUNCTION__, __FILE__, __LINE__, ( _desc_), ## _args_); \
} while( 0)

This macro always causes an assertion failure. It takes a format string and printf-style arguments for the format string. The macro takes a variable number of arguments:

_desc_: The description or format string for the assertion. Any additional arguments (_args_) are replacement arguments for % directives in the format string.


MOInvariantAssert

A convenience assertion with a canned message for invariants.
#define MOInvariantAssert( _condition_) \
MOAssert( ( _condition_), @"Invariant broken: %s", #_condition_)

This macro simply asserts the given _condition_ with a description that indicates that failure implies a broken invariant. The condition itself is included in the message. The macro takes one argument:

_condition_: The conditional expression being asserted. This can be any expression that is legal within the parens of an if () statement.


MOParameterAssert

A convenience assertion with a canned message for invalid parameters.
#define MOParameterAssert( _condition_) \
MOAssert( ( _condition_), @"Invalid parameter not satisfying: %s", #_condition_)

This macro simply asserts the given _condition_ with a description that indicates that failure implies a bad parameter being passed to a function or method. The condition itself is included in the message. The macro takes one argument:

_condition_: The conditional expression being asserted. This can be any expression that is legal within the parens of an if () statement.


MOPostconditionAssert

A convenience assertion with a canned message for postconditions.
#define MOPostconditionAssert( _condition_) \
MOAssert( ( _condition_), @"Postcondition broken: %s", #_condition_)

This macro simply asserts the given _condition_ with a description that indicates that failure implies a broken postcondition. The condition itself is included in the message. The macro takes one argument:

_condition_: The conditional expression being asserted. This can be any expression that is legal within the parens of an if () statement.


MOPreconditionAssert

A convenience assertion with a canned message for preconditions.
#define MOPreconditionAssert( _condition_) \
MOAssert( ( _condition_), @"Precondition broken: %s", #_condition_)

This macro simply asserts the given _condition_ with a description that indicates that failure implies a broken precondition. The condition itself is included in the message. The macro takes one argument:

_condition_: The conditional expression being asserted. This can be any expression that is legal within the parens of an if () statement.


MOSubclassResponsibilityError

Used to indicate a subclass responsibility that has not been fulfilled.
#define MOSubclassResponsibilityError( _class_) \
do { \
Class cls = [_class_ class]; \
MOAssert( 0,@"Error. The method %@ must be overridden by subclasses of %
    @.", NSStringFromSelector( _cmd), NSStringFromClass( cls)); \
} while( 0)

This macro always causes an assertion failure. It is used to indicate that subclass responsibility that has not been fulfilled. Usually it is called from an abstract class' implementation of a method that must be overridden by all subclasses. The macro takes one argument:

_class_: The abstract class. Generally this is the class whose implementation is invoking the macro.


MOSubclassResponsibilityError

Used to indicate a subclass responsibility that has not been fulfilled.
See Also:
MOWarning
#define MOWarning( _desc_, _args_...) \
do { \
MOHandleAssertionFailure( YES, _cmd, self, __PRETTY_FUNCTION__, __FILE__, __LINE__, ( _desc_), ## _args_); \
} while( 0)

This macro never causes an assertion failure. It simply logs an error message. The macro takes a variable number of arguments:

_desc_: The description or format string for the assertion. Any additional arguments (_args_) are replacement arguments for % directives in the format string.


MOWarning

Used to indicate a subclass responsibility that has not been fulfilled.
See Also:
MOSubclassResponsibilityError
#define MOWarning( _desc_, _args_...) \
do { \
MOHandleAssertionFailure( YES, _cmd, self, __PRETTY_FUNCTION__, __FILE__, __LINE__, ( _desc_), ## _args_); \
} while( 0)

This macro never causes an assertion failure. It simply logs an error message. The macro takes a variable number of arguments:

_desc_: The description or format string for the assertion. Any additional arguments (_args_) are replacement arguments for % directives in the format string.

(Last Updated 3/20/2005)