NSMutableArray not being saved - objective-c

I'm trying to insert objects (NSNumbers) into an NSMutable array, but when I check it, the objectAtElement always returns 0.
NSNumber *indexNum = [NSNumber numberWithInt:indexInt];
[last100 insertObject:indexNum atIndex:prevCount];
NSLog(#"Entry #%d : %d", prevCount, (int)[last100 objectAtIndex:prevCount]);
prevCount++;
indexInt is coming in through the method, I already checked it and its valid. indexNum has also been checked and matches indexInt. The problem is NSLog(#"Entry #%d : %d", prevCount, (int)[last100 objectAtIndex:prevCount]); which always returns
2012-01-08 14:08:11.551 ThoughtSpreader[20746:fb03] Entry #9 : 0 The entry number will change, but the 0 is always there.
Oh, I also checked [last100 count] after every time I insert something new into it, and it always returns 0, so I believe its a problem with how I'm inserting something into the NSMutable array

If your count always returns 0 the likelihood is you haven't actually instantiated your NSMutableArray.
NSMutableArray *array = [NSMutableArray array];
[array addObject:[NSNumber numberWithInt:1]];
NSLog(#"%lu", [array count]); // Count => 1
//-------
array = nil;
[array addObject:[NSNumber numberWithInt:1]]; // Calling methods on nil is a no-op
NSLog(#"%lu", [array count]); // Count => 0
Updated %d to %lu thanks to #markhunte - it's hard to remember the finer details without testing it

Use
[[last100 objectAtIndex:prevCount] intValue]
instead of
(int)[last100 objectAtIndex:prevCount] - this explict conversion won't work.
[... intValue] is the message of NSNUmber which converts it to int.

NSNumber is an object, you can't just cast it to an int. Use intValue:
NSLog(#"Entry #%d : %d", prevCount, [[last100 objectAtIndex:prevCount] intValue]);

Related

why does __block not adding values to array

I am enumerating ranges inside a block and storing the values inside an array. I expected using __block should store the values inside block into array?
__block NSMutableArray *array;
[indexSet enumerateRangesUsingBlock:^(NSRange range,BOOL * stop ) {
[array addObject:#(range.location)];
[array addObject:#(range.length)];
NSLog(#"location is %d, %ld", range.location, range.length);
}];
NSLog(#"%#",array );
But this result in
location is 4, 2 location is 8, 2 location is 14, 2
and for array
(null)
I expected array to be filled with values.
You have to initialize it, a just declared array is nil:
__block NSMutableArray *array = [NSMutableArray array];
(The Swift compiler would throw an error ... 😉 )
__block NSMutableArray *array = [NSMutableArray array];
It does work fine.
However when I declared array as property then block became redundant.

valueForKeyPath: #"#max.self" not work when number is 100

NSArray *vals = {100,100,50,50,50}
maximumValue = [[vals valueForKeyPath: #"#max.self"] intValue];
Returns
maximumValue : 50
You probably have an array of strings. When compared as strings, "50" is greater than "100" because 5 comes after 1. You need to convert to integers first, then take the max.
Unfortunately, ObjC doesn't have the map function, so you need to do it manually.
NSMutableArray *intArray = [NSMutableArray array];
for (NSString *val in vals) {
[intArray addObject:#(val intValue)];
}
maximumValue = [[intArray valueForKeyPath: #"#max.self"] intValue];
Edit
Based on Sulthan's suggestion, you can also do the following:
NSArray *a = #[ #"50", #"100" ];
NSLog(#"%#", [[a valueForKeyPath:#"intValue"] valueForKeyPath:#"#max.self"]);
The first call to valueForKeyPath:#"intValue" gives an array of NSNumbers. At this point, the #max.self key-path gives the expected value, as a numeric comparison is made between elements.
NSArray *vals = #[#100,#100,#50,#50,#50];
NSLog(#"%d",[[vals valueForKeyPath: #"#max.self"] intValue]

How to count items in plist

I got a question how i can count items in my plist file. I tried:
NSString *bundlePathofPlist = [[NSBundle mainBundle]pathForResource:#"Mything" ofType:#"plist"];
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:bundlePathofPlist];
NSArray *dataFromPlist = [dict valueForKey:#"some"];
for(int i =0;i<[dataFromPlist count];i++)
{
//NSLog(#"%#",[dataFromPlist objectAtIndex:i]);
[self setTableData:[dataFromPlist count]];
}
NSLog(#"%#", tableData);
But on this line an error appears:
[self setTableData:[dataFromPlist count]];
Implicit conversion of 'NSUInteger' (aka 'unsigned int') to 'NSArray *' is disallowed with ARC
and warning:
Incompatible integer to pointer conversion sending 'NSUInteger' (aka 'unsigned int') to parameter of type 'NSArray *';
It looks like your setTableData takes an NSArray instance. You need to prepare an array upfront in a loop, and then set it once, like this:
NSMutableArray *data = [NSMutableArray array];
for(int i =0;i<[dataFromPlist count];i++)
{
//NSLog(#"%#",[dataFromPlist objectAtIndex:i]);
[data addObject:[NSNumber numberWithInt:[[dataFromPlist objectAtIndex:i] count]]];
}
[self setTableData:data];
This assumes that your setTableData method expects an array of NSNumber instances wrapping ints.
The problem is you're using [dataFromPlist count] inside your for loop, which makes no sense. You probably meant [dataFromPlist objectAtIndex:i].
Or, more idiomatically,
for (NSArray *elt in dataFromPlist) {
[self setTableData:elt];
}
Although I do have to wonder why you're calling -setTableData: over and over with different elements.

Application crashes when using NSMutableString

in a header file I defined
NSMutableArray *numbers;
In the implementation I initialize this array first in the init method
numbers = [[NSMutableArray alloc] init];
I add strings to this array
[numbers insertObject:number atIndex:[numbers count]];
But when I access the array like this in another method
NSLog(#"%#", [numbers count]);
the application crashes. Any idea why this happens?
You are wrong here -
NSLog(#"%#", [numbers count]);
Array count is an integer value. Use %d instead of %# to print integer.
NSLog(#"%d", [numbers count]);
Your format string doesn't match the type of the second parameter.
[numbers count] returns an integer, not an object.
The " %#" format specifier indicates that the corresponding argument is an object, and that object will be sent a -description message. The string returned from that message expression will be inserted in place of the "%#". Your app crashes because it tries to send a message to an invalid receiver.

NSMutableArray writing issue?

I read in a CSV file and now I am parsing the string and writing the element to a 2D NSMutableArray.
AS I am writing the elements to the 2D array the NSLog outputs the expected element.
But when I am done parsing and writing the whole file to the 2D array, the NSLog shows the last element at each row for each column at that row.
--as if every element in the row was replaced.
??? why, thank you in advanced...
for (int i = 1; i < iM; i++) {//was a 1 to pass over the header
//get the row and break up into columns
nsmarrDummy = [NSMutableArray arrayWithArray:[[nsmarrRow objectAtIndex: i] componentsSeparatedByString: nsstrColParse]];
//write each item to the proper column in the 2d array at the given row
for (int j = 0; j < iN; j++) {//<<--
[[nsmarrData objectAtIndex:j] replaceObjectAtIndex:i-1 withObject: [nsmarrDummy objectAtIndex:j]];
NSLog(#"i:%d j:%d item:%#", i, j, [[nsmarrData objectAtIndex:j] objectAtIndex:i-1]);
}
}
//all the following are the same value, but doing the NSLog as it was writing was correct.
NSLog(#"FINAL: i:%d j:%d item:%#", 0, 4, [[nsmarrData objectAtIndex:4] objectAtIndex:0]);
NSLog(#"FINAL: i:%d j:%d item:%#", 0, 5, [[nsmarrData objectAtIndex:5] objectAtIndex:0]);
NSLog(#"FINAL: i:%d j:%d item:%#", 0, 6, [[nsmarrData objectAtIndex:6] objectAtIndex:0]);
That is some serious thrash I'm seeing in your example, aside from the problem lurking there. Cocoa can do so much of the work for you. It's got thunder appeal. Let it be on your side:
// Get the contents of the file.
// Real apps never ignore their errors or potential nil results.
// For this example, assume path exists.
NSString *fileContents = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:NULL];
NSMutableArray *nsmarrData = [NSMutableArray array];
NSArray *lines = [fileContents componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
for (NSString *line in lines)
{
// Guard against the last line being only a return.
if ([line length] > 0)
{
NSArray *tokens = [line componentsSeparatedByString:#","]; // assuming no space as well
[nsmarrData addObject:tokens];
}
}
This produces a NSMutableArray filled with NSArrays for each row. Need a NSMutableArray for each row? No problem. Instead of:
[nsmarrData addObject:tokens];
you can use:
[nsmarrData addObject:[NSMutableArray arrayWithArray:tokens]];
Of course, none of this accounts for varying numbers of items on a line; you'll need to beware of that later.
Good luck to you in your endeavors.