0

I am using a dictionary with parameters to send to a web service. I keep getting memory leaks from it, altho I do a release for the object. My code:

 NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];

// getting an NSString
NSString *clientID = [prefs stringForKey:@"ClientID"];



//Call web service
id delegate1 = self;
AsyncWebServiceController * webService = [[[AsyncWebServiceController alloc] initWithDelegate:delegate1
                                                                                 selSucceeded:@selector(webServiceConnectionSucceeded:)
                                                                                    selFailed:@selector(webServiceconnectionFailed:)] autorelease];


NSMutableDictionary *params = [[NSMutableDictionary alloc] init]; //Memory leak here
[params setValue:clientID forKey:@"clientId"]; //Memory leak here
[params setValue:[self.jobDetails objectForKey:@"BoardId"] forKey:@"jobBoardId"];
[params setValue:[self.jobDetails objectForKey:@"Id"] forKey:@"jobId"];

[webService startRequest:@"JobReviewGet" parameters:params];

[params release];

Any ideas? Thanks!!

Yaniv Efraim
  • 6,633
  • 7
  • 53
  • 96
  • You're not releasing webService. And generally one would use setObject rather than setValue, though that shouldn't cause a leak. – Hot Licks Oct 04 '11 at 12:14

4 Answers4

2

You should be using :

- (void)setObject:(id)anObject forKey:(id)aKey;

Thus you code should look like:"

NSMutableDictionary *params = 
[[NSMutableDictionary alloc] init]; //Memory leak here
[params setObject:clientID forKey:@"clientId"]; //Memory leak here
[params setObject:[self.jobDetails objectForKey:@"BoardId"] forKey:@"jobBoardId"];
[params setObject:[self.jobDetails objectForKey:@"Id"] forKey:@"jobId"];

[webService startRequest:@"JobReviewGet" parameters:params];

[params release];

What does [webService startRequest:@"JobReviewGet" parameters:params]; method do with the param, does it retain it? If so you also need to release it there.

Also ar some point you will need to release the webService.

rckoenes
  • 69,092
  • 8
  • 134
  • 166
  • Why `setObject:forKey:` instead of `setValue:forKey:`, both are methods on NSDictionary? I understand that `setValue:forKey:` calls `setObject:forKey:` and the delete semantics but does that apply to the problem here? – zaph Oct 04 '11 at 12:09
  • 1
    No `setValue:forKey:` is a method of `NSObject` and `setObject:forKey:` is a method of `NSMutableDictionary` More here: http://stackoverflow.com/questions/1062183/objective-c-whats-the-difference-between-objectforkey-and-valueforkey – rckoenes Oct 04 '11 at 12:12
  • Yep, not in the header file! In iOS in the document viewer in Organizer it has `setValue:forKey` as an instance method at the path: "iOS 5.0 Library>Data Management>Data Types & Collections>NSMutable Class Reference" (option double clicking on `NSMutableDictionary` in an iOS Xcode file. So, it seems that Apple's documentation is wrong, I will submit a bug. Thanks! – zaph Oct 04 '11 at 12:37
  • 1
    It seems that `setValue:forKey:` is over-ridden in `NSMutableDictionary` and has slightly different behavior: "This method adds value and key to the dictionary using setObject:forKey:, unless value is nil in which case the method instead attempts to remove key using removeObjectForKey:." Notice the difference when value is nil. So, in some cases the documentation is better than reading the header file. – zaph Oct 04 '11 at 12:59
  • Thanks!!! it was the combination of release the param inside the method (where I retain it) and changing addValue to addObject. Why should I release the webservice if I use autorelease??? – Yaniv Efraim Oct 04 '11 at 13:39
  • Sorry did not see the autorelease – rckoenes Oct 04 '11 at 13:45
2

Build with analyze. That may give some pointers.

Outside of that:

  1. You are calling alloc on AsyncWebServiceController do you own it but the code above does not release.
  2. You should be calling setObject:forKey instead of setValue:ForKey. setValue is for KVC.
bryanmac
  • 38,941
  • 11
  • 91
  • 99
2

Why don't you use the convenience constructor?

NSMutableDictionary *params = [NSMutableDictionary dictionary]; 

Then there would be no need to release it. This should solve your problem.

mskfisher
  • 3,291
  • 4
  • 35
  • 48
sElanthiraiyan
  • 6,000
  • 1
  • 31
  • 38
1

Are you releasing your webService object at some point? Also is the delegate of AsyncWebServiceController an assigned or retained property? Delegates should generally be assigned properties to avoid retain loops.

jbat100
  • 16,757
  • 4
  • 45
  • 70