显示Parse PFGeoPoints数组作为Map Annotations Error

时间:2015-03-01 01:14:07

标签: ios objective-c parse-platform nsarray mkannotation

我试图在地图上显示存储在NSArray中的对象。在执行了用户2英里范围内获取位置的方法后,将从名为Affiliates的Parse.com类中提取对象。我已经使用NSLog来确认查询是否正确执行,所以我知道fetch也正在正确执行。

当我尝试运行应用程序时,我在for(NSDictionary)部分抛出了一个错误,应用程序冻结了。错误状态“线程1:EXC_BAD_ACCESS(访问代码1,地址0x80120)”在咨询Google之后,我发现它是某种类型的内存分配问题,但我不知道它为什么会发生或如何解决它。

#import "ViewController.h"
#import "MapAnnotation.h"

@import CoreLocation;

@interface ViewController () <CLLocationManagerDelegate>

@property (nonatomic,strong) NSArray *affiliates;

@end

@implementation ViewController

- (void)viewDidLoad {


    [super viewDidLoad];

    // Ask for authorization to collect location from user
    CLLocationManager * locationManager = [[CLLocationManager alloc] init];
    // Check for iOS 8. Without this guard the code will crash with "unknown selector" on iOS 7.
    if ([locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) {

        locationManager.delegate = self;
        locationManager.distanceFilter = kCLDistanceFilterNone;
        locationManager.desiredAccuracy = kCLLocationAccuracyBest;
        [locationManager startUpdatingLocation];
        [locationManager requestWhenInUseAuthorization];
    }

    //Set map options
    self.mapView.showsUserLocation = YES;
    self.mapView.delegate = self;
    self.mapView.scrollEnabled = YES;
    self.mapView.zoomEnabled = YES;
    self.mapView.userTrackingMode = YES;

    // Store the user's location as a Parse PFGeoPoint and call the fetchAffiliatesNearPoint method
    [PFGeoPoint geoPointForCurrentLocationInBackground:^(PFGeoPoint *geoPoint, NSError *error) {
        if (!error) {
            [self fetchAffiliatesNearPoint:geoPoint];
            NSLog(@"Got User Location! %@", geoPoint);
        }
    }];

    /* This is where I am having issues

    for(NSDictionary *affiliates in affiliates) {
        CLLocationCoordinate2D annotationCoordinate = CLLocationCoordinate2DMake([affiliates[@"latitude"] doubleValue], [affiliates[@"longitude"] doubleValue]);

        MapAnnotation *annotation = [[MapAnnotation alloc] init];
        annotation.coordinate = annotationCoordinate;
        annotation.title = affiliates[@"name"];
        annotation.subtitle = affiliates[@"url"];
        [self.mapView addAnnotation:annotation];
    }

*/

}


//Fetch an array of affiliates that are within two miles of the user's current location.
- (void)fetchAffiliatesNearPoint:(PFGeoPoint *)geoPoint
{

    PFQuery *query = [PFQuery queryWithClassName:@"Affiliates"];
    [query whereKey:@"geometry" nearGeoPoint:geoPoint withinMiles:2.0];
    [query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
        if (!error)
        {
            self.affiliates = objects;
            NSLog(@"Nearby Locations %@", _affiliates);
        }
    }];
}


-(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{


    //Zoom map to users current location
    if (!self.initialLocation) {
        self.initialLocation = userLocation.location;
        MKCoordinateRegion mapRegion;
        mapRegion.center = mapView.userLocation.coordinate;
        mapRegion.span.latitudeDelta = .025;
        mapRegion.span.longitudeDelta = .025;

        [mapView setRegion:mapRegion animated: YES];
        }

}
@end

2 个答案:

答案 0 :(得分:1)

如果要将自定义对象添加到MapKit地图,则必须符合MKAnnotation协议。只有一个属性需要实现才能使对象符合协议:

@property (nonatomic, readonly) CLLocationCoordinate2D coordinate;

其他属性(例如titlesubtitle)和方法是可选的。

您需要做的就是在PFGeoPoint上创建一个类别(假设您使用的是Objective-C),并为coordinate属性实现一个getter。

<强> PFGeoPoint + Annotation.h

@interface PFGeoPoint (Annotation) <MKAnnotation>

@end

<强> PFGeoPoint + Annotation.m

@implementation PFGeoPoint (Annotation)

- (CLLocationCoordinate2D)coordinate {
    return CLLocationCoordinate2DMake(self.latitude, self.longitude);
}

@end

最后,要将其添加到地图中,您将使用:

- (void)addAnnotation:(id <MKAnnotation>)annotation;

例如:[mapView addAnnotation:geoPoint];

答案 1 :(得分:0)

我还没与Parse合作,但有一些明显的问题可能有助于指出:

  1. 这条线没有意义:

    for(NSDictionary *affiliates in affiliates)
    

    此处,affiliates之后in引用本地声明的字典变量而引用同名的属性变量。由于局部变量没有初始化引用并且指向某个随机内存,因此您获得EXC_BAD_ACCESS。使用self.affiliates明确引用该属性。

    此外,它的非常令人困惑,因为它将循环变量命名为与循环变量相同的数组。您正在遍历一系列&#34;附属公司&#34; (复数)。该数组包含字典,每个字典都是一个&#34; affiliate&#34; (单数)。将字典变量命名为affiliate(单数)会更容易混淆。例如:

    for (NSDictionary *affiliate in self.affiliates)
    

    同时将循环内的其余参考从affiliates更改为affiliate

  2. 目前,self.affiliates上的循环是在geoPointForCurrentLocationInBackground 启动之后立即完成的。 geoPointForCurrentLocationInBackground似乎是异步的,这意味着self.affiliates上的循环将在 geoPointForCurrentLocationInBackground实际设置该属性之前执行

    在启动self.affiliates后立即在viewDidLoad中循环遍历geoPointForCurrentLocationInBackground,而不是在findObjectsInBackgroundWithBlock的完成块内移动(之后) self.affiliates已设置)。例如:

    [query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
        if (!error)
        {
            self.affiliates = objects;
            NSLog(@"Nearby Locations %@", _affiliates);
    
            for(NSDictionary *affiliate in self.affiliates) {
                ...
            }
        }
    }];