NSObject categories documentation
ETModel
NSObject (ETModel)Providing the Metamodel
- + (ETEntityDescription *) newEntityDescription
Returns a new self-description (aka metamodel).
You must never use this method to retrieve an entity description, but only retrieves it through a ETModelDescriptionRepository instance.
This method can be invoked at runtime by a repository to automatically collect the entity descriptions and make them available in this repository.
You can implement this method to describe your subclasses more precisely than -basicNewEntityDescription .
You must never call [super newEntityDescription] in the implementation.
You must not return an autoreleased object.For example:
ETEntityDescription *desc = [self newBasicEntityDescription]; // For subclasses that don't override -newEntityDescription, we must not add the // property descriptions that we will inherit through the parent (the // 'MyClassName' entity description). if ([[desc name] isEqual: [MyClass className]] == NO) return desc; ETPropertyDescription *city = [ETPropertyDescription descriptionWithName: @"city" type: (id)@"NSString"]; ETPropertyDescription *country = [ETPropertyDescription descriptionWithName: @"country" type: (id)@"NSString"]; [desc setPropertyDescriptions: A(city, country)]; [desc setAbstract: YES]; return desc;
If you want set the parent explicitly, replace -newBasicEntityDescription with:
ETEntityDescription *desc = [ETEntityDescription descriptionWithName: [self className]]; // Will be resolved when the entity description is put in the repository [desc setParent: NSStringFromClass([self superclass])];
Returns a new self-description (aka metamodel).
You must never use this method to retrieve an entity description, but only retrieves it through a ETModelDescriptionRepository instance.
This method can be invoked at runtime by a repository to automatically collect the entity descriptions and make them available in this repository.
You can implement this method to describe your subclasses more precisely than -basicNewEntityDescription .
You must never call [super newEntityDescription] in the implementation.
You must not return an autoreleased object.For example:
ETEntityDescription *desc = [self newBasicEntityDescription]; // For subclasses that don't override -newEntityDescription, we must not add the // property descriptions that we will inherit through the parent (the // 'MyClassName' entity description). if ([[desc name] isEqual: [MyClass className]] == NO) return desc; ETPropertyDescription *city = [ETPropertyDescription descriptionWithName: @"city" type: (id)@"NSString"]; ETPropertyDescription *country = [ETPropertyDescription descriptionWithName: @"country" type: (id)@"NSString"]; [desc setPropertyDescriptions: A(city, country)]; [desc setAbstract: YES]; return desc;
If you want set the parent explicitly, replace -newBasicEntityDescription with:
ETEntityDescription *desc = [ETEntityDescription descriptionWithName: [self className]]; // Will be resolved when the entity description is put in the repository [desc setParent: NSStringFromClass([self superclass])];
- + (ETEntityDescription *) newBasicEntityDescription
Returns a new minimal self-description without any property descriptions.
This entity description uses the class name as its name and the parent is set to the superclass name.
The parent will be resolved once when the description is added to the repository.You must never use this method to retrieve an entity description, but only a ETModelDescriptionRepository instance to do so.
The returned object is not autoreleased.
See also -newEntityDescription .
Common Representations
- - (NSString *) stringValue
Returns the description of the receiver by default.
Subclasses can override this method to return a string representation that encodes some basic infos about the receiver. This string representation can then be edited, validated by -validateValue:forKey:error: and used to instantiate another object by passing it to +objectWithStringValue: .
- - (BOOL) isCommonObjectValue
Returns YES when the receiver is an object which can be passed to -setObjectValue: or returned by -objectValue . Some common object values like string and number can be displayed and edited transparently (in an NSCell instance to take an example). If you define additional common object values, you usually have to write related formatters. Returns NO by default. Subclasses can override this method to specify an object can be accepted and used a common object value.
Basic Properties
- - (NSString *) displayName
Returns the receiver description. Subclasses can override this method to return a more appropriate display name.
Returns the receiver description. Subclasses can override this method to return a more appropriate display name.
- - (NSString *) primitiveDescription
Returns the description as NSObject would. This method returns the same value as -description if the latter method isn't overriden in your subclasses, otherwise it returns the value that -description would return if you haven't overriden it. Useful to get consistent short descriptions on all instances and can be used to provide custom description built with other short descriptions.
- - (NSString *) descriptionWithOptions: (NSMutableDictionary *)options
Returns a description generated based on the given options.
Might describe a tree or graph structure if a traversal key is provided to recursively invoke -descriptionsWithOptions: on each object node. To do so, put ETDescriptionOptionTraversalKey with a valid KVC key in the options. You can also set a max depth with ETDescriptionOptionMaxDepth to limit the description size or end a graph traversal.
You can collect key path values on each object node by specifying an array of key paths with ETDescriptionOptionValuesForKeyPaths.
The description format is roughly: depth based indentation + object short description + keyPath1: value1, keyPath2: value2 etc.
By default, -description is used to print both object short description and key path values.
For customizing the object short description, put kETDescriptionOptionShortDescriptionSelector with a custom selector string in the options (-description is then used as fallback).
If you override -description to call -descriptionWithOptions: , you must provide a valid kETDescriptionOptionShortDescriptionSelector to prevent an endless loop (for example, just use -primitiveDescription).For presenting each key path on a new line, put kETDescriptionOptionPropertyIndent with a tab string in the options.
Here is an example based on EtoileUI that dumps an item tree structure:
// ObjC code ETLog(@"\n%@\n", [browserItem descriptionWithOptions: [NSMutableDictionary dictionaryWithObjectsAndKeys: A(@"frame", @"autoresizingMask"), kETDescriptionOptionValuesForKeyPaths, @"items", kETDescriptionOptionTraversalKey, nil]]); // Console Output <ETLayoutItemGroup: 0x9e7b268> { frame: {x = 0; y = 0; width = 600; height = 300}, autoresizingMask: 18 } <ETLayoutItemGroup: 0x9fbea48> { frame: {x = 0; y = 0; width = 1150; height = 53}, autoresizingMask: 2 } <ETLayoutItem: 0x9f29240> { frame: {x = 12; y = 12; width = 100; height = 22}, autoresizingMask: 0 } <ETLayoutItem: 0x9e6fcf0> { frame: {x = 124; y = 12; width = 100; height = 24}, autoresizingMask: 0 } <ETLayoutItemGroup: 0x9fac170> { frame: {x = 0; y = 0; width = 1150; height = 482}, autoresizingMask: 18 } <ETLayoutItemGroup: 0x9fb2870> { frame: {x = 0; y = 0; width = 50; height = 50}, autoresizingMask: 0 }
options must not be nil, otherwise raises an NSInvalidArgumentException.
You can override this method in subclasses, although it is not advised to. The options dictionary can be changed arbitrarily in a new implementation.
KVO Syntactic Sugar (Unstable API)
- - (NSSet *) observableKeyPaths
Returns an empty set.
Overrides to return the receiver key paths to be observed when an observer is set up with -addObserver: .
The returned set content must not change during the whole object lifetime, otherwise -removeObserver: will crash randomly.
Returns an empty set.
Overrides to return the receiver key paths to be observed when an observer is set up with -addObserver: .
The returned set content must not change during the whole object lifetime, otherwise -removeObserver: will crash randomly.
- - (void) addObserver: (id)anObserver
Sets up the given object to observe each receiver key paths returned by -observableKeyPaths .
The observer will receive NSKeyValueObservingOptionOld and NSKeyValueObservingOptionNew in the change dictionary.
- - (void) removeObserver: (id)anObserver
Removes the observer that was observing the receiver key paths returned by -observableKeyPaths .
Collection and Mutability
- + (Class) mutableClass
Returns a mutable counterpart class or Nil if such a class does not exist.
Returns a mutable counterpart class or Nil if such a class does not exist.
- - (BOOL) isMutable
Returns YES if the receiver is declared as mutable, otherwise returns NO.
This method returns NO by default. You can override it to return YES if you want to declare your subclass instances as mutable objects (which are collections most of time).
If you adopts ETCollectionMutation in a subclass, you don't need to override this method to declare your collection objects as mutable.
- - (BOOL) isCollection
Returns YES if the receiver is declared as a collection by conforming to ETCollection protocol, otherwise returns NO.
You must never override this method in your collection classes, you only need to adopt ETCollection protocol.
- - (BOOL) isMutableCollection
Returns YES if the receiver is declared as a collection by conforming to ETCollectionMutation protocol, otherwise returns NO.
You must never override this method in your collection classes, you only need to adopt ETCollectionMutation protocol.
- - (BOOL) isPrimitiveCollection
Returns YES if the receiver is a low-level collection such as NSArray, NSet, etc., otherwise returns NO.
For a model object such as ETLayoutItemGroup that conforms to ETCollection protocol, would return NO.
- - (BOOL) isGroup
Returns YES if the receiver is declared as a group, otherwise returns NO.
This method returns NO by default. You can override it to return YES if you want to declare your subclass instances as groups.
A group is specialized model object which is a composite and can behave like a mutable collection. A basic collection object (like NSMutableArray, NSMutableDictionary, NSMutableSet) must never be declared as a group.
COGroup in CoreObject or ETLayoutItemGroup in EtoileUI are typical examples.A group should conform to ETCollectionMutation protocol.
- - (id) insertionKeyForCollection: (id <ETKeyedCollection>)aCollection
Returns a key for inserting the receiver into the given keyed collection.
By default, returns a key built by incrementing the integer value in the 'Unknown <number>' pattern, until it provides a key not yet in use in the collection argument.
This key is retrieved by a collection in reply to -insertObjects:atIndexes:hints: of ETCollectionMutation protocol. You can return different keys depending on the type of collection. This parameter is usually the mutated collection itself.
ETPropertyValueCoding
NSObject (ETPropertyValueCoding)Overview
Property-Value Coding allows to access properties of objects in a uniform manner, while still supporting Key-Value Coding.
Key-Value Coding is similar but tends to be overriden in many subclasses. As a result, -[NSDictionary valueForKey: @"count"] doesn't return the count value, but attemps to look a value using [NSDictionary objectForKey: @"count"]. So Key-Value Coding doesn't constitute a mechanism versatile enough to introspect or access object properties. In addition, -valueForKey: doesn't accept invalid key unlike -valueForProperty: . This is important for presenting unrelated objects in a table UI (mapping properties to columns) where each object has its own property set. More generally this matters for manipulating properties of unrelated objects using the same code.
ETPropertyValueCoding protocol is usually adopted by root object classes such as NSObject and overriden in subclasses. See NSObject(Model).
The basic behavior of the Property-Value-Coding is implemented in NSObject(ETModelAdditions), but few classes such as ETMutableObjectViewpoint and ETLayoutItem in EtoileUI overrides the NSObject semantic for -valueForProperty: and -setValue:forProperty: .
Default
- - (BOOL) requiresKeyValueCodingForAccessingProperties
Can be overriden to return YES in order to support exposing properties, in case -valueForProperty: and -setValue:forProperty: access another object and not the receiver.
This method is used by ETMutableObjectViewpoint to determine whether the receiver represented property can be accessed through -valueForProperty: or -valueForKey: .
By default, returns NO.
If -valueForProperty: and -setValue:forProperty: don't access a represented object, there is not need to override this method to return YES in subclasses. You usually never need to override this method unless you adopt ETPropertyViewpoint protocol.
- - (NSArray *) propertyNames
Returns the names of the properties exposed by the receiver through -valueForProperty: and -setValue:forProperty: , or -valueForKey: and -setValue:forKey: if -requiresKeyValueCodingForAccessingProperties returns YES.
Returns both the property names bound to the object entity description and the basic property names.
+[ETModelDescriptionRepository mainRepository] is used to look up the entity description.
To be exposed through Property Value Coding, the receiver properties must be listed among the returned properties.
Can be overriden to return property names bound to entity descriptions that don't belong to the main repository, or filter some properties out. In the overriden method, you should usually return -basicPropertyNames along the property description names.
For a NSObject subclass not bound to an entity description, the property names related to the closest superclass bound to an entity description are returned through a recursive lookup in -entityDescriptionForClass: .
See -basicPropertyNames , -valueForProperty: and -setValue:forProperty: . See also -[ETPropertyValueCoding propertyNames] .
- - (id) valueForProperty: (NSString *)key
Returns the value of the property.
If the property doesn't exist, returns nil but must not raise an exception.
The method precise semantic is under the control of the class implementing the protocol. For example, the property can belong to another object than the receiver.
See also -[NSObject valueForProperty:] and -[ETPropertyViewpoint valueForProperty:] .
- - (BOOL) setValue: (id)value forProperty: (NSString *)key
Sets the value of the property and returns YES if the value was successfully set.
If the property doesn't exist, returns NO but must not raise an exception.
The method precise semantic is under the control of the class implementing the protocol.
See also -[NSObject setValue:forProperty:] and -[ETPropertyViewpoint setValue:forProperty:] .
ETKeyValuePair
NSObject (ETKeyValuePair)Default
- - (BOOL) isKeyValuePair
Returns whether the receiver is a ETKeyValuePair instance.
ETDoubleDispatch
NSObject (ETDoubleDispatch)Overview
This category provides a visitor which supports double-dispatch on all visited objects without implementing extra methods (such as accept: on the visited object side).
For a more detailed discussion, see -visit: .
Here is a visitor example:
@interface ETView : NSView @end @interface UIVisitor : NSObject @end @implementation ETView + (NSString *) typePrefix { return @"ET"; } @end // To start using the visitor, instantiate a visitor and do [visitor visit: someWindow] @implementation UIVisitor // visitXXX methods return id, but returning void would be valid - (id) visitWindow: (NSWindow *)aWindow { NSLog(@"Visiting window %@", aWindow); return [self visit: [aWindow contentView]]; } - (id) visitView: (NSView *)aView { NSLog(@"Visiting view %@", aView); for (NSView *subview in [aView subviews]) { [self visit: subview]; } return nil; } // Show how you can include the class name prefix and how such a method has // priority over a method without any type prefix such as -visitView:. - (id) visitETView: (ETView *)aSpecialView { NSLog(@"Visiting special view %@", aSpecialView); return nil; } @end
Default
- - (NSString *) doubleDispatchPrefix
Returns the method name prefix used to build the method name to be invoked by the double dispatch.
By default, returns visit.
Can be overriden to return a custom prefix such as visit.
See also -visit: .
- - (id) visit: (id)object
Tries to build a method name based on the given object type and invoke it.
For example, if you have a NSView, and you pass it as an argument to -visit: , the selector visitNSView: is built and invoked with the given view on the receiver. If the receiver doesn't respond to visitNSView: , then visitView: is built by trimming the class name prefix, and invoked. If the receiver still doesn't respond the last built selector, then it fails silently and returns nil.
Class name prefix are trimmed based on the value returned by +[NSObject(Etoile) typePrefix] . You can override this last method to return a custom prefix, by default it returns NS.If you want to use another method name prefix than visit (e.g. to build a selector such as renderView:), -doubleDispatchPrefix can be overriden.
Subclasses can override this method, if they want to customize the double-dispatch behavior.
- - (id) visit: (id)object result: (BOOL *)performed
Does the same than -visit: but reports whether a double-dispatch method was succesfully invoked by setting performed to YES, or NO when no such method was found.
See also -visit: and -supportsDoubleDispatchWithObject:.
This method is called by -visit: and implements the double-dispatch logic.
- - (BOOL) supportsDoubleDispatchWithObject: (id)object
Returns whether the receiver implements a double dispatch method that corresponds to the given object type.
This method serves a similar purpose than -[NSObject respondsToSelector:] .
See also -visit: .
- - (SEL) doubleDispatchSelectorWithObject: (id)object ofType: (NSString *)aType
Builds and returns the selector to be invoked for a double dispatch on the given type.
For a detailed example, see -visit: .
Can be overriden in subclasses to implement an alternative strategy to build the method names targeted by the double dispatch.
- - (id) tryToPerformSelector: (SEL)selector withObject: (id)object result: (BOOL *)performed
Tries to invoke the selector with the given object as first argument, and returns either the value returned by the invoked method or nil.
If the receiver doesn't respond to the selector, performed is set to NO and nil is returned, otherwise performed is set YES.
ETTrait
NSObject (ETTrait)Overview
Adds traits to Objective-C, to support class composition, in addition to inheritance. Traits allow methods to be added to another class.
The trait support in EtoileFoundation is based on:
- http://scg.unibe.ch/archive/papers/Scha03aTraits.pdf (original and short one)
- http://scg.unibe.ch/archive/papers/Duca06bTOPLASTraits.pdf (most recent and quite lengthy)
To get an introduction to the trait model and its various rules, you should read the short paper listed above.
Objective-C Trait Overview and Restrictions
The trait API supports both trait operators (exclusion, aliasing) and composite trait (a trait with subtraits). However there are two important restrictions:
- the super keyword must not be used in a trait method
- instances variables must not be accessed directly but only through accessors
If these restrictions are ignored, the code may compile, but will surely result in a buggy behavior at runtime.
With the current implementation, the limitations below should be kept in mind:
- trait applications don't take in account class methods
- no mechanism to declare and check non-trait methods required by trait methods (so you get a runtime exception instead)
Basic example and Terminology
To apply a trait, the basic API is +applyTraitFromClass: , and we use the terminology below:
- trait class
- the class which represents a trait and whose methods are called trait methods. The superclass methods are ignored if the class is used as a trait
- target class
- the class to which a trait class is applied to
- trait application
- a trait use that involves a trait class, a target class and operator-related arguments
For example:
// Traits should be applied as early as possible usually, that's why we use +initialize + (void) initialize { if (self != [MyClass class]) return; [aTargetClass applyTraitFromClass: aTraitClass]; }
Detailed Examples
Here is a more complex example that applies two subtraits (BasicTrait and ComplexTrait) to another trait (CompositeTrait), then the resulting is applied to the target class (the receiver's class).
// -wanderWhere: from Basic method will be renamed -lost: in CompositeTrait [[CompositeTrait class] applyTraitFromClass: [BasicTrait class] excludedMethodNames: S(@"isOrdered") aliasedMethodNames: D(@"lost:", @"wanderWhere:")]; [[CompositeTrait class] applyTraitFromClass: [ComplexTrait class]]; [[self class] applyTraitFromClass: [CompositeTrait class]];
As a concrete example, collection protocols are now implemented by most classes in Étoilé frameworks through two new ETCollectionTrait and ETMutableCollectionTrait.
Trait Validation
Trait applications are memorized to support composite traits and multiple trait applications to the same target class. Each time a trait is applied, it gets validated against the trait tree already bound to the target class. This ensures operators, overriding rule and flattening property will remain valid in the new trait tree. Unlike Squeak trait support, a trait can be applied at any time.
Mixin-style Application
In addition, it's possible to apply a trait without the overriding rule (that states target class overrides trait methods), which means methods in the target class can be replaced by methods from a trait.
// With YES, we allow the trait to override/replace methods in the target class [[self class] applyTraitFromClass: [BasicTrait class] excludedMethodNames: S(@"isOrdered") aliasedMethodNames: D(@"lost:", @"wanderWhere:") allowsOverride: YES];
Trait applications are commutative, so the ordering in which you apply traits doesn't matter… but when this mixin-style composition is used, traits are not commutative and the ordering matters. That's why we'd rather discourage its use.
Default
- + (void) applyTraitFromClass: (Class)aClass
Apply aClass to this class as a trait.
Raises exceptions if the trait application cannot be validated.
- + (void) applyTraitFromClass: (Class)aClass excludedMethodNames: (NSSet *)excludedNames aliasedMethodNames: (NSDictionary *)aliasedNames
Apply aClass to this class as a trait, without the trait methods listed in excludedNames, and by renaming the trait methods with the name values provided in the aliasedNames dictionary (where keys should be the existing trait method names).
Raises exceptions if the trait application cannot be validated.
- + (void) applyTraitFromClass: (Class)aClass excludedMethodNames: (NSSet *)excludedNames aliasedMethodNames: (NSDictionary *)aliasedNames allowsOverride: (BOOL)override
Does the same than +applyTraitFromClass:excludedMethodNames:aliasedMethodNames: but allows to replace methods in the target class with trait methods if YES is passed as the last argument.
By default, the trait overriding rule states that trait methods cannot replace methods that belongs to the target class, but only hide methods declared in superclasses and inherited by the target class.
If YES is passed and there are other traits applied to the target class, the ordering use to apply traits cannot be ignored anymore.
Raises exceptions if the trait application cannot be validated.
Etoile
NSObject (Etoile)Overview
This category extends NSObject reflection API in a minimal way.
The true Etoile reflection API is declared in ETReflection.h.
Default
- + (NSArray *) allSubclasses
Returns all descendant subclasses of the receiver class.
The returned array doesn't include the receiver class.
You should rather use -[ETClassMirror allSubclassMirrors] , this method could be deprecated in the future.
- + (NSArray *) directSubclasses
Returns all subclasses which inherit directly from the receiver class.
Subclasses that belongs to the class hierarchy of the receiver class but whose superclasses aren't equal to it, are excluded.
The returned array doesn't include the receiver class.
- - (ETUTI *) UTI
Returns the uniform type identifier of the object.
The UTI object encodes the type of the object in term of namespaces and multiple inheritance.
By default, the UTI object is shared by all instances by being built from the class name. If you need to introduce type at instance level, you can do it by overriding this method.
- - (NSString *) typeName
Returns the type name which is the last component of the string value returned by the receiver UTI object.
See also -UTI.
- + (NSString *) typePrefix
Returns the type prefix, usually the prefix part of the type name returned by -className .
By default, returns 'NS'.
You must override this method in your subclass to indicate the prefix of your new class name. Take note the prefix will logically apply to every subsequent subclasses inheriting from the class that redefines -typePrefix .
ETListenSocketDelegate
NSObject (ETListenSocketDelegate)ETSocketDelegate
NSObject (ETSocketDelegate)Default
- - (void) receivedData: (NSData *)aData fromSocket: (ETSocket *)aSocket
Handle data received over the specified socket.
ETBatchCollectionMutation
NSObject (ETBatchCollectionMutation)Overview
Any mutable collection can also implement the optional methods listed below.
EtoileUI will use these methods when possible.
Initially you can skip implementing them. Later, they can be implemented to speed up the communication between your model collections and the layout items that represent them at the UI level. In addition, these methods allows to react to batch insertion and removal at the model level (e.g. in reply to a pick and drop).
You are not required to implement every method when a class adopts this informal protocol.
When a collection is received in argument, the collection type can be checked to know whether the code needs to convert the collection or not, to remove or insert its content in the receiver. In most cases, the code below is a useless optimization (the else branch is good enough).
if ([[aCollection content] isArray] == NO) { [personIvarArray addObjectsFromArray: (NSArray *)aCollection]; } else { [personIvarArray addObjectsFromArray: [aCollection contentArray]]; }
See NSObject+Model for other methods such as -isArray .
Default
- - (void) insertCollection: (id <ETCollection>)objects atIndexes: (NSIndexSet *)indexes
Inserts the given collection elements at separate indexes.
When the collection is not ordered, the indexes are ignored.
The element are inserted one-by-one by increasing index value while iterating over the indexes. When the greatest index is reached and several elements remain to be inserted, they are inserted at that same index.
For a more precise description of the behavior ordered collection should comply to, see -[NSArray insertObjects:atIndexes:] in Cocoa documentation.
- - (void) removesCollection: (id <ETCollection>)objects
Removes the elements from the collection.
ETCollectionMutationKVOSupport
NSObject (ETCollectionMutationKVOSupport)Overview
This lets you easily change the collection type, without rewriting all the mutation notifications.
Default
- - (void) willChangeValueForKey: (NSString *)key atIndexes: (NSIndexSet *)indexes withObjects: (NSArray *)objects mutationKind: (ETCollectionMutationKind)mutationKind
Tells the receiver that the collection bound to the property is about to change.
By default, limited to calling:
- -willChangeValueForKey:
- NSDictionary, NSMapTable and NSIndexSet
- -willChange:valuesAtIndexes:forKey:
- NSArray, NSPointerArray and NSOrderedSet
- -willChangeValueForKey:withSetMutation:usingObjects:
- NSSet and NSHashTable
For an ordered collection, the correct index must be passed for each inserted or removed object, otherwise a NSInvalidArgumentException is raised.
For an unordered collection, the indexes should be empty.
For nil arguments, raises a NSInvalidArgumentException.
Can be overriden, but the superclass implementation must be called.
- - (void) didChangeValueForKey: (NSString *)key atIndexes: (NSIndexSet *)indexes withObjects: (NSArray *)objects mutationKind: (ETCollectionMutationKind)mutationKind
Tells the receiver that the collection bound to the property is about to change.
By default, limited to calling:
- -didChangeValueForKey:
- NSDictionary, NSMapTable and NSIndexSet
- -didChange:valuesAtIndexes:forKey:
- NSArray, NSPointerArray and NSOrderedSet
- -didChangeValueForKey:withSetMutation:usingObjects:
- NSSet and NSHashTable
For an ordered collection, the correct index must be passed for each inserted or removed object, otherwise a NSInvalidArgumentException is raised.
For an unordered collection, the indexes should be empty.
For nil arguments, raises a NSInvalidArgumentException.
Can be overriden, but the superclass implementation must be called.
ETIndexValuePair
NSObject (ETIndexValuePair)Default
- - (BOOL) isIndexValuePair
Returns whether the receiver is an index-value pair. By default, returns NO. See also -[ETIndexValuePair isIndexValuePair] .
ETPrototypes
NSObject (ETPrototypes)Default
- + (BOOL) addInstanceMethod: (SEL)aSelector fromBlock: (id)aBlock
Adds an instance method to the class, using the specified block. The types for the method are inferred from the block.
The block must take an object (self) as the first argument. Any subsequent arguments are the explicit arguments to the method. The _cmd argument is not available for methods added in this way.
- + (BOOL) addClassMethod: (SEL)aSelector fromBlock: (id)aBlock
Adds a class method to the class, using the specified block. The types for the method are inferred from the block.
The block must take an object (self) as the first argument. Any subsequent arguments are the explicit arguments to the method. The _cmd argument is not available for methods added in this way.
- - (BOOL) addMethod: (SEL)aSelector fromBlock: (id)aBlock
Adds a method to the receiver, using the specified block. The types for the method are inferred from the block.
The block must take an object (self) as the first argument. Any subsequent arguments are the explicit arguments to the method. The _cmd argument is not available for methods added in this way.
- - (void) setMethod: (IMP)aMethod forSelector: (SEL)aSelector
Adds the specified method to this instance. Objects modified in this way get a hidden dictionary for non-indexed instance variables, allowing them to use KVC to set arbitrary objects on self.
ETHOM
NSObject (ETHOM)Default
- - (id) ifResponds
Returns the receiver itself when it can respond to the next message that follows -ifResponds , otherwise returns nil.
If we suppose the Cat class doesn't implement -bark , then -ifResponds would return nil and thereby -bark be discarded: [[cat ifResponds] bark];
Now let's say the Dog class implement -bark , the -ifResponds will return 'dog' and -bark be executed: [[dog ifResponds] bark];
ETViewpointAdditions
NSObject (ETViewpointAdditions)Overview
This is an unstable API (will probably be removed or changed later).
Default
ETCollectionHOMIntegrationInformalProtocol
NSObject (ETCollectionHOMIntegrationInformalProtocol)Default
- - (NSArray *) collectionArrayAndInfo: (id*)info
Returns the array representation used to evaluate high-order messages.
If not implemented, -contentArray is used.
If info is not NULL, you can return additional information to be passed to the element-handling hook -placeObject:inCollection:insteadOfObject:atIndex:havingAlreadyMapped:info:.
ETEachHOM
NSObject (ETEachHOM)Default
- - (id) each
If the receiver conforms to the ETCollection protocol, this method returns a proxy that will let -map and -filter methods iterate over the contents of the collection when it is used as an argument to a message. This way, [[people map] sendMail: [messages each]]; will cause the -sendMail: message to be executed once with every combination of elements from the people and the messages collection.
Note 1: It is only possible to use an proxy object created with -each if it is passed as an argument to a message that is send to a higher-order messaging proxy created by -filter , -map, -filteredCollection or -mappedCollection . Doing [aCollection addObject: [things each]] won't do anything.
Note 2: If an each proxy is passed to a message used as a filter predicate, it suffices that the predicate evaluates to YES for one element of the argument-collection. If a collection A contains "foo" and "bar" and collection B contains "BAR" and "bar", after [[A filter] isEqualToString: [B each]]; , A will still contain "bar" (but not "BAR"), since one of the elements of B matched "bar".
ETStackTraceRecorderConveniency
NSObject (ETStackTraceRecorderConveniency)Overview
You can use these methods to record stack traces with +[ETStackTraceRecorder sharedInstance] .
For example, in GDB you can type [self recordStackTrace] to keep a trace of the current call stack.
And you can print all the stack traces recorded for the current object with 'po [[self recordedStackTraces] stringValue]'.