无法在MapKit中使用核心数据模型类添加注释

时间:2016-12-10 00:28:29

标签: ios objective-c mapkit

我尝试使用核心数据模型类作为我的自定义注释,但不知何故,viewForAnnotation永远不会被调用。

这是我的视图控制器,它包含所有核心数据片段以及我如何实现委托方法

#import "SkyCastViewController.h"
#import "AppDelegate.h"
#import "Pixel-Swift.h"
#import "Photo+Annotation.h"


static NSString* const NavigationBarTitleFontName = @"Avenir-Heavy";
static CGFloat const NavigationBarTitleFontSize = 17;
static NSString* const MapViewReuseIdentifier = @"AnnotationViweIden";

@interface SkyCastViewController () <MKMapViewDelegate>

@property (weak, nonatomic) IBOutlet MKMapView *mapView;
@property (strong, nonatomic) NSArray* photos;
@property (strong, nonatomic) UIManagedDocument* document;



@end

@implementation SkyCastViewController

- (void) viewDidLoad{
    [super viewDidLoad];
    [self updateUI];
    self.mapView.delegate = self;
}

- (void) viewDidAppear:(BOOL)animated{
    [super viewDidAppear:animated];
    NSFileManager* fileManager = [NSFileManager defaultManager];
    NSURL* docsDir = [fileManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask].firstObject;
    if(docsDir){
        NSURL* url = [docsDir URLByAppendingPathComponent:@"storage"];
        self.document = [[UIManagedDocument alloc] initWithFileURL: url];
        if(self.document.documentState != UIDocumentStateNormal){
            if([[NSFileManager defaultManager] fileExistsAtPath: url.path]){
                //the document exists, open it
                [self.document openWithCompletionHandler:^(BOOL success){
                    if(success){
                        [self documentInit];
                    }
                }];
            }else{
                //the document does not exist, create one
                [self.document saveToURL:url forSaveOperation: UIDocumentSaveForCreating completionHandler:^(BOOL success){
                    //post a notification that document is ready
                    if(success){
                        NSLog(@"saveToURL succeed");
                    }else{
                        NSLog(@"saveToURL falied");
                    }
                }];
            }
        }
    }

}




// document ready observer
- (void) documentInit{
    dispatch_async(dispatch_get_main_queue(), ^{
        NSManagedObjectContext* context = self.document.managedObjectContext;
        NSError* error;
        //fetch objects
        NSFetchRequest* request = [[NSFetchRequest alloc] initWithEntityName:@"User"];
        request.fetchBatchSize = 10;
        request.fetchLimit = 100;
        NSString* nameAttr = @"name";
        NSString* nameValue = @"Kesong Xie";
        request.predicate = [NSPredicate predicateWithFormat:@"%K like %@", nameAttr, nameValue];
        NSArray* users = [context executeFetchRequest:request error: &error];
        if(error != nil){
            NSLog(@"%@", error.localizedDescription);
        }else{
            if([users count] > 0){
                for(User* user in users){
                    self.photos = (NSArray<Photo<MKAnnotation>*>*)user.photo.allObjects;
                    [self.mapView addAnnotations:self.photos];
                }
            }
        }
        NSLog(@"%@", self.photos);
        //        [self.mapView showAnnotations: self.photos animated: YES];
    });

}


//MARK: - UPATE UI
- (void) updateUI{
    [self.navigationController.navigationBar setBarTintColor: [UIColor blackColor]];
    UIFont* titleFont = [UIFont fontWithName: NavigationBarTitleFontName size: NavigationBarTitleFontSize];
    [self.navigationController.navigationBar setTitleTextAttributes:@{NSFontAttributeName: titleFont,    NSForegroundColorAttributeName: [UIColor whiteColor]}];
}

- (UIStatusBarStyle) preferredStatusBarStyle{
    return UIStatusBarStyleLightContent;
}


//MARK: - MKMapViewDelegate
-(MKAnnotationView*) mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation{
    NSLog(@"called from viewForAnnotation");
    if([annotation isKindOfClass:[ MKUserLocation class]]){
        return nil;
    }
    MKAnnotationView* annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier: MapViewReuseIdentifier];
    if(!annotationView){
        annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:MapViewReuseIdentifier];
    }else{
        annotationView.annotation = annotation;
    }
    UIImage* shot = [[UIImage alloc] initWithContentsOfFile:@"shot3"];
    annotationView.image = shot;
    annotationView.frame = CGRectMake(0, 0, 60, 60);
    annotationView.clipsToBounds = YES;
    return annotationView;
}

