Re: problem with subclassing a cluster class
Re: problem with subclassing a cluster class
- Subject: Re: problem with subclassing a cluster class
- From: Greg Herlihy <email@hidden>
- Date: Sun, 05 Mar 2006 15:53:53 -0800
- Thread-topic: problem with subclassing a cluster class
Yes, using the NSMutableDictionary to initialize the NSDictionary is a more
elegant solution than the one I suggested. And safer as well.
Greg
On 3/5/06 2:26 PM, "Ivan Kourtev" <email@hidden> wrote:
> Thanks, that helped. It took me a little while to wrap my brains
> around it but I understand it now. I actually sort of came up with a
> similar solution -- instead of the C arrays you suggested, I used an
> NSMutableDictionary instance to put the arguments in, then
> initWithDictionary for my embedded object. Works like a charm (code
> at end).
>
> --
> ivan
>
> On Mar 5, 2006, at 4:07 PM, Greg Herlihy wrote:
>
>> See comments below...
>>
>> Since the dictionary is immutable, your routine must initialize it
>> with a
>> single call. The NSDictionary's entries cannot be added one at a
>> time like
>> your current code is doing. And that is the behavior causing the
>> problem.
>>
>> Therefore I would recommend pre-allocating two reasonably-sized C
>> arrays,
>> one to hold the keys and the other to hold the values. Then I would
>> place
>> each key and value in the corresponding array as they are read in
>> (with the
>> usual precautions: being certain to use large enough arrays and
>> checking
>> that the current index is within a valid range).
>>
>> Only after all the parameters have been processed in this way,
>> would I call
>>
>> - (id)initWithObjects:(id *)objects forKeys:(id *)keys
>> count:(unsigned)count;
>>
>> Passing pointers to the key and value arrays and how many items are in
>> either - for the count.
>
> #import <Foundation/Foundation.h>
>
> @interface MyDictionary : NSDictionary {
> NSDictionary *embeddedDictionary;
> }
>
> - (id)init;
> - (id)initWithDictionary:(NSDictionary *)otherDictionary;
> + (id)dictionaryWithObjectsAndKeys:(id)firstObject, ...;
> - (void)dealloc;
>
> // Primitive methods of the abstract superclass
> - (unsigned)count;
> - (id)objectForKey:(id)aKey;
> - (NSEnumerator *)keyEnumerator;
>
> @end
>
> @implementation MyDictionary
>
> - (unsigned)count
> {
> assert( embeddedDictionary != nil );
> return [embeddedDictionary count];
> }
>
> - (id)objectForKey:(id)aKey
> {
> assert( embeddedDictionary != nil );
> return [embeddedDictionary objectForKey:aKey];
> }
>
> - (NSEnumerator *)keyEnumerator
> {
> assert( embeddedDictionary != nil );
> return [embeddedDictionary keyEnumerator];
> }
>
> - (id)init
> {
> self = [super init];
> if ( self ) {
> embeddedDictionary = [[NSDictionary alloc] init];
> }
> return self;
> }
>
> - (id)initWithDictionary:(NSDictionary *)otherDictionary
> {
> self = [super init];
> if ( self ) {
> embeddedDictionary = [[NSDictionary alloc]
> initWithDictionary:otherDictionary];
> }
> return self;
> }
>
> - (void)dealloc
> {
> [embeddedDictionary release];
> [super dealloc];
> }
>
> + (id)dictionaryWithObjectsAndKeys:(id)firstObject, ...
> {
> // argument list empty: not much to do but return an empty
> dictionary
> if ( firstObject == nil ) {
> return [[[self alloc] init] autorelease];
> }
>
> // arguments exist: create dictionary and insert keys and
> objects from list
> NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
> va_list argList;
> id anObject, aKey;
> va_start( argList, firstObject );
> aKey = va_arg(argList, id);
> NSLog( @"The first object from the argument list is %@",
> firstObject );
> NSLog( @"The next object from the argument list is %@", aKey );
> if ( aKey == nil ) {
> NSLog( @"Invalid arg list to %s", __PRETTY_FUNCTION__ );
> assert( NO );
> } else {
> NSLog( @" Now inserting %@ for key %@", firstObject, aKey );
> [dictionary setObject:firstObject forKey:aKey];
> }
> while ( ( anObject = va_arg( argList, id) ) != nil ) {
> aKey = va_arg( argList, id);
> if ( aKey == nil ) {
> NSLog( @"Invalid arg list to %s", __PRETTY_FUNCTION__ );
> assert( NO );
> } else {
> NSLog( @" Now inserting %@ for key %@", anObject, aKey );
> [dictionary setObject:anObject forKey:aKey];
> }
> }
> va_end( argList );
> return [[[self alloc] initWithDictionary:dictionary] autorelease];
> }
> @end
>
> int main (int argc, const char * argv[]) {
> NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
> NSString *obj1 = [NSString stringWithString:@"myObject 1"];
> NSString *key1 = [NSString stringWithString:@"myKey 1"];
> NSString *obj2 = [NSString stringWithString:@"myObject 2"];
> NSString *key2 = [NSString stringWithString:@"myKey 2"];
> MyDictionary *dict = [MyDictionary
> dictionaryWithObjectsAndKeys:obj1, key1, obj2, key2, nil];
> NSLog( @"Created dictionary: %@", dict );
> [pool release];
> return 0;
> }
>
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden