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
都会添加注释的副本。最好添加额外的检查以确保您不会多次添加相同的注释。
我的应用在第一次执行时收到一个 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
都会添加注释的副本。最好添加额外的检查以确保您不会多次添加相同的注释。