themrzt
themrzt

Reputation: 23

iOS—NSDictionary has 6 keys, shows 3

For a task tracking app, I'm using an array of NSDictionaries that contain certain details about the task—-duration, etc.

    NSString *savedTaskName = addedTask.taskName;
    NSString *savedTaskAccountName = addedTask.accountName;
    NSString *savedTaskBillCode = addedTask.billCode;
    NSString *savedTaskActivityCode = addedTask.activityCode;
    NSNumber *savedTaskDuration = [NSNumber numberWithFloat:addedTask.taskDuration];
    NSString *savedTaskTimeCode = addedTask.formattedTimeString;
    NSDictionary *addedTaskData = [[NSDictionary alloc] initWithObjectsAndKeys:savedTaskName, kTaskName,
        savedTaskAccountName, kAccountName, 
        savedTaskBillCode, kBillCode, 
        savedTaskActivityCode, kActivityCode,
        savedTaskDuration, kTaskDuration,
        savedTaskTimeCode, kTimeCode, nil];

Perhaps I'm making a newb mistake, but when I go to add addedTaskData to an NSMutableArray, the array only catches the first three values and keys of the dictionary.

Have I lost my mind? Why isn't it catching all? Curiously, asking for the count of dictionary keys returns the full amount.

Upvotes: 1

Views: 140

Answers (3)

Steven Fisher
Steven Fisher

Reputation: 44876

initWithObjectsAndKeys stops when it hits a nil value. If you're getting three keys/values, then:

NSDictionary *addedTaskData = [[NSDictionary alloc] initWithObjectsAndKeys:savedTaskName, kTaskName,
    savedTaskAccountName, kAccountName, 
    savedTaskBillCode, kBillCode, 
    savedTaskActivityCode, kActivityCode, // <-- THIS IS NIL
    savedTaskDuration, kTaskDuration,
    savedTaskTimeCode, kTimeCode, nil];

You can use something like this instead:

NSDictionary *addedTaskData = [[NSDictionary alloc] initWithObjectsAndKeys:savedTaskName, kTaskName,
    savedTaskAccountName, kAccountName, 
    savedTaskBillCode, kBillCode, 
    (savedTaskActivityCode ?: [NSNull null]), kActivityCode, // Or @""
    savedTaskDuration, kTaskDuration,
    savedTaskTimeCode, kTimeCode, nil];

Anything that could be nil should be protected like this.

If you're doing a bunch of them in a row, you can declare a local null variable:

id null = [NSNull null];
NSDictionary *addedTaskData = [[NSDictionary alloc] initWithObjectsAndKeys:(savedTaskName ?: null), kTaskName,
    (savedTaskAccountName ?: null), kAccountName, 
    (savedTaskBillCode ?: null), kBillCode, 
    (savedTaskActivityCode ?: null), kActivityCode, // Or @""
    (savedTaskDuration ?: null), kTaskDuration,
    (savedTaskTimeCode ?: null), kTimeCode, nil];

Upvotes: 3

PiotrDomo
PiotrDomo

Reputation: 1045

Try to use literals like this:

NSString *savedTaskName = addedTask.taskName;
    NSString *savedTaskAccountName = addedTask.accountName;
    NSString *savedTaskBillCode = addedTask.billCode;
    NSString *savedTaskActivityCode = addedTask.activityCode;
    NSNumber *savedTaskDuration = [NSNumber numberWithFloat:addedTask.taskDuration];
    NSString *savedTaskTimeCode = addedTask.formattedTimeString;

    // Use literals and see your code doesn't crash
    NSDictionary *addedTaskData = @{kTaskName: savedTaskName, 
                                    kAccountName: savedTaskAccountName,
                                    savedTaskBillCode: savedTaskBillCode,
                                    savedTaskActivityCode: savedTaskActivityCode
                                    savedTaskDuration: savedTaskDuration
                                    savedTaskTimeCode: savedTaskTimeCode};

And see your code doesn't crash

Upvotes: 0

macshome
macshome

Reputation: 949

When not using the literal syntax there is a chance that you will run into nil termination issues. If savedTaskDuration is actually nil then it's going to chop off the rest of the NSDictionary.

Take a look with the debugger and see if you have a nil value in there somewhere. Then run the Modern Objective-C refactor tool and convert that sucker to a NSDictionary literal so that you are protected from this in the future.

For reference the Literal syntax is like this:

NSDictionary *addedTaskData = @{@"Key" : @"Value", @"AnotherKey" : @"AnotherValue"};

Upvotes: 0

Related Questions