IOS/Objective-C:应用程序首次启动后定位引脚 (json) 未显示

IOS/Objective-C: Location pins (json) not showing up after application first launch

我的应用在第一次执行时收到一个 json 对象(具有三个针点位置);有一个 mapKit(第一个屏幕)和一个 TableView,用户可以在其中检查这些位置。问题是当我第一次启动该应用程序时,地图上没有图钉。但是如果我切换到 table 我可以看到它们 - 在单元格上 - 如果我再次切换到地图,就会出现图钉......我不知道为什么会这样,我不应该看到应用程序启动后立即固定?地图代码:

- (void)viewDidLoad {
    [super viewDidLoad];

    NSNotificationCenter *notification=[NSNotificationCenter defaultCenter];
    [notification addObserver:self selector:@selector (receiveNotification:) name:@"notification" object:self];

    _mapView.showsUserLocation=YES;
    _mapView.showsBuildings=YES;
    _locationManager = [[CLLocationManager alloc] init];
    [_locationManager requestAlwaysAuthorization]; 
    _mapView.delegate = self;
    _locationManager.delegate=self;

}

-(void)viewDidAppear:(BOOL)animated{
        [self receiveNotification:nil];


}
-(void)receiveNotification:(NSNotification*)notification{
    NSArray *spots = [Spot spotType:@"users"];
    NSArray *places = [Spot spotWithType:@"users"];

    [_mapView addAnnotations:spots];
    [_mapView addAnnotations:places];

}

和 table:

- (void)viewDidLoad {
    [super viewDidLoad];

    self.tableView.dataSource = self;

    self.detailList=@[@"Your Favourite Spots",@"Our suggestion"];

}

-(void)viewDidAppear:(BOOL)animated{
    _lisbonSpots = [[Spot spotType:@"users"]mutableCopy];
    _users=[[Spot spotWithType:@"users"]mutableCopy];

    [self.tableView reloadData];

}

编辑 - 现场 Class

@implementation Spot


@dynamic ID;
@dynamic name;
@dynamic desc;
@dynamic type;
@dynamic phone;
@dynamic latitude;
@dynamic longitude;

+ (instancetype)spotWithName:(NSString *)name andCoord:

(CLLocationCoordinate2D)coord type:(NSString*)type desc:(NSString*)desc phone:(NSString*)phone{

    NSPersistentContainer *persistenceContainer = [AppDelegate sharedDelegate].persistentContainer;
    NSManagedObjectContext *context = persistenceContainer.viewContext;

    Spot *spot = [NSEntityDescription insertNewObjectForEntityForName:@"Spot" inManagedObjectContext:context];

    spot.name = name;
    spot.latitude = coord.latitude;
    spot.longitude = coord.longitude;
    spot.type=type;
    spot.desc=desc;
    spot.phone=phone;


    [[AppDelegate sharedDelegate] saveContext];

    return spot;
}

+ (instancetype)spotWithDict:(NSDictionary *)dict {
    CLLocationCoordinate2D coord = CLLocationCoordinate2DMake([dict[@"latitude"] doubleValue], [dict[@"longitude"] doubleValue]);

    return [Spot spotWithName:dict[@"name"] andCoord:coord type:dict[@"type"] desc:dict[@"desc"] phone:dict[@"phone"]];
}

+ (NSArray*)getSpotType:(NSString*)type withPredicate:(NSString*) pred andMessage:(NSString*)message {

    NSPersistentContainer *persistenceContainer = [AppDelegate sharedDelegate].persistentContainer;

    NSPredicate* predicate = [NSPredicate predicateWithFormat:pred, type];

    NSManagedObjectContext *context = persistenceContainer.viewContext;

    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Spot"];

    [request setPredicate:predicate];

    NSError *error;

    NSArray *result = [context executeFetchRequest:request error:&error];

    if (error != nil) {
        NSLog(message, [error localizedDescription]);
        return nil;
    }
    return result;
}

+ (NSArray*)spotType:(NSString*)type {
    return [Spot getSpotType:type withPredicate:@"type =%@" andMessage:@"[Spot spotType] -> %@"];
}

+ (NSArray*)spotWithType:(NSString*)type {
    return [Spot getSpotType:type withPredicate:@"NOT (type = %@)" andMessage:@"[Spot spotWithType] -> %@"];
}


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

- (NSString *)title {
    return self.name;
}

- (NSString *)description {

    return [NSString stringWithFormat:@"%@", self.name];
}

@end

编辑:SpotService class

@implementation SpotService

+ (NSURL *)serviceURL {
    return [NSURL URLWithString:@"http://training.reativ.io/ios/lisbon-spots"];

}
+ (BOOL)service:(id<SpotServiceInvoker>)invoker {

    NSMutableURLRequest * request = [[NSMutableURLRequest alloc] initWithURL:[SpotService serviceURL]];


    NSURLSession *session = [NSURLSession sharedSession];

    NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {

        if (error != nil) {
            NSLog(@"Response: %@", response);
            NSLog(@"Error: %@", error);

            return;
        }

        NSArray *lisbonSecrets = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&error];


        dispatch_async(dispatch_get_main_queue(), ^{
            if ([invoker respondsToSelector:@selector(receiveSpot:)]){
                [invoker receiveSpot:lisbonSecrets];
            }

            for(NSDictionary *dict in lisbonSecrets) {
                [Spot spotWithDict:dict];
            }
        });
    }];

    [task resume];

    return YES;
}

我的猜测是 - 你的 Spot class 异步检索数据,当你第一次从 MapView 上的 viewDidAppear 调用 [Spot spotType:@"users"] 时还没有检索到数据。当您切换视图控制器时,数据会出现并且一切正常。

但最好向我们展示您的 Spot class。可能您需要 completion handler 或类似的东西来实现预期的行为。

此外,每次当您的地图出现在屏幕上时,您都会调用 addAnnotations,这意味着每次您调用此方法时,MKMapView 都会添加注释的副本。最好添加额外的检查以确保您不会多次添加相同的注释。