1

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

Nirav
  • 315
  • 1
  • 4
  • 16
  • 1
    Can you show us the code for definition/usage? – waldrumpus Sep 17 '12 at 09:59
  • 1
    You have included the header for your category in the file where you have used `initWithContentsOfFile`, right? As a side note, it is probably better to name your methods something different than what's in Cocoa to avoid confusion later on. – Sergey Kalinichenko Sep 17 '12 at 10:25
  • Added the sample implementation and the code usage !! – Nirav Sep 17 '12 at 11:27
  • First, I believe that categories defined on `NSDictionary` will not carry over to `NSMutableDictionary`, but rather be fixed to that specific class. Second, there is already a method called `-[NSDictionary initWithContentsOfFile:]`; maybe this interferes with your definition of the same name. Try renaming yours and see if it works. – waldrumpus Sep 17 '12 at 11:47

1 Answers1

1

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.
Community
  • 1
  • 1
Dirk
  • 30,623
  • 8
  • 82
  • 102
  • How safe/good is Method Swizzling? Using Method swizzling will I be able to achiveve the above ? – Nirav Sep 17 '12 at 12:52
  • @Nirav: Do you really want to modify the behaviour of *all* `NSDictionary` instances in your program that way? This is, what you seem to try to achieve here. What is the use case? What about other code (e.g., in Cocoa itself), which calls these methods. These places would automatically get your special treatment, too. Is that really your intention? If you do this simply to read/write some internal file format, this is simply dangerous overkill. – Dirk Sep 17 '12 at 13:01
  • -thanks for the explanation. My usecase is to encrypt all the contents of the NSDictionary and writeToFile. And while reading simple decrypt and return. This I want to achieve by keeping the function signature same as the native class. Basically I am creating a framework which will do these operation for NSDictionary/NSString/NSArray/NSData. And frankly speaking m not an expert in iOS :). – Nirav Sep 18 '12 at 04:15