Code refactoring of 2 duplicate methods - iphone

Basically I have 2 methods that are similar in functionality. The only difference is the class container that are different. What I am trying to achieve is to unify these 2 methods and somehow have the container be dynamic.
here are the 2 methods:
-(NSMutableArray*) parseRequest:(NSArray*)elements {
NSMutableArray *currentStruct = [NSMutableArray array];
for (id element elemets) {
// This is where the difference is
FriendRequest *friend = [[FriendRequest alloc] init];
if(nickname != nil) {
friend.nickname = [element objectAtIndex:0];
}
[currentStruct addObject:friend];
[friend release];
}
return currentStruct;
}
Second:
-(NSMutableArray*) parseRequest:(NSArray*)elements {
NSMutableArray *currentStruct = [NSMutableArray array];
for (id element elemets) {
// This is where the difference is
Friend *friend = [[Friend alloc] init];
if(nickname != nil) {
friend.nickname = [element objectAtIndex:0];
}
[currentStruct addObject:friend];
[friend release];
}
return currentStruct;
}

Make that class a parameter.
-(NSMutableArray*) parseRequest:(NSArray*)elements withClass:(Class)friendClass {
NSMutableArray *currentStruct = [NSMutableArray array];
for (id element elemets) {
// This is where the difference is
id friend = [[friendClass alloc] init]; // <---
if(nickname != nil) {
[friend setNickname:[element objectAtIndex:0]];
}
[currentStruct addObject:friend];
[friend release];
}
return currentStruct;
}
...
-(NSMutableArray*) parseRequest:(NSArray*)elements {
return [self parseRequest:elements withClass:[Friend class]];
}

