Nirav
Nirav

Reputation: 315

NSDictionary Category Fails

I create a category for NSDictionary and override couple of methods 1. writeToFile 2. initWithContentsOfFile.

The WriteToFile function works perfectly and my function gets called. The initWithContentsOfFile fails, it doesnt call my extended function and it returns NULL.

Any pointers/solution/guidance what I am missing or doing wrong?

The same thing works for NSString and I am able to call the similar methods.

Update - My Code

#import <Foundation/Foundation.h>

@interface NSDictionary (TESTDictionary)

-(BOOL)writeToFile:(NSString *)path atomically:(BOOL)useAuxiliaryFile;
-(id)initWithContentsOfFile:(NSString *)path;

@end

The implementation

 #import "NSDictionary+TESTDictionary.h"
@implementation NSDictionary (DMPNSDictionary)

-(BOOL)writeToFile:(NSString *)path atomically:(BOOL)useAuxiliaryFile{

    NSData *someData ;
    //
    //I process somedata and convert the NSDictionary to NSData here
    //
    //Write the processed data
    return [someData writeToFile:path atomically:useAuxiliaryFile];
}

-(id)initWithContentsOfFile:(NSString *)path{
    //Read the file to NSData
    NSData *someData = [read from the file here];
    //convert the NSData to NSDictionary
    self = convertedNSDictionary;
    return self;
}

@end

And I use them in one of the file as

#import "NSDictionary+TESTDictionary.h"

NSDictionary *xmlDictionary;
//write to file where storepath is in application document directory
[xmlDictionary writeToFile:storePath atomically:YES];

I try reading as follows

 NSMutableDictionary *xmlDictionary = [[NSMutableDictionary alloc]initWithContentsOfFile:storePath1];
    NSLog(@"Contents ::%@",xmlDictionary);

 NSDictionary *xmlDictionary = [[NSDictionary alloc]initWithContentsOfFile:storePath1];
    NSLog(@"Contents ::%@",xmlDictionary);

In both the cases I get Contents as null Regards,

Nirav

Upvotes: 1

Views: 1399

Answers (1)

Dirk
Dirk

Reputation: 31053

It is dangerous to override existing methods in a category, since there are no guarantees, about whether your overridden method is called or the already existing method. In particular, NSDictionary already has a member call initWithContentsOfFile:. Categories are safe only, if you add new methods, AFAIK. The same applies to writeToFile:atomically:.

Either create a subclass (instead of merely adding a category), or use a custom dictionary class and employ composition.

See this answer for details.

Revised What's wrong with adding your own specific method pair for that purpose instead of hooking the existing methods?

@interface NSDictionary (EncryptedReadingAndWriting)

- (id) initWithContentsOfEncryptedFile: (NSString*) path;
- (BOOL) writeToEncryptedFile: (NSString*) path atomically: (BOOL) flag;

@end

The methods are similar enough to the "standard" ones, so that it should be clear how to use them (though adding a little comment wouldn't hurt).

This solution has the advantage, that

  • it does not clobber existing methods, which is a bad idea anyway, since you don't know who is using those and for what purpose, and
  • it makes absolutely clear, that this is a new contract, which deals in encrypted files, not the "usual" files, a NSDictionary usually reads/writes.

Upvotes: 1

Related Questions