Search code examples
iosobjective-ccsv

Parsing csv file to NSMutableArray


I know the instructions are all over of how to read a .csv file in objective c then pass it to an NSMuatbleArray, but I'm getting problems when I assign it to a mutableArray. I've spent hours of checking online and trying to fix it, but nothing helped.

Here is my objective c code:

NSError *err;
NSString *filePath = [NSString stringWithContentsOfFile:@"/users/Mike/Desktop/Book1.csv" encoding:NSUTF8StringEncoding error:&err];

NSString *replace = [filePath stringByReplacingOccurrencesOfString:@"\"" withString:@""];
NSString *something = [replace stringByReplacingOccurrencesOfString:@"," withString:@"\n"];

NSMutableArray *columns = [[NSMutableArray alloc] initWithObjects:[something componentsSeparatedByString:@"\n"], nil];

NSLog(@"%@", filePath);
NSLog(@"%@", something);
NSLog(@"%@", columns);

Here is the output:

My App[1854:54976] Kitchen,Bathroom,Dinning Room,Living Room
My App[1854:54976] Kitchen
Bathroom
Dinning Room
Living Room

My App[1854:54976] (
        (
        Kitchen,
        Bathroom,
        "Dinning Room",
        "Living Room"
    )
)

The problem is that the output of the array comes with commas and quotations which I eliminated.

What I need is for the array "columns" to come out like the string "something".

Update

I took away the two strings of "replace" and "something" and switched the array to:

columns = [[NSMutableArray alloc] initWithObjects:[filePath componentsSeparatedByString:@","], nil];

Now I'm having trouble loading it to a table view. Here's my code for that.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *cellIdentifier = @"firstCell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
    
    cell.textLabel.text = [columns objectAtIndex:indexPath.row];
    return cell;
}

The app just crashes with an unexplained reason, but when I make another array manually, it works.

This one works:

NSMutableArrayrow = [[NSMutableArray alloc] initWithObjects:@"First", @"Second", nil];

Solution

  • Your code is a bit muddled, and contains one error that is the cause of your unexplained parenthesis.

    • Why replace quotes with nothing when there are no quotes in the source data?
    • Why replace commas with line breaks, and then split the string into an array of strings on the line breaks (which gets rid of the line breaks entirely)? Why not just split the string into an array using commas and skip the intermediate step?
    • Finally, and most seriously, the method initWithObjects wants a comma-delimited set of objects, then a nil. You are passing it an array, and nil. So what you are getting as a result is a mutable array that contains a single object, an immutable array. This is almost certainly not what you want.

    This line:

    NSMutableArray *columns = 
      [[NSMutableArray alloc] initWithObjects:
        [something componentsSeparatedByString:@"\n"], nil];
    

    ...is wrong.

    You would use initWithObjects like this:

    NSMutableArray *columns = 
      [[NSMutableArray alloc] initWithObjects: @"one", @"two", @"three", nil];
    

    Note how I'm passing in a comma-separated list of objects, and then a nil. Your use of initWithObjects is passing in a single object, an array, and then a nil. You won't get a mutable array that contains the objects from the source array - you'll get a mutable array that contains your starting immutable array.

    It should be written like this instead:

    NSMutableArray *columns = [[something componentsSeparatedByString:@"\n"] 
      mutableCopy];
    

    Or better yet, do it in 2 steps so it's clear whats going on:

    NSArray *tempArray = [something componentsSeparatedByString:@"\n"];
    NSMutableArray *columns = [tempArray mutableCopy];