2

I have faced an issue which I have no idea what went wrong. I have a method for saving info into NSUserDefaults and then another method for retrieving it. But when I retrieve it the error message came up:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSDictionary initWithObjects:forKeys:]: count of objects (0) differs from count of keys (19)'

My saving method is:

- (BOOL) grabAndSaveDataFromServerForPageCount: (int) pageCount
{
NSData * serverResponse = [NSData dataWithContentsOfURL:[NSURL URLWithString:[self getFetchURLStringForPageType:FindLocate_Pet withInfo:[NSString stringWithFormat:@"%i",pageCount]]]];

if (![[NSJSONSerialization JSONObjectWithData:serverResponse options:kNilOptions error:nil] objectForKey:@"Count"])
{
    //Server Error. Jump over updating process.
    serverResponse = nil;
}


if (serverResponse)
{
    //We'll re-organize the data to be display-friendly
    NSMutableDictionary * petsData = [NSJSONSerialization JSONObjectWithData:serverResponse options:kNilOptions error:nil];

    NSMutableDictionary * newDataToBeStored = [NSMutableDictionary dictionary];
    NSMutableArray * newGroupsOfIndividualPost = [NSMutableArray array];

    for (NSDictionary * individualPost in [petsData objectForKey:@"Content"])
    {
        NSMutableDictionary * newIndividualPost = [individualPost mutableCopy];

        //"ID"
        [newIndividualPost setObject:(NSString *)[individualPost objectForKey:@"ID"] forKey:@"ID"];

        //"TypeID"
        [newIndividualPost setObject:(NSString *)[individualPost objectForKey:@"TypeID"] forKey:@"TypeID"];

        //"Name"
        [newIndividualPost setObject:(NSString *)[individualPost objectForKey:@"Name"] forKey:@"Name"];

        //"GenderID"
        [newIndividualPost setObject:(NSString *)[individualPost objectForKey:@"GenderID"] forKey:@"GenderID"];

        //"Description"
        [newIndividualPost setObject:(NSString *)[individualPost objectForKey:@"Description"] forKey:@"Description"];

        //"PetsterTag"
        [newIndividualPost setObject:(NSString *)[individualPost objectForKey:@"PetsterTag"] forKey:@"PetsterTag"];

        //"Color"
        [newIndividualPost setObject:(NSString *)[individualPost objectForKey:@"Color"] forKey:@"Color"];

        //"Breed"
        [newIndividualPost setObject:(NSString *)[individualPost objectForKey:@"Breed"] forKey:@"Breed"];

        //"BreedName"
        [newIndividualPost setObject:(NSString *)[individualPost objectForKey:@"BreedName"] forKey:@"BreedName"];

        //"DOB"
        [newIndividualPost setObject:(NSString *)[individualPost objectForKey:@"DOB"] forKey:@"DOB"];

        //"DateCreated"
        [newIndividualPost setObject:(NSString *)[individualPost objectForKey:@"DateCreated"] forKey:@"DateCreated"];

        //"Lost"
        [newIndividualPost setObject:(NSString *)[individualPost objectForKey:@"Lost"] forKey:@"Lost"];

        //"LostMessage"
        [newIndividualPost setObject:(NSString *)[individualPost objectForKey:@"LostMessage"] forKey:@"LostMessage"];

        //"DateLost"
        [newIndividualPost setObject:(NSString *)[individualPost objectForKey:@"DateLost"] forKey:@"DateLost"];

        //"ImageURLCover"
        if ([(NSString *)[individualPost objectForKey:@"ImageURLCover"] length] > 0)
        {
            NSData * coverImageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:(NSString *)[individualPost objectForKey:@"ImageURLCover"]]];
            UIImage * coverImageConverted = [UIImage imageWithData:coverImageData];
            if (coverImageConverted)
            {
                [newIndividualPost setObject:coverImageConverted forKey:@"ImageURLCover"];
            }
            else
            {
                [newIndividualPost setObject:[UIImage imageNamed:@"no_image.png"] forKey:@"ImageURLCover"];
            }
        }


        //"Die"
        [newIndividualPost setObject:(NSString *)[individualPost objectForKey:@"Die"] forKey:@"Die"];

        //"DateDie"
        [newIndividualPost setObject:(NSString *)[individualPost objectForKey:@"DateDie"] forKey:@"DateDie"];

        //"Enabled"
        [newIndividualPost setObject:(NSString *)[individualPost objectForKey:@"Enabled"] forKey:@"Enabled"];



        //"MemberID"
        NSDictionary * dataToWrite = [individualPost objectForKey:@"MemberID"];

        NSMutableDictionary * newIndividualMemberDetail = [NSMutableDictionary dictionary];


        //"ID"
        [newIndividualMemberDetail setObject:(NSString *)[dataToWrite objectForKey:@"ID"] forKey:@"ID"];

        //"GenderID"
        [newIndividualMemberDetail setObject:(NSString *)[dataToWrite objectForKey:@"GenderID"] forKey:@"GenderID"];

        //"ProfileImageURL" - Incomplete URL. Would save simply as NSString
        [newIndividualMemberDetail setObject:(NSString *)[dataToWrite objectForKey:@"ProfileImageURL"] forKey:@"ProfileImageURL"];

        //"Name"
        [newIndividualMemberDetail setObject:(NSString *)[dataToWrite objectForKey:@"Name"] forKey:@"Name"];

        //"Company"
        [newIndividualMemberDetail setObject:(NSString *)[dataToWrite objectForKey:@"Company"] forKey:@"Company"];

        //"DOB"
        [newIndividualMemberDetail setObject:(NSString *)[dataToWrite objectForKey:@"DOB"] forKey:@"DOB"];

        //"NRIC"
        [newIndividualMemberDetail setObject:(NSString *)[dataToWrite objectForKey:@"NRIC"] forKey:@"NRIC"];

        //"Passport"
        [newIndividualMemberDetail setObject:(NSString *)[dataToWrite objectForKey:@"Passport"] forKey:@"NPassportRIC"];

        //"Nationality"
        [newIndividualMemberDetail setObject:(NSString *)[dataToWrite objectForKey:@"Nationality"] forKey:@"Nationality"];

        //"Username"
        [newIndividualMemberDetail setObject:(NSString *)[dataToWrite objectForKey:@"Username"] forKey:@"Username"];

        //"Password"
        [newIndividualMemberDetail setObject:(NSString *)[dataToWrite objectForKey:@"Password"] forKey:@"Password"];

        //"PhoneNo"
        [newIndividualMemberDetail setObject:(NSString *)[dataToWrite objectForKey:@"PhoneNo"] forKey:@"PhoneNo"];

        //"FaxNo"
        [newIndividualMemberDetail setObject:(NSString *)[dataToWrite objectForKey:@"FaxNo"] forKey:@"FaxNo"];

        //"MobileNo"
        [newIndividualMemberDetail setObject:(NSString *)[dataToWrite objectForKey:@"MobileNo"] forKey:@"MobileNo"];

        //"Email"
        [newIndividualMemberDetail setObject:(NSString *)[dataToWrite objectForKey:@"Email"] forKey:@"Email"];

        //"ShowFields" group of data
        NSString * jsonShowFields = [dataToWrite objectForKey:@"ShowFields"];

        NSString *jsonString = jsonShowFields;
        NSData *dataShowFields = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
        NSDictionary * showFields = [NSJSONSerialization JSONObjectWithData:dataShowFields options:0 error:nil];

        //"isName"
        if (![[showFields objectForKey:@"isName"] isKindOfClass:[NSNull class]])
        {
            [newIndividualMemberDetail setObject:(NSString *)[showFields objectForKey:@"isName"] forKey:@"isName"];
        }
        else
        {
            [newIndividualMemberDetail setObject:@"0" forKey:@"isName"];
        }


        //"isAge"
        if (![[showFields objectForKey:@"isAge"] isKindOfClass:[NSNull class]])
        {
            [newIndividualMemberDetail setObject:(NSString *)[showFields objectForKey:@"isAge"] forKey:@"isAge"];
        }
        else
        {
            [newIndividualMemberDetail setObject:@"0" forKey:@"isAge"];
        }


        //"isMobileNo"
        if (![[showFields objectForKey:@"isMobileNo"] isKindOfClass:[NSNull class]])
        {
            [newIndividualMemberDetail setObject:(NSString *)[showFields objectForKey:@"isMobileNo"] forKey:@"isMobileNo"];
        }
        else
        {
            [newIndividualMemberDetail setObject:@"0" forKey:@"isMobileNo"];
        }

        //"isContactNo"
        if (![[showFields objectForKey:@"isContactNo"] isKindOfClass:[NSNull class]])
        {
            [newIndividualMemberDetail setObject:(NSString *)[showFields objectForKey:@"isContactNo"] forKey:@"isContactNo"];
        }
        else
        {
            [newIndividualMemberDetail setObject:@"0" forKey:@"isContactNo"];
        }

        //"isPhoneNo"
        if (![[showFields objectForKey:@"isPhoneNo"] isKindOfClass:[NSNull class]])
        {
            [newIndividualMemberDetail setObject:(NSString *)[showFields objectForKey:@"isPhoneNo"] forKey:@"isPhoneNo"];
        }
        else
        {
            [newIndividualMemberDetail setObject:@"0" forKey:@"isPhoneNo"];
        }



        //Final copy
        [newIndividualPost setObject:newIndividualMemberDetail forKey:@"MemberID"];
        [newGroupsOfIndividualPost addObject:newIndividualPost];
    }


    [newDataToBeStored setObject:newGroupsOfIndividualPost forKey:@"Content"];
    [newDataToBeStored setObject:[petsData objectForKey:@"Count"] forKey:@"Count"];

    if (pageCount>1)
    {
        //Means this info grab should add into the existing backup and not to replace it.
        NSUserDefaults * storage = [NSUserDefaults standardUserDefaults];
        NSDictionary * existingData = (NSDictionary*) [NSKeyedUnarchiver unarchiveObjectWithData:[storage objectForKey:@"PetPageBackup"]];

        NSMutableDictionary * newExistingData = [existingData mutableCopy];
        [newExistingData addEntriesFromDictionary:newDataToBeStored];
        [storage setObject:[NSKeyedArchiver archivedDataWithRootObject:newExistingData] forKey:@"PetPageBackup"];

        [storage synchronize];

    }
    else
    {

        //Directly save to NSUserDefaults by packaging it to a NSData format
        NSUserDefaults * storage = [NSUserDefaults standardUserDefaults];
        [storage setObject:[NSKeyedArchiver archivedDataWithRootObject:newDataToBeStored] forKey:@"PetPageBackup"];

        [storage synchronize];
    }

    return YES;

}
else
{

    return NO;
}
}

