NSMutableArray 解析 csv 不工作?

NSMutableArray parsing csv not working?

我有这段代码,我在其中使用 NSMutableArray 来解析 csv 文件。没有错误阻止我使用 运行 该应用程序,但是地图不显示任何内容。

 NSString *csvFilePath = [[NSBundle mainBundle] pathForResource:@"Data2"   ofType:@"csv"];
NSString *dataStr = [NSString stringWithContentsOfFile:csvFilePath encoding:NSUTF8StringEncoding error:nil];

NSMutableArray *allLinedStrings = [[NSMutableArray alloc]initWithArray:[dataStr componentsSeparatedByString:@"\r"]];


NSMutableArray *latitude = [[NSMutableArray alloc]init];
NSMutableArray *longitude = [[NSMutableArray alloc]init];
NSMutableArray *description = [[NSMutableArray alloc]init];
NSMutableArray *address = [[NSMutableArray alloc]init];
NSMutableArray *temperature = [[NSMutableArray alloc]init];
NSMutableArray *time = [[NSMutableArray alloc]init];
NSMutableArray *ambient = [[NSMutableArray alloc]init];

NSMutableArray *filteredLocations = [NSMutableArray array];
MKMapPoint* pointArr = malloc(sizeof(MKMapPoint) * filteredLocations.count);

for (int idx = 0; idx < [allLinedStrings count]; idx++)
{
NSMutableArray *infos = [[NSMutableArray alloc]initWithArray:[[allLinedStrings objectAtIndex:idx] componentsSeparatedByString:@","]];
    if ([infos count] > 1)
    {
        [latitude addObject:[infos objectAtIndex:4]];
        [longitude addObject:[infos objectAtIndex:5]];
        [description addObject:[infos objectAtIndex:0]];
        [address addObject:[infos objectAtIndex:10]];
        [temperature addObject:[infos objectAtIndex:6]];
        [time addObject:[infos objectAtIndex:15]];
        [ambient addObject:[infos objectAtIndex:8]];


        if([[latitude objectAtIndex:4] isEqualToString:@"NULL"] || [[longitude objectAtIndex:5] isEqualToString:@"NULL"] || [[description objectAtIndex:0] isEqualToString:@"NULL"] ||  [[address objectAtIndex:10]isEqualToString:@"NULL"] ||  [[temperature objectAtIndex:6] isEqualToString:@"NULL"] ||  [[time objectAtIndex:15]isEqualToString:@"NULL"] ||  [[ambient objectAtIndex:8] isEqualToString:@"NULL"]) {continue;}

        CLLocationCoordinate2D coordinate;
        coordinate.latitude = [[latitude objectAtIndex:4] doubleValue];
        coordinate.longitude = [[longitude objectAtIndex:5] doubleValue];
        Location *annotation = [[Location alloc] initWithName:[description objectAtIndex:0] address:[address objectAtIndex:10] temperature:[temperature objectAtIndex:6] time:[time objectAtIndex:15] ambient:[ambient objectAtIndex:8] coordinate:coordinate] ;
        [mapview addAnnotation:annotation];
        [filteredLocations addObject:annotation];

        MKMapPoint point = MKMapPointForCoordinate(coordinate);

        pointArr[idx] = point;


    }

}

self.routeLine = [MKPolyline polylineWithPoints:pointArr count:filteredLocations.count];
[self.mapview addOverlay:self.routeLine];
free(pointArr);


        MKMapRect zoomRect = MKMapRectNull;
        for (id <MKAnnotation> annotation in mapview.annotations)
        {
            MKMapPoint annotationPoint = MKMapPointForCoordinate(annotation.coordinate);
            MKMapRect pointRect = MKMapRectMake(annotationPoint.x, annotationPoint.y, 0.1, 0.1);
            zoomRect = MKMapRectUnion(zoomRect, pointRect);
        }
        [mapview setVisibleMapRect:zoomRect animated:YES];

        self.mapview.delegate = self;

    }

我想我调用对象或 MKMapPoint 的方式肯定有问题,但我没能找到阻止应用程序显示数据的原因。我试过同时使用 "initWithObjects" 和删除 "if ([infos count] > 1){" 但是当 运行 它崩溃显示 "NSMutableArray *latitude = [[NSMutableArray alloc]init];".

中的故障点

根据您之前关于此项目的问题,您希望在更高层次上执行以下操作:

  1. 解析每行都有坐标数据的 CSV 文件。忽略具有 "null" 数据的行。 (为了这个答案的目的,让我们忽略可以使用预构建的 CSV 解析器,或者完全使用不同的格式。)
  2. 显示包含 "good" 数据的行的注释。
  3. 用一条线连接所有注释。

对于要求 1 (R1),您已经知道如何加载 CSV 文件、循环遍历行以及用 "null" 数据识别行。

对于要求 2 (R2),经过一些研究,您知道您可以一次创建一个注释并将其添加到地图,而地图 不需要提前知道如何许多你会添加,这意味着前两个要求可以在同一个循环中完成。

对于要求 3 (R3),经过一些研究,您知道要创建折线并将其添加到地图,您需要提前知道 直线上有多少个点。

对于 R1 和 R2,您将遍历 CSV 的行并识别非空行。