Or you can use the factory pattern:
-(NSMutableArray*) parseRequest:(NSArray*)elements factory:(SEL)factory {
NSMutableArray *currentStruct = [NSMutableArray array];
for (id element elemets) {
NSObject *friend = [self performSelector:factory];
if(nickname != nil) {
[friend performSelector:#selector(setNickname) withObject:[element objectAtIndex:0]];
}
[currentStruct addObject:friend];
}
return currentStruct;
}
-(Friend*) friendFactory {
return [[[Friend alloc] init] autorelease];
}

Related

Multiple sharedInstance called failed

In my application i have called sharedinstance multiple time in multiple method deffinition ,
Here my code,
Method 1
-(void) showActionSheet:(id)sender forEvent:(UIEvent*)event
{
if(isQuantity==YES)
{
[[WebService sharedInstance] getQuantity:^(BOOL result)
{
if(result)
{
NSLog(#"success");
NSManagedObjectContext *context = [[DataAccessLayer sharedInstance] managedObjectContext];
Quantity = [context fetchObjectsForEntityName:NSStringFromClass([GetQuantity class]) withSortColumn:nil withSortDescending:TRUE withPredicate:nil];
NSLog(#"array ->%#",Quantity);
isQuantity=NO;
}
}];
}
popoverController1 = [[TSPopoverController alloc]initWithContentViewController:tableViewController1];
popoverController1.cornerRadius = 5;
popoverController1.titleText = #"Quantity";
popoverController1.popoverBaseColor = [UIColor blackColor];
popoverController1.popoverGradient= NO;
[popoverController1 showPopoverWithTouch:event];
}
Method 2
-(void) showActionSheetw:(id)sender forEvent:(UIEvent*)events
{
if(isSize==YES)
{
[[WebService sharedInstance] getDimension:^(BOOL result)
{
if(result){
NSLog(#"success");
NSManagedObjectContext *context = [[DataAccessLayer sharedInstance] managedObjectContext];
dime = [context fetchObjectsForEntityName:NSStringFromClass([Getdimension class]) withSortColumn:nil withSortDescending:FALSE withPredicate:nil];
NSLog(#"array ->%#",dime);
}
}];
}
popoverController2 = [[TSPopoverController alloc] initWithContentViewController:tableViewController2];
popoverController2.cornerRadius = 5;
popoverController2.titleText = #"Size";
popoverController2.popoverBaseColor = [UIColor blackColor];
popoverController2.popoverGradient= NO;
// popoverController.arrowPosition = TSPopoverArrowPositionHorizontal;
[popoverController2 showPopoverWithTouch:events];
}
EDIT
- (void) getDimension:(void (^)(BOOL))handler
{
JBContainedURLConnection *connection = [[JBContainedURLConnection alloc]init ];
[connection initWithGETUrl:IP methodName:GETDIMENSION param:nil andCompletionHandler:^(JBContainedURLConnection *connection, NSError *error, NSString *urlString, NSDictionary *userInfo, NSData *response)
{
if(error)
{
NSLog(#"Error: %#", error);
handler(FALSE);
}
else
{
if(response == nil)
handler(FALSE);
else
{
NSManagedObjectContext *context = [[DataAccessLayer sharedInstance] managedObjectContext];
NSArray *existingResults = [context fetchObjectsForEntityName:NSStringFromClass([Getdimension class]) withSortColumn:nil withSortDescending:FALSE withPredicate:nil];
for (NSManagedObject *obj in existingResults)
[context deleteObject:obj];
[[DataAccessLayer sharedInstance] saveContext];
id responseData = [self DictionaryFromResponse:response];
if(responseData == nil)
handler(FALSE);
else
{
NSLog(#"Dimension Response: %#", [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding]);
NSArray *data=[responseData objectForKey:#"GetDimensionResult"];
NSLog(#"GetDimensionResult :%#",data);
for( NSDictionary *dict in data){
Getdimension *userDetails = [Getdimension newObject];
[userDetails fillFromDictionary:dict];
}
[[DataAccessLayer sharedInstance] saveContext];
handler(TRUE);
}
} }
}];
}
- (void) getQuantity:(void (^)(BOOL))handler
{
JBContainedURLConnection *connection = [[JBContainedURLConnection alloc]init ];
[connection initWithGETUrl:IP methodName:GETQUANTITY param:nil andCompletionHandler:^(JBContainedURLConnection *connection, NSError *error, NSString *urlString, NSDictionary *userInfo, NSData *response)
{
if(error)
{
NSLog(#"Error: %#", error);
handler(FALSE);
}
else
{
if(response == nil)
handler(FALSE);
else
{
NSManagedObjectContext *context = [[DataAccessLayer sharedInstance] managedObjectContext];
NSArray *existingResults = [context fetchObjectsForEntityName:NSStringFromClass([GetQuantity class]) withSortColumn:nil withSortDescending:FALSE withPredicate:nil];
for (NSManagedObject *obj in existingResults)
[context deleteObject:obj];
[[DataAccessLayer sharedInstance] saveContext];
id responseData = [self DictionaryFromResponse:response];
if(responseData == nil)
handler(FALSE);
else
{
NSLog(#"GetQuantityResult Response: %#", [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding]);
NSArray *data=[responseData objectForKey:#"GetQuantityResult"];
// NSLog(#"GetDimensionResult :%#",data);
for( NSDictionary *dict in data){
GetQuantity *userDetails = [GetQuantity newObject];
[userDetails fillFromDictionary:dict];
}
[[DataAccessLayer sharedInstance] saveContext];
handler(TRUE);
}
} }
}];
}
Instance method
+ (id)sharedInstance
{
#synchronized(self)
{
if (manager == nil)
manager = [[self alloc] init];
}
return manager;
}
-(id)init
{
if(self = [super init])
{
}
return self;
}
-(NSString *)NSStringFromDictionaryUsingJSON:(id)dictionary
{
SBJsonWriter *writer = [[SBJsonWriter alloc]init];
return [writer stringWithObject:dictionary];
}
-(id)DictionaryFromResponse:(NSData *)response
{
NSString *responseBody = [[NSString alloc] initWithData:response encoding:NSASCIIStringEncoding];
SBJsonParser *parser = [[SBJsonParser alloc]init];
return [parser objectWithString:responseBody error:nil];
}
sharedInstance only works one time,ie,. if i call any of the method first its worked,if calls other method second time app gets crashed.Can any one please help me to sort it out
I guess sharedInstance method is messy.
It should be
+ (id)sharedInstance
{
if (manager == nil)
manager = [[self alloc] init];
return manager;
}
Enjoy Programming !
Have you declared instance of your class as static,
Declare you class object as :
static ClassName *manager;
And the allocate the same object in your sharedInstance method.
The reason may be that the memory object was released but reference is still there in the memory.So when you execute the shared instance method it found a reference to !nil object and leads your application to crash.
This is singleton class feature of iOS(objective C)

I can't get the value retrieved using MGTwitterEngine(iPhone) for Twitter API 1.1

I use MGTwitterEngine(iPhone).
But I can't get the value retrieved using MGTwitterYAJLParser…
Following is described
https://dev.twitter.com/docs/api/1.1/get/search/tweets.
here is my code….
MGTwitterSearchYAJLParser.m
- (void)addValue:(id)value forKey:(NSString *)key
{
//if for some reason there are no dictionaries, exit here
if (!_dictionaries || [_dictionaries count] == 0)
{
return;
}
NSMutableDictionary *lastDictionary = [_dictionaries lastObject];
if([[lastDictionary objectForKey:key] isKindOfClass:[NSArray class]]){
NSMutableArray *array = [lastDictionary objectForKey:key];
[array addObject:value];
}else{
[lastDictionary setObject:value forKey:key];
}
#if DEBUG_PARSING
NSLog(#"parsed item: %# = %# (%#)", key, value, NSStringFromClass([value class]));
#endif
}
- (void)startDictionaryWithKey:(NSString *)key
{
#if DEBUG_PARSING
NSLog(#"status: dictionary start = %#", key);
#endif
if (!_dictionaries)
{
_dictionaries = [[NSMutableArray alloc] init];
}
if (!_dictionaryKeys)
{
_dictionaryKeys = [[NSMutableArray alloc] init];
}
//add a new dictionary to the array
NSMutableDictionary *newDictionary = [[NSMutableDictionary alloc] initWithCapacity:0];
[_dictionaries addObject:newDictionary];
[newDictionary release];
//add a key for the above dictionary to the array
[_dictionaryKeys addObject:(key) ? key : #""];
}
- (void)endDictionary
{
if (_dictionaries && _dictionaryKeys && [_dictionaries count] > 0 && [_dictionaryKeys count] > 0)
{
//is this the root dictionary?
if ([_dictionaries count] == 1)
{
//one dictionary left, so it must be the root
NSMutableDictionary *rootDictionary = [_dictionaries lastObject];
//set the request type in the root dictionary
[rootDictionary setObject:[NSNumber numberWithInt:requestType] forKey:TWITTER_SOURCE_REQUEST_TYPE];
//send the root dictionary to the super class
[self _parsedObject:rootDictionary];
[parsedObjects addObject:rootDictionary];
}
else
{
//child dictionary found
//add the child dictionary to its parent dictionary
NSMutableDictionary *parentDictionary = [_dictionaries objectAtIndex:[_dictionaries count] - 2];
[parentDictionary setObject:[_dictionaries lastObject] forKey:[_dictionaryKeys lastObject]];
}
//remove the last dictionary since it has been joined with its parent (or was the root dictionary)
//also remove the corresponding key
[_dictionaries removeLastObject];
[_dictionaryKeys removeLastObject];
}
#if DEBUG_PARSING
NSLog(#"status: dictionary end");
#endif
}
- (void)startArrayWithKey:(NSString *)key
{
arrayDepth++;
NSMutableArray *newArray = [NSMutableArray array];
[self addValue:newArray forKey:key];
#if DEBUG_PARSING
NSLog(#"status: array start = %#", key);
#endif
}
- (void)endArray
{
#if DEBUG_PARSING
NSLog(#"status: array end");
#endif
arrayDepth--;
[self clearCurrentKey];
}
- (void)dealloc
{
[_dictionaries release];
[_dictionaryKeys release];
[_status release];
[super dealloc];
}

App crashes if Last Name in Contacts is empty for iOS 5 +

I am trying to retrieve contacts from address book & display it in table view with indexed list same as Contacts app in iOS. I am sorting contacts on LAST NAME. If last name is empty then my app crashes. Here is my code
- (void)getAddressBookDataForUpdateRequest:(BOOL)isUpdateRequest {
if (self.peopleArray == nil) {
NSMutableArray *temp = [[NSMutableArray alloc]init];
self.peopleArray = temp;
}
if (self.batchUserArray == nil) {
NSMutableArray *temp = [[NSMutableArray alloc]init];
self.batchUserArray = temp;
}
row = [[NSMutableDictionary alloc] init];
words = [[NSMutableArray alloc]init];
ABAddressBookRef addressBook=ABAddressBookCreate();
CFArrayRef cfPeople=ABAddressBookCopyArrayOfAllPeople(addressBook);
CFMutableArrayRef cfPeopleMutable=CFArrayCreateMutableCopy(kCFAllocatorDefault, CFArrayGetCount(cfPeople), cfPeople);
CFArraySortValues(cfPeopleMutable, CFRangeMake(0, CFArrayGetCount(cfPeopleMutable)), (CFComparatorFunction)ABPersonComparePeopleByName, (void *)ABPersonGetSortOrdering());
NSArray *tempPeople=(__bridge NSArray *)cfPeopleMutable;
APP_DELGATE.people = [NSArray arrayWithArray:tempPeople];
peopleCount = [APP_DELGATE.people count];
lastCharacter = #"A";
if (peopleCount >0) {
int noOfRec = 0;
for (int i=0; i<peopleCount; i++) {
ABRecordRef record = (__bridge ABRecordRef)[APP_DELGATE.people objectAtIndex:i];
// Convert ABRecordRef to UserContactInfo object
UserContactInfo *user = [self getUserContactInfoFromABRecordRef:record isForUpdate:isUpdateRequest];
if (user != nil) {
currentCharacter = [[user.lastName substringToIndex:1]uppercaseString];
NSLog(#"Last: %# :: Current:- %#",lastCharacter,currentCharacter);
if ([currentCharacter isEqualToString:lastCharacter]) {
[words addObject:user];
}
else {
row = nil;
row = [[NSMutableDictionary alloc] init];
[row setValue:lastCharacter forKey:#"sectionTitle"];
[row setValue:words forKey:#"sectionRows"];
[self.peopleArray addObject:row];
[self.batchUserArray addObject:row];
NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:[self.batchUserArray mutableCopy],BATCH_DONE_KEY,[NSNumber numberWithBool:isUpdateRequest],#"isUpdateRequest", nil];
[[NSNotificationCenter defaultCenter] postNotificationName:BATCH_DONE_NOTIFICATION object:self userInfo:dic];
[self.batchUserArray removeAllObjects];
words = nil;
words = [[NSMutableArray alloc]init];
[words addObject:user];
NSLog(#"ASCII Value of %# = %d :: Last Char %# = %d",currentCharacter,[currentCharacter characterAtIndex:0],lastCharacter,[lastCharacter characterAtIndex:0]);
int lastCharAsciiValue = [lastCharacter characterAtIndex:0];
int currentCharAsciiValue = [currentCharacter characterAtIndex:0];
while ((lastCharAsciiValue +1) < (currentCharAsciiValue)) {
row = nil;
row = [[NSMutableDictionary alloc] init];
lastCharAsciiValue ++;
lastCharacter = [NSString stringWithFormat:#"%c",lastCharAsciiValue];
[row setValue:lastCharacter forKey:#"sectionTitle"];
[row setValue:[[NSMutableArray alloc]init] forKey:#"sectionRows"];
[self.peopleArray addObject:row];
[self.batchUserArray addObject:row];
}
}
lastCharacter = currentCharacter;
noOfRec++;
}
}
// For last char "z"
row = nil;
row = [[NSMutableDictionary alloc] init];
[row setValue:lastCharacter forKey:#"sectionTitle"];
[row setValue:words forKey:#"sectionRows"];
[self.peopleArray addObject:row];
[self.batchUserArray addObject:row];
NSLog(#"total rec count=%d",self.peopleArray.count);
NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:self.batchUserArray,BATCH_DONE_KEY,[NSNumber numberWithBool:isUpdateRequest],#"isUpdateRequest", nil];
[[NSNotificationCenter defaultCenter] postNotificationName:BATCH_DONE_NOTIFICATION object:self userInfo:dic];
[self.batchUserArray removeAllObjects];
[[NSNotificationCenter defaultCenter]postNotificationName:TASK_DONE_NOTIFICATION object:self];
APP_DELGATE.allUsersArray = self.peopleArray;
}
else {
[[NSNotificationCenter defaultCenter]postNotificationName:NO_CONTACTS_AVAILABLE_NOTIFICATION object:nil];
}
CFRelease(addressBook);
}
If LAST NAME is EMPTY app crashes at
if ([currentCharacter isEqualToString:lastCharacter]) {
[words addObject:user];
}
How can I check if Last Name is empty & display it in UNNAMED section of indexed list.
Any kind of help is appreciated. Thanks in advance
Please Use
if (user.lastName != nil) {
Rather
if (user != nil) {
Full Code
- (void)getAddressBookDataForUpdateRequest:(BOOL)isUpdateRequest {
if (self.peopleArray == nil) {
NSMutableArray *temp = [[NSMutableArray alloc]init];
self.peopleArray = temp;
}
if (self.batchUserArray == nil) {
NSMutableArray *temp = [[NSMutableArray alloc]init];
self.batchUserArray = temp;
}
row = [[NSMutableDictionary alloc] init];
words = [[NSMutableArray alloc]init];
ABAddressBookRef addressBook=ABAddressBookCreate();
CFArrayRef cfPeople=ABAddressBookCopyArrayOfAllPeople(addressBook);
CFMutableArrayRef cfPeopleMutable=CFArrayCreateMutableCopy(kCFAllocatorDefault, CFArrayGetCount(cfPeople), cfPeople);
CFArraySortValues(cfPeopleMutable, CFRangeMake(0, CFArrayGetCount(cfPeopleMutable)), (CFComparatorFunction)ABPersonComparePeopleByName, (void *)ABPersonGetSortOrdering());
NSArray *tempPeople=(__bridge NSArray *)cfPeopleMutable;
APP_DELGATE.people = [NSArray arrayWithArray:tempPeople];
peopleCount = [APP_DELGATE.people count];
lastCharacter = #"A";
if (peopleCount >0) {
int noOfRec = 0;
for (int i=0; i<peopleCount; i++) {
ABRecordRef record = (__bridge ABRecordRef)[APP_DELGATE.people objectAtIndex:i];
// Convert ABRecordRef to UserContactInfo object
UserContactInfo *user = [self getUserContactInfoFromABRecordRef:record isForUpdate:isUpdateRequest];
if (user.lastName != nil) {
currentCharacter = [[user.lastName substringToIndex:1]uppercaseString];
NSLog(#"Last: %# :: Current:- %#",lastCharacter,currentCharacter);
if ([currentCharacter isEqualToString:lastCharacter]) {
[words addObject:user];
}
else {
row = nil;
row = [[NSMutableDictionary alloc] init];
[row setValue:lastCharacter forKey:#"sectionTitle"];
[row setValue:words forKey:#"sectionRows"];
[self.peopleArray addObject:row];
[self.batchUserArray addObject:row];
NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:[self.batchUserArray mutableCopy],BATCH_DONE_KEY,[NSNumber numberWithBool:isUpdateRequest],#"isUpdateRequest", nil];
[[NSNotificationCenter defaultCenter] postNotificationName:BATCH_DONE_NOTIFICATION object:self userInfo:dic];
[self.batchUserArray removeAllObjects];
words = nil;
words = [[NSMutableArray alloc]init];
[words addObject:user];
NSLog(#"ASCII Value of %# = %d :: Last Char %# = %d",currentCharacter,[currentCharacter characterAtIndex:0],lastCharacter,[lastCharacter characterAtIndex:0]);
int lastCharAsciiValue = [lastCharacter characterAtIndex:0];
int currentCharAsciiValue = [currentCharacter characterAtIndex:0];
while ((lastCharAsciiValue +1) < (currentCharAsciiValue)) {
row = nil;
row = [[NSMutableDictionary alloc] init];
lastCharAsciiValue ++;
lastCharacter = [NSString stringWithFormat:#"%c",lastCharAsciiValue];
[row setValue:lastCharacter forKey:#"sectionTitle"];
[row setValue:[[NSMutableArray alloc]init] forKey:#"sectionRows"];
[self.peopleArray addObject:row];
[self.batchUserArray addObject:row];
}
}
lastCharacter = currentCharacter;
noOfRec++;
}
}
// For last char "z"
row = nil;
row = [[NSMutableDictionary alloc] init];
[row setValue:lastCharacter forKey:#"sectionTitle"];
[row setValue:words forKey:#"sectionRows"];
[self.peopleArray addObject:row];
[self.batchUserArray addObject:row];
NSLog(#"total rec count=%d",self.peopleArray.count);
NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:self.batchUserArray,BATCH_DONE_KEY,[NSNumber numberWithBool:isUpdateRequest],#"isUpdateRequest", nil];
[[NSNotificationCenter defaultCenter] postNotificationName:BATCH_DONE_NOTIFICATION object:self userInfo:dic];
[self.batchUserArray removeAllObjects];
[[NSNotificationCenter defaultCenter]postNotificationName:TASK_DONE_NOTIFICATION object:self];
APP_DELGATE.allUsersArray = self.peopleArray;
}
else {
[[NSNotificationCenter defaultCenter]postNotificationName:NO_CONTACTS_AVAILABLE_NOTIFICATION object:nil];
}
CFRelease(addressBook);
}

UISearchBar - search a NSDictionary of Arrays of Objects

I'm trying to insert a search bar in a tableview, that is loaded with information from a NSDictionary of Arrays. Each Array holds and object. Each object has several properties, such as Name or Address.
I've implemented the methods of NSSearchBar, but the code corresponding to the search it self, that i have working on another project where the Arrays have strings only, is not working, and I can't get to thr problem.
Here's the code:
'indiceLateral' is a Array with the alphabet;
'partners' is a NSDictionary;
'RLPartnersClass' is my class of Partners, each one with the properties (name, address, ...).
-(void)handleSearchForTerm:(NSString *)searchTerm {
NSMutableArray *sectionsToRemove = [[NSMutableArray alloc] init];
[self resetSearch];
for (NSString *key in self.indiceLateral) {
NSMutableArray *array = [partners valueForKey:key];
NSMutableArray *toRemove = [[NSMutableArray alloc] init];
for (NSString *name in array) {
if ([name rangeOfString:searchTerm options:NSCaseInsensitiveSearch].location == NSNotFound)
[toRemove addObject:name];
}
if ([array count] == [toRemove count])
[sectionsToRemove addObject:key];
[array removeObjectsInArray:toRemove];
[toRemove release];
}
[self.indiceLateral removeObjectsInArray:sectionsToRemove];
[sectionsToRemove release];
[theTable reloadData];
}
Can anyone help me please?
Thanks,
Rui Lopes
I've done it.
Example:
-(void)handleSearchForTerm:(NSString *)searchTerm {
NSMutableDictionary *finalDict = [NSMutableDictionary new];
NSString *currentLetter = [[NSString alloc] init];
for (int i=0; i<[indiceLateral count]; i++) {
NSMutableArray *elementsToDict = [[[NSMutableArray alloc] init] autorelease];
currentLetter = [indiceLateral objectAtIndex:i];
NSArray *partnersForKey = [[NSArray alloc] initWithArray:[partnersCopy objectForKey:[indiceLateral objectAtIndex:i]]];
for (int j=0; j<[partnersForKey count]; j++) {
RLNames *partnerInKey = [partnersForKey objectAtIndex:j];
NSRange titleResultsRange = [partnerInKey.clientName rangeOfString:searchTerm options:NSDiacriticInsensitiveSearch | NSCaseInsensitiveSearch];
if (titleResultsRange.length > 0){
NSLog(#"found: %#", partnerInKey.clienteCity
[elementsToDict addObject:partnerInKey];
}
}
[finalDict setValue:elementsToDict forKey:currentLetter];
}
NSMutableDictionary *finalResultDict = [finalDict mutableDeepCopy];
self.partners = finalResultDict;
[finalResultDict release];
[theTable reloadData];
}

Memory leaks in NSMutableDictionary

My coding contains a memory leak, and somehow I can't find the leak.
Leaks points me in the direction of the way I create "ReportDetailItems"
e.g. areaContainer = [[[ReportDetailItem alloc] init] autorelease];
I've been looking at this for hours and I am at a total loss, the objects reported leaking are "ReportDetailItem", and the NSMutableDictionary contained in those objects.
Please advice.
------[ReportDetailItem.h
#interface ReportDetailItem : NSObject
{
NSNumber *total;
NSMutableDictionary *items;
}
#property (nonatomic, retain) NSNumber *total;
#property (nonatomic, retain) NSMutableDictionary *items;
- (NSString *)description;
#end
------[ReportDetailItem.m
#synthesize items, total;
- (id)init {
if (self = [super init]) {
self.items = [NSMutableDictionary dictionaryWithCapacity:0];
DLog("Alloc: %d", [items retainCount]);
}
return self;
}
- (NSString *)description {
return #"ReportDetailItem";
}
- (void)release {
[super release];
}
- (void)dealloc {
[self.items release];
[self.total release];
items = nil;
total = nil;
[super dealloc];
}
#end
------[Leaking code
NSError *error;
NSArray *data = [self.managedObjectContext executeFetchRequest:request error:&error];
if (data == nil || [data count] == 0) {
DLog(#"No data.")
} else {
for (int i=0; i < [data count]; i++) {
TaskEntity *task = [data objectAtIndex:i];
NSString *areaKey = task.activity.project.area.title.text;
NSString *projectKey = task.activity.project.title.text;
NSString *activityKey = task.activity.title.text;
ReportDetailItem *areaContainer;
if (![dataSource objectForKey:areaKey]) {
areaContainer = [[[ReportDetailItem alloc] init] autorelease];
} else {
areaContainer = [dataSource objectForKey:areaKey];
}
areaContainer.total = [NSNumber numberWithInt:([task.seconds intValue] + [areaContainer.total intValue])];
[dataSource setObject:areaContainer forKey:areaKey];
ReportDetailItem *projectContainer;
if (![areaContainer.items objectForKey:projectKey]) {
projectContainer = [[[ReportDetailItem alloc] init] autorelease];
} else {
projectContainer = [areaContainer.items objectForKey:projectKey];
}
projectContainer.total = [NSNumber numberWithInt:([task.seconds intValue] + [projectContainer.total intValue])];
[areaContainer.items setObject:projectContainer forKey:projectKey];
ReportDetailItem *activityContainer;
if (![projectContainer.items objectForKey:activityKey]) {
activityContainer = [[[ReportDetailItem alloc] init] autorelease];
} else {
activityContainer = [projectContainer.items objectForKey:activityKey];
}
activityContainer.total = [NSNumber numberWithInt:([task.seconds intValue] + [activityContainer.total intValue])];
[projectContainer.items setObject:activityContainer forKey:activityKey];
}
}
I found it, the leak was located in the way I allocated the "dataSource"
---[Leak
- (void)viewDidLoad {
[super viewDidLoad];
self.dataSource = [[NSMutableDictionary alloc] init];
[self fetchData];
}
---[No leak
- (void)viewDidLoad {
[super viewDidLoad];
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
self.dataSource = dict;
[dict release];
[self fetchData];
}
I'm pretty skeptic about the two ways u assign pointers to the ReportDetailItem. Why are you trying to autorelease the object in the first place? If not try this
ReportDetailItem *projectContainer;
if (![areaContainer.items objectForKey:projectKey]) {
projectContainer = [[ReportDetailItem alloc] init];
} else {
projectContainer = [[areaContainer.items objectForKey:projectKey] retain];
}
projectContainer.total = [NSNumber numberWithInt:([task.seconds intValue] + [projectContainer.total intValue])];
[areaContainer.items setObject:projectContainer forKey:projectKey];
if(projectContainer) {
[projectContainer release];
projectContainer = nil;
}