Terminating program with error "object 1 beyond bounds" - ios

Terminating program with the error index 1 beyond bounds. Actually I am trying to parse the columns from csv file. I found few questions on stackoverflow similar to this issue but none of the answer is helpful
NSMutableArray *lines = [sourceFileString componentsSeparatedByString:#"\n"].mutableCopy;
NSArray *keys = [lines.firstObject componentsSeparatedByString:#","];
NSMutableArray *result = [NSMutableArray array];
for (int i = 0; i<keys.count; i++) {
[result addObject:#{keys[i] : [NSMutableArray array]}];
}
[lines removeObjectAtIndex:0];
for (NSString *line in lines) {
// Get a list of all values
NSArray *columns = [line componentsSeparatedByString:#","];
// Insert the value into the array of the proper key
NSMutableArray *values = result[1][keys[1]];
[values addObject:columns[1]];
NSLog(#"values %#",values);
}

check that your array contains empty indexes, the reason is you are check ing with the help of [line componentsSeparatedByString:#","] if any index is empty it surely crash , so in here in before checking remove the empty index from array using following concept
for (int j=[lines count]-1; j>=0; j--)
if ([[lines objectAtIndex:j] length] == 0)
[lines removeObjectAtIndex:j];

Related

Put multiple arrays in Dictionary

I am parsing a CSV file multiple times with for loop, here I need to store these arrays one by one dictionary. There are very less questions in stack about adding NSArray to NSDictionary. I am parsing CSV with below code but I strucked at storing in NSDictionary, The program is terminating and showing warning at assigning string to dictionary
for (i=0; i<=57; i++) {
NSString *keysString = [csvArray objectAtIndex:i];
NSArray *keysArray = [keysString componentsSeparatedByString:#","];
NSLog(#"Serail No %d %#",i,keysArray);
NSString *string = [NSString stringWithFormat:#"%d", i];
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithObjects: keysArray forKeys: string];
}
NSMutableDictionary *dict = [[NSMutableDictionary alloc]init];
for (i=0; i<=57; i++) {
NSString *keysString = [csvArray objectAtIndex:i];
NSArray *keysArray = [keysString componentsSeparatedByString:#","];
NSString *key = [NSString stringWithFormat:#"serial%d",i];
[dict setObject:keysArray forKey:key];
}
To get back data from dictionary,
NSArray *array = [dict valueForKey:#"serial24"];//to get array 24.
If I understand you correctly, you want to add the arrays to a dictionary, with the key being the string value of integer i ? What you need to do is allocate the dictionary outside your loop -
NSMutableDictionary *dict=[NSMutableDictionary new];
for (i=0; i<=57; i++) {
NSString *keysString = [csvArray objectAtIndex:i];
NSArray *keysArray = [keysString componentsSeparatedByString:#","];
NSLog(#"Serial No %d %#",i,keysArray);
NSString *string = [NSString stringWithFormat:#"%d", i];
dict[string]=keysArray;
}
I am not sure why you would want to do this, because this is basically an array. You could simply do -
NSMutableArray *outputArray=[NSMutableArray new];
for (NSString *keysString in csvArray) {
NSArray *keysArray = [keysString componentsSeparatedByString:#","];
[outputArray addObject:keysArray];
}

How to save two Arrays in two dimensional Array?

I am new at iOS Dev. I want to save two different arrays (array1 & array2) in 2 dimensional array. I know how to save data directly in two dimensional array but can't by save two different arrays in one.
NSString* path = [[NSBundle mainBundle] pathForResource:#"Aasvogel" ofType:#"txt"];
NSString* content = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:NULL];
NSArray* foo = [content componentsSeparatedByString: #","];
NSMutableArray *array1 = #[], *array2 = #[];
for ( int i = 0; i < [foo count]; i++ )
{
NSString* day = foo[i];
if ( i % 2 == 0 ) { [array1 addObject:day];}
else { [array2 addObject:day];}
}
// and here i have populated two arrays (array1 and array2)
// Now i want to save these arraya in below two dimensional array (dataArray) atIndex:0 and at Index:1
NSMutableArray *dataArray = [[NSMutableArray alloc] initWithCapacity: 2];
[dataArray addObject:[NSMutableArray arrayWithObjects:#"e",
#"el",
#"ale",
#"vela",
#"gavel",nil] atIndex:0];
[dataArray addObject:[NSMutableArray arrayWithObjects:#"Represents 50 in Roman numeral",
#"Building Wing",
#"Pub Brew",
#"Thin Parchment or membranes",
#"chairperson's hammer",nil] atIndex:1];
I have recently implemented 2D array into my application. Please check below code which is available at 2DArray
int capacity;
#property (nonatomic, strong) NSMutableArray *outerArray;
#define kCRL2DArrayEmptyKey #"kCRL2DArrayEmptyKey"
- (id) initWithRows:(int)x columns:(int)y
{
if (self = [super init])
{
capacity = y;
self.outerArray = [NSMutableArray array];
for (int i = 0; i < x; i++) {
NSMutableArray *innerArray = [NSMutableArray array];
for (int j = 0; j < y; j++) {
[innerArray addObject:kCRL2DArrayEmptyKey];
}
[self.outerArray addObject:innerArray];
}
}
return self;
}
you can try this
NSArray * firstArray, *secondArray;
NSArray * mainArray= [[NSArray alloc]initWithObjects: firstArray, secondArray, nil];
I am not sure about 2-dimensional array in iOS but if I were you I would be saved the two arrays within a dictionary such as
NSMutableDictionary *dict = [[NSMutableDictionary alloc]init];
[dict setvalue:yourArray forKey:#"FirstArray"];
[dict setvalue:yourSecondArray forKey:#"SecondArray"];
And Use it accordingly.
There’s no such thing as a two (or more) dimensional NSArray. If you genuinely need an n-dimensional array object in iOS or OS X, you can of course roll your own, or you could instead create an NSArray of NSArray instances (which are columns and which are rows is entirely up to you). In that case, you could e.g. add items by doing
[[outerArray objectAtIndex:0] addObject:#"Foo"];
[[outerArray objectAtIndex:1] addObject:#"Bar"];
That said, for the problem you are tackling, it looks to me as if an NSDictionary might be more appropriate, e.g. with keys #"e", #"el" and values #"Represents 50 in Roman numerals", #"Building Wing".
If your concern is that the keys of NSDictionary are not held in sorted order, you can always extract the keys as an array and sort them. Or, if the keys change regularly, you might want to use a more sophisticated approach (e.g. keeping a separate sorted array of keys and inserting them into the right place when adding to the NSDictionary).
Also, you know that in modern Objective-C you can write e.g.
#[ #"a", #"b", #"c" ]
or
#{ #"a": #1, #"b": 2 }
rather than the very verbose forms you're using above?
this is how u add anything in a 2d array i.e an Array of arrays in objective-c
NSMutableArray *array 1 = [[NSMutableArray alloc]init];
NSMutableArray *array 2;
for(int col = 0;col <5;col++){
array2 = [[NSMutableArray alloc]init];
for(int row = 0;row<5;row++){
[array2 addObject:myItems];
}
[array1 addObject:array2];
}
hope this helps
use for loop to generate 2d array from 2 different array,
follow this stracture
int i, j;
for(i = 0; i < nrows; i++)
{
for(j = 0; j < ncolumns; j++)
array[i][j] = 0;
}
}
May be it will help you

NSMutableArray with int values from 1 to 100

This should be dead easy, but somehow it doesn't want to work for me. Using iOS 7 and XCode 5.
All I'm trying to do is create an array with values from 1 to 100.
NSMutableArray *array;
for (int i = 0; i < 100; i++)
{
[array addObject:i];
}
This doesn't work. I get a "Implicit conversion of 'int' to 'id' is disallowed with ARC.
I get it, I can't add primitive types to an NSMutableArray.
[array addObject:#i];
This doesn't work either. I get a "unexpected '#' in program"
[array addObject:[NSNumber numberWithInt:i]];
[array addObject:[NSNumber numberWithInteger:i]];
(either case) This "works" (compiles) but it really doesn't "work". The problem with this is that the value from NSNumber is really not a 1-100. What I get for each row is "147212864", 147212832", "147212840"...not what I want.
Lastly:
for (NSNumber *i = 0; i < [NSNumber numberWithInteger:100]; i++)
{
[array addObject:i];
}
This also doesn't compile. I get an error on the i++. "Arithmetic on pointer to interface 'NSNumber', which is not a constant size for this architecture and platform"
Any suggestions on how to do this extremely simple thing on obj-c?
Either one of these should work:
NSMutableArray *array = [NSMutableArray array];
for (int i = 0; i < 100; i++) {
[array addObject:#(i)];
}
or
NSMutableArray *array = [NSMutableArray array];
for (int i = 0; i < 100; i++) {
[array addObject:[NSNumber numberWithInt:i]];
}
Here are the reasons why your code snippets did not work:
[array addObject:i] - You cannot add primitives to Cocoa collections
[array addObject:#i] - You forgot to enclose the expression i in parentheses
NSNumber *i = 0; i < [NSNumber numberWithInteger:100]; i++ - You cannot increment NSNumber without "unwrapping" its value first.
If memory serves, I think you're simply missing parenthesis around the NSNumber shorthand expression.
NSMutableArray *array = [[NSMutableArray alloc] init];
for (NSUInteger i = 0; i < 100; i++)
{
[array addObject:#(i)];
}
Minimally, #i should be #(i) as described here. You are also forgetting to allocate and initialise your array
NSMutableArray *array = [[NSMutableArray alloc] init];
for (int i = 0; i < 100; i++) {
[array addObject:#(i)];
}
And since you are getting: "147212864", 147212832", "147212840"...not what I want., I think you are probably printing out your information wrongly or because the array is unallocated, that's simply garbage. Can you show us how you are outputting?
NSMutableArray *array = [[NSMutableArray alloc] init];
NSNumber *myNum;
for (int i = 0; i < 100; i++) {
myNum = [[NSNumber alloc]initWithInt:i];
[array addObject:myNum];
}
NSLog(#"%#", array); // 1 - 99 as expected
Worked for me :)
Just saying: Turn on all reasonable warnings in your Xcode project. Then read what the warnings are saying and do something about them. When you write something like
for (NSNumber *i = 0; i < [NSNumber numberWithInteger:100]; i++)
What does a for loop do? An object is in the end a pointer. So you initalise i to nil. Then you compare a pointer with a random pointer: [NSNumber numberWithInteger:100] returns a pointer to an object which could be anywhere in memory, and you compare pointers. Next the i++: No, you can't increment a pointer to an NSNumber. It doesn't make sense.

Trying to make NSMutableArray of dictionaries(logical mistake)

I am trying to make an Array of dictionaries
but something going wrong I have a mistake (logical) in my code and I can't figure out it for 2 hours, (I am new to iOS development , so maybe some experienced eye can see it fast?)
here is my code
Edited: code Update
ABAddressBookRef addressBook = ABAddressBookCreate();
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
//get all contacts names
NSMutableArray* EmailArrayPerPerson = [[NSMutableArray alloc]init];
NSMutableArray* PhoneArrayPerPerson = [[NSMutableArray alloc]init];
for (int i = 0; i < ABAddressBookGetPersonCount(addressBook); i++)
{
NSMutableDictionary *ContactsDetails = [NSMutableDictionary dictionary];
ABRecordRef ref = CFArrayGetValueAtIndex(allPeople, i);
NSString *contact = (__bridge NSString *)(ABRecordCopyCompositeName(ref));
NSLog(#"%#",contact);//contact is good here
ContactsDetails = [NSMutableDictionary dictionary];
[ContactsDetails setObject:contact forKey:#"CName"];
ABMultiValueRef emails = ABRecordCopyValue(ref, kABPersonEmailProperty);
[EmailArrayPerPerson removeAllObjects];
NSLog(#"dictionary is:%#",[ContactsDetails objectForKey:#"CName"]);
for (CFIndex j=0; j < ABMultiValueGetCount(emails); j++)
{
NSString* email = (NSString*)CFBridgingRelease(ABMultiValueCopyValueAtIndex(emails, j));
[EmailArrayPerPerson addObject:email];
}
[ContactsDetails setObject:EmailArrayPerPerson forKey:#"CEMails"];
ABMultiValueRef multi = ABRecordCopyValue(ref, kABPersonPhoneProperty);
[PhoneArrayPerPerson removeAllObjects];
for (CFIndex j=0; j < ABMultiValueGetCount(multi); j++)
{
NSString* phone = (NSString*)CFBridgingRelease(ABMultiValueCopyValueAtIndex(multi, j));
[PhoneArrayPerPerson addObject:phone];
}
[ContactsDetails setObject:PhoneArrayPerPerson forKey:#"CPhones"];
NSLog(#"dictionary is:%#",ContactsDetails);
[Contacts addObject:ContactsDetails];
[Contacts insertObject:ContactsDetails atIndex:i];
NSLog(#"%#",Contacts);
}
NSLog(#"%d",[Contacts count]);
Contacts is my mutableArray, but when I am printing it
it always has the values of the last dictionary at all of his indexes.
when I am printing the dictionary in each iteration , I get the correct values inside.
Please give it a look help me to figure out what is wrong there.
I did mix of all answers , now it is partially working , I getting distinct Names , but mails and phones are still same for all
You're only ever creating one dictionary, and then modifying it in every iteration. Your final result contains the same dictionary N times, not N copies of the last dictionary.
You're doing this, basically:
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
NSMutableArray *dictionaries = [NSMutableArray array];
for (NSInteger i = 0; i < 10; i++) {
dict[#"something"] = #(i);
[dictionaries addObject:dict]; // adding the same dictionary you added last time
}
You want to be doing this:
NSMutableArray *dictionaries = [NSMutableArray array];
for (NSInteger i = 0; i < 10; i++) {
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
dict[#"something"] = #(i);
[dictionaries addObject:dict]; // adding the newly created dictionary
}
Side note...don't name your variables in Uppercase. In Objective-C, uppercase identifiers are used for class names. It's not technically wrong, but it's against the standard coding conventions for the language, which makes the code harder to read for other developers.
Try replacing each "remove object call," for example
[ContactsDetails removeAllObjects];
[EmailArrayPerPerson removeAllObjects];
with a re-instantiation, i.e.
ContactDetails = [NSMutableDictionary dictionary];
EmailArrayPerPerson = [[NSMutableArray alloc]init];
because you're essentially placing the same objects in each slot in your array repeatedly. You need to create new objects for each iteration.
Put this line of code in side your for loop
NSMutableDictionary *ContactsDetails = [NSMutableDictionary dictionary];

converting a onedimensional array to 2-d array having the specified number of columns

i am passing one one dimensional array having elements "1,2,3,4,5,6,7"
and in my code i want to convert this array into a 2-dimensional array .
The number of columns of the 2-d array will be specified by user .
say if am setting the columns value to 3
then the output 2-d array should be in the format
123
456
7
.m file of my class
-(NSMutableArray *)OneToTwoDimensionalArray:(NSMutableArray *)values :(NSInteger)columns
{
NSMutableArray * twoDimensional=[[NSMutableArray alloc]initWithCapacity:columns];
for(int i=0;i<columns;i++)
{
[twoDimensional insertObject:values atIndex:i];
}
return twoDimensional;
}
viewcontroller.m file
EPArray *arr=[[EPArray alloc]init];
int columns=4;
arr1=[[NSMutableArray alloc]initWithObjects:#"1",#"2",#"3",#"4",#"5",#"6",#"7",nil];
NSMutableArray *finalresult=[arr OneToTwoDimensionalArray:arr1 :columns];
for(int i=0;i<columns;i++)
{
NSLog(#"%#",[finalresult objectAtIndex:i]);
}
Try this,
NSArray *array = #[#"1", #"2", #"3", #"4", #"5", #"6", #"7"];
int noOfColumns = 3;
NSMutableArray *outerArray = [[NSMutableArray alloc] init];
for (int counter = 0; counter < [array count]; counter = counter + noOfColumns) {
NSMutableArray *innerArray = [[NSMutableArray alloc] init];
for (int arrayIndex = counter; ((arrayIndex < counter + noOfColumns) && (arrayIndex < [array count])); arrayIndex++) {
[innerArray addObject:array[arrayIndex]];
}
[outerArray addObject:innerArray];
}
NSLog(#"outerArray = %#", outerArray);
Here outerArray will give the 2 dimensional array with the provided column value. The above code is readable and easy to maintain especially if you want to make some quick changes.
Output:
outerArray = (
(
1,
2,
3
),
(
4,
5,
6
),
(
7
)
)
Next to my other answer — that I would favor — I want to offer another solution, that uses more traditional C-style programming but is quite readable.
NSUInteger columnWidth = 3;
NSArray *array = #[#1, #2, #3, #4 ,#5, #6, #7];
NSMutableArray *newArray = [NSMutableArray array];
NSUInteger columnIdx = 0;
for (NSUInteger count = 0; count < [array count]; ++count) {
if (columnIdx == 0) {
[newArray addObject:[NSMutableArray array]];
}
NSMutableArray *lastArray = [newArray lastObject];
[lastArray addObject:array[count]];
columnIdx = (++columnIdx)%columnWidth;
}
newArray now contains the subarrays as required.
note, that also this solution uses the modulo operator columnIdx = (++columnIdx)%columnWidth;.
instead of this you also could write
++columnIdx;
if(columnIdx == columnWidth) columnIdx = 0;
NSUInteger columnWidth = 3;
NSArray *array = #[#1, #2, #3, #4 ,#5, #6, #7];
NSMutableArray *mArray =[NSMutableArray array];
[array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
if (idx % columnWidth == 0) {
[mArray addObject:[NSMutableArray array]];
}
[[mArray objectAtIndex:[mArray count]-1] addObject:obj];
}];
mArraynow contains 3 arrays with
(
(
1,
2,
3
)
,
(
4,
5,
6
)
,
(
7
)
)
This code uses the modulo operator that finds the remainder of division of one number by another.
if (idx % 3 == 0) {
[mArray addObject:[NSMutableArray array]];
}
if there is no remainder, it must be the index 0,3,6,…. In such a case, a new array is added to the outer array. the object are always added to the last array.
Also note that using enumerateObjectsUsingBlock: should be faster than using c-style for (for(int i=0;i<columns;i++)) or even fast enumeration.
I added a second answer that uses only C-constructs rather than blocks, but I'd favor this one.
and — of course — you should consider using a category on NSArray
#interface NSArray (Columns)
-(NSArray *)arrayOfArraysWithColumnWidth:(NSUInteger)width;
#end
#implementation NSArray (Columns)
-(NSArray *)arrayOfArraysWithColumnWidth:(NSUInteger)width
{
NSAssert(width > 0, #"width need to be 1 or greater");//sanity check
NSMutableArray *mArray =[NSMutableArray array];
[self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
if (idx % width == 0) {
[mArray addObject:[NSMutableArray array]];
}
[[mArray objectAtIndex:[mArray count]-1] addObject:obj];
}];
return mArray;
}
#end
You would use it like:
NSArray *numbers = [#[#1, #2, #3, #4 ,#5, #6, #7] arrayOfArraysWithColumnWidth:3];

Resources