这意味着您将知道在处理 R1 和 R2 的循环之后折线 中有多少点。这意味着必须在该循环之后创建折线。

但是要创建折线,您不仅需要点数,还需要每个点的坐标。

这意味着在遍历 CSV 中的行时,您需要将坐标数据保存在某处(按照它在 CSV 中出现的顺序)。

在 Objective-C 中,一种方便的结构是 NSMutableArray

允许您在事先不知道将添加多少对象的情况下向其中添加数据。


所以现在我们有了这个非常高级的计划:

  1. 遍历 CSV 文件,忽略包含空数据的行,创建并添加注释,将行数据添加到 NSMutableArray (NSMA)。
  2. 使用NSMA中的点数据创建折线,将折线添加到地图中。

有了这个计划,我们发现我们需要 一个 NSMutableArray。请注意,在现有代码中,您有一个 Location class 保存(或可能保存)CSV 每一行的所有数据。

这意味着我们可以简单地将这些 Location 个对象添加到 NSMA。 NSMutableArrays 可以容纳任何类型的对象(它们不必只是 NSStrings)。


所以这里有一个更详细的计划:

  1. 初始化一个名为 filteredLocationsNSMutableArray(例如 NSMutableArray *filteredLocations = [NSMutableArray array];)。
  2. 遍历 CSV 文件,忽略包含空数据的行,创建一个 Location 对象并添加为注释,将 Location 对象添加到 filteredLocations(例如 [filteredLocations addObject:annotation];).
  3. 初始化 (malloc) 一个 C 数组来保存折线的点,点数为 filteredLocations
  4. 遍历 filteredLocations,将 filteredLocations 中的点添加到 C 数组。
  5. 创建折线并将其添加到地图。

在此计划说明中,我们有 两个独立的循环:第一个用于 R1 和 R2。第二个是给R3的。


如果需要,我将 post 实现此计划的示例代码。



首先,只是为了解释你最近的 NSRangeException 错误,它发生在这一行:

if([[latitude objectAtIndex:4] isEqualToString:@"NULL"] || ...

因为您已将 latitude 声明为数组,并且 if 第一次在循环中执行,latitude 只有一个对象(此 [= 以上几行) 31=] 你做 [latitude addObject:...)。数组的索引从零开始,因此具有一个对象的数组的边界是零到零,因此错误消息显示 index 4 beyond bounds [0 .. 0].

其余代码还有许多其他问题。
本回答篇幅不够,无法详细说明。

我劝你,如果可能的话,停下来,退后一步,然后重新开始一个更简单的项目或教程,最重要的是,学习一般编程的绝对基础知识.

下面是一个代码示例,应该可以根据您的示例数据运行:

-(void)viewDidLoad
{
    [super viewDidLoad];


    self.mapview.delegate = self;


    NSString *csvFilePath = [[NSBundle mainBundle] pathForResource:@"Data2" ofType:@"csv"];
    NSString *dataStr = [NSString stringWithContentsOfFile:csvFilePath encoding:NSUTF8StringEncoding error:nil];


    NSArray *allLinedStrings = [dataStr componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];


    NSMutableArray *filteredLocations = [NSMutableArray array];

    for (int idx = 0; idx < [allLinedStrings count]; idx++)
    {
        NSArray *infos = [[allLinedStrings objectAtIndex:idx] componentsSeparatedByString:@","];

        if ([infos count] > 15)
        {
            NSString *latitude = [infos objectAtIndex:4];
            NSString *longitude = [infos objectAtIndex:5];
            NSString *description = [infos objectAtIndex:0];
            NSString *address = [infos objectAtIndex:10];
            NSString *temperature = [infos objectAtIndex:6];
            NSString *time = [infos objectAtIndex:15];
            NSString *ambient = [infos objectAtIndex:8];

            if([latitude isEqualToString:@"NULL"]
               || [longitude isEqualToString:@"NULL"]
               || [description isEqualToString:@"NULL"]
               || [address isEqualToString:@"NULL"]
               || [temperature isEqualToString:@"NULL"]
               || [time isEqualToString:@"NULL"]
               || [ambient isEqualToString:@"NULL"])
            {
                continue;
            }

            CLLocationCoordinate2D coordinate;
            coordinate.latitude = [latitude doubleValue];
            coordinate.longitude = [longitude doubleValue];

            Location *annotation = [[Location alloc] initWithName:description
                                                          address:address
                                                      temperature:temperature
                                                             time:time
                                                          ambient:ambient
                                                       coordinate:coordinate];
            [mapview addAnnotation:annotation];

            [filteredLocations addObject:annotation];
        }
    }



    MKMapPoint* pointArr = malloc(sizeof(MKMapPoint) * filteredLocations.count);

    for (int flIndex = 0; flIndex < filteredLocations.count; flIndex++)
    {
        Location *location = [filteredLocations objectAtIndex:flIndex];
        MKMapPoint point = MKMapPointForCoordinate(location.coordinate);
        pointArr[flIndex] = point;
    }

    self.routeLine = [MKPolyline polylineWithPoints:pointArr count:filteredLocations.count];
    [self.mapview addOverlay:self.routeLine];
    free(pointArr);



    [self.mapview showAnnotations:self.mapview.annotations animated:YES];
}