@end

现在控制台上的唯一输出是

Pixel[1832:440548] (
    "<Pixel.Photo: 0xa03a400> (entity: Photo; id: 0x17e905f0 <x-coredata://FB9198FE-57D1-4C88-945B-0B04D49821C0/Photo/p42> ; data: {\n    latitude = \"32.88831721994364\";\n    longitude = \"-117.2413945199151\";\n    thumbnailData = nil;\n    time = nil;\n    title = \"Beach Walking\";\n    whoTook = \"0xa040660 <x-coredata://FB9198FE-57D1-4C88-945B-0B04D49821C0/User/p10>\";\n})",
    "<Pixel.Photo: 0xa039440> (entity: Photo; id: 0xa038b40 <x-coredata://FB9198FE-57D1-4C88-945B-0B04D49821C0/Photo/p43> ; data: {\n    latitude = \"32.88831721994364\";\n    longitude = \"-117.2413945199151\";\n    thumbnailData = nil;\n    time = nil;\n    title = \"Aerial Shots of Sedona Arizona\";\n    whoTook = \"0xa040660 <x-coredata://FB9198FE-57D1-4C88-945B-0B04D49821C0/User/p10>\";\n})"
)

2 个答案:

答案 0 :(得分:0)

请您分享一下您的viewController代码,因为根据您的代码共享,我可以假设您的MapView在此代码之后启动。

if(error != nil){
            NSLog(@"%@", error.localizedDescription);
        }else{
            if([users count] > 0){
                for(User* user in users){
                    self.photos = (NSArray<Photo<MKAnnotation>*>*)user.photo.allObjects;
                    [self.mapView addAnnotations:self.photos];
                }
            }
        }
        NSLog(@"%@", self.photos);

因为在您的控制台中,这些行在您加载MapView后立即打印

2016-12-09 16:19:42.101997 Pixel[1646:397556] viewForAnnotation called
2016-12-09 16:19:42.102120 Pixel[1646:397556] annotation is the MKUserLocation 

这些行应在 CoreData 结果

之前打印

答案 1 :(得分:0)

我想我明白为什么我现在无法装入我的别针。这条线

 self.photos = (NSArray<Photo<MKAnnotation>*>*)user.photo.allObjects;

尝试将所有photo(MKAnnotation)分配给photos属性,但由于核心数据的错误,实际的“数据”在您访问之前不可用。

解决方案: 创建一个名为MKAnnotation的新PhotoAnnotation类 这是这个类的代码 的 PhotoAnnotation.h

#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>

@interface PhotoAnnotation : NSObject

@property (nonatomic) CLLocationCoordinate2D coordinate;

@property (strong, nonatomic) NSString* thumbnailUrl;

- (id) initWithThumbnailUrl:(CLLocationCoordinate2D)coordinate url: (NSString*) thumbnailUrl;

@end

<强> ## PhotoAnnotation.m

#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#import "PhotoAnnotation.h"

@interface PhotoAnnotation() <MKAnnotation>

@end

@implementation PhotoAnnotation

- (id) initWithThumbnailUrl:(CLLocationCoordinate2D)coordinate url: (NSString*) thumbnailUrl{
    self = [super init];
    if(self){
        self.coordinate = coordinate;
        self.thumbnailUrl = thumbnailUrl;
    }
    return self;
}

@end

像这样分配MKAnnotation

 for(User* user in users){
                    self.photos = [[NSMutableArray alloc] init];
                    for(Photo* photo in user.photo){
                        CLLocationCoordinate2D location = CLLocationCoordinate2DMake(photo.latitude, photo.longitude);
                        PhotoAnnotation* myAnnotation = [[PhotoAnnotation alloc]initWithThumbnailUrl: location url: photo.thumbnailUrl];
                        [self.photos insertObject:myAnnotation atIndex:0];
                    }
                }

这会在地图上成功创建自定义MKAnnotation!