My retrieving method is:

NSUserDefaults * storage = [NSUserDefaults standardUserDefaults];
NSDictionary * petsData = (NSDictionary*) [NSKeyedUnarchiver unarchiveObjectWithData:[storage objectForKey:@"PetPageBackup"]];

And at the last line is where the warning came up. Any idea as to why that happened?

Help!

EDIT:

This is the state of the "newDataToBeStored" variable prior to saving into NSUserDefaults:

enter image description here

Marcus
  • 548
  • 1
  • 5
  • 13
  • Please show a full stack trace. Are you saying the unarchiver raises the error? – Wain Jan 20 '15 at 07:48
  • Yes, the last line in the code above, which I attempted to unarchive the stored NSData, is where the error being raised. – Marcus Jan 20 '15 at 07:55

3 Answers3

1

Try this,

newIndividualPost = [[NSMutableDictionary alloc]initWithDictionary: individualPost];

hope this solves your problem.

iOSNoob
  • 1,420
  • 2
  • 16
  • 30
1

I think you are making a simple mistake, inside your for loop you are instantiating your dictionary as NSMutableDictionary * newIndividualPost = [individualPost mutableCopy]; means you are not creating any new fresh object but creating a copy of your individualPost dictionary and again inserting the same objects again and again. So replace your line NSMutableDictionary * newIndividualPost = [individualPost mutableCopy]; with NSMutableDictionary * newIndividualPost = [NSMutableDictionary new]; and it will work.

iHulk
  • 4,869
  • 2
  • 30
  • 39
  • `NSDictionary *d1 = @{@"key" : @"value"}; NSMutableDictionary *d2 = [d1 mutableCopy]; d2[@"key"] = d1[@"key"];` Now `d2` *still* has one key and one value. They are overwritten. Essentially, `d2` after the assignment is the same as before the assignment. So it can't be the reason of the error. – FreeNickname Jan 20 '15 at 07:44
  • @iHulk I tried your suggestion but still the same error pops up. – Marcus Jan 20 '15 at 07:45
  • @FreeNickname so what is your suggestion? – Marcus Jan 20 '15 at 07:56
  • Ok you are right @FreeNickname that it may not be the reason for error but creating a copy of object and then setting them again and again also not make any sense. – iHulk Jan 20 '15 at 08:03
  • 1
    @iHulk, I'm totally agree with you on this point :) Actually, there are plenty of ways to shorten the code in question. From the modern Obj-C syntax to `setValuesForKeysWithDictionary`, or simply creating a copy. But, unfortunately, it doesn't solve the OP's problem. – FreeNickname Jan 20 '15 at 08:19
  • @Marcus, unfortunately, I don't know, what's wrong. I would write an answer otherwise. If I find out, I will. – FreeNickname Jan 20 '15 at 08:20
  • Guys, I totally agree with you both that the copy-resetting codes are not good. I have made the changes according to @iHulk. Though the question remains as to why the error was raised. – Marcus Jan 20 '15 at 09:00
-2
 //"ImageURLCover"
if ([(NSString *)[individualPost objectForKey:@"ImageURLCover"] length] > 0)
{
   NSData * coverImageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:(NSString *)[individualPost objectForKey:@"ImageURLCover"]]];
    UIImage * coverImageConverted = [UIImage imageWithData:coverImageData];
   if (coverImageConverted)
 {
    [newIndividualPost setObject:coverImageConverted forKey:@"ImageURLCover"];
 }
  else
 {
    [newIndividualPost setObject:[UIImage imageNamed:@"no_image.png"] forKey:@"ImageURLCover"];
 }
}
Nazik
  • 8,696
  • 27
  • 77
  • 123
  • UIImage * coverImage = [UIImage imageWithCGImage: coverImageConverted.CGImage scale: coverImageConverted.scale orientation: coverImageConverted.imageOrientation]; – user5336298 Sep 15 '15 at 03:52