2

私のアプリでは、マップ上にあるピンを保存して、ユーザーがアプリを終了した後に開いたときにピンが表示されるようにしようとしています。mkAnnotationクラスをNSCodingに準拠させ、2つの必須メソッドを実装しました。アノテーションはすべてシングルトンクラスのNSMutableArrayに格納されているため、実際には配列をシングルトンクラスに保存しようとしています。すべてが正常にエンコードされていますが、デコードされているとは思いません。ここにいくつかのコードがあります:これは私のMKAnnotationクラスです:

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

@interface MapPoint : NSObject <MKAnnotation, NSCoding>
{
}

- (id)initWithAddress:(NSString*)address
        coordinate:(CLLocationCoordinate2D)coordinate
                title:(NSString *)t;

@property (nonatomic, readwrite) CLLocationCoordinate2D coordinate;

//This is an optional property from MKAnnotataion
@property (nonatomic, copy) NSString *title;
@property (nonatomic, readonly, copy) NSString *subtitle;
@property (nonatomic) BOOL animatesDrop;
@property (nonatomic) BOOL canShowCallout;

@property (copy) NSString *address;
@property (nonatomic, copy) NSString *imageKey;
@property (nonatomic, copy) UIImage *image;

@end 

@implementation MapPoint

@synthesize title, subtitle, animatesDrop, canShowCallout, imageKey, image;
@synthesize address = _address, coordinate = _coordinate;

-(id)initWithAddress:(NSString *)address
       coordinate:(CLLocationCoordinate2D)coordinate
            title:(NSString *)t {
    self = [super init];

    if (self) {
        _address = [address copy];
        _coordinate = coordinate;

        [self setTitle:t];

        NSDate *theDate = [NSDate date];

        subtitle = [NSDateFormatter localizedStringFromDate:theDate
                                                  dateStyle:NSDateFormatterShortStyle
                                                  timeStyle:NSDateFormatterShortStyle];
    }
    return self;
}

- (void)encodeWithCoder:(NSCoder *)aCoder {

    [aCoder encodeObject:_address forKey:@"address"];

    NSLog(@"ENCODING coordLatitude %f coordLongitude %f ", _coordinate.latitude, _coordinate.longitude);
    [aCoder encodeDouble:_coordinate.longitude forKey:@"coordinate.longitude"];
    [aCoder encodeDouble:_coordinate.latitude forKey:@"coordinate.latitude"];

    [aCoder encodeObject:title forKey:@"title"];
}

- (id)initWithCoder:(NSCoder *)aDecoder {
    self = [super init];
    if (self) {
        [self setAddress:[aDecoder decodeObjectForKey:@"address"]];

        NSLog(@"DECODING coordLatitude %f coordLongitude %f ", _coordinate.latitude, _coordinate.longitude);
        _coordinate.longitude = [aDecoder decodeDoubleForKey:@"coordinate.longitude"];
        _coordinate.latitude = [aDecoder decodeDoubleForKey:@"coordinate.latitude"];

        [self setTitle:[aDecoder decodeObjectForKey:@"title"]];
    }
    return self;
}

@end

これが私のシングルトンクラスです:

#import <Foundation/Foundation.h>
@class MapPoint;

@interface Data : NSObject
{
NSMutableArray *_annotations;
}

@property (retain, nonatomic) NSMutableArray *annotations;

+ (Data *)singleton;
- (NSString *)pinArchivePath;
- (BOOL)saveChanges;

@end

@implementation Data

@synthesize annotations = _annotations;

+ (Data *)singleton {
    static dispatch_once_t pred;
    static Data *shared = nil;
    dispatch_once(&pred, ^{
        shared = [[Data alloc] init];
        shared.annotations = [[NSMutableArray alloc]init];
    });
    return shared;
}

- (id)init {
    self = [super init];
    if (self) {
        NSString *path = [self pinArchivePath];
        _annotations = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
        if (!_annotations) {
            _annotations = [[NSMutableArray alloc]init];
        }
    }
    return self;
}

- (NSString *)pinArchivePath {
    NSArray *cachesDirectories = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);

    NSString *cachesDirectory = [cachesDirectories objectAtIndex:0];

    return [cachesDirectory stringByAppendingPathComponent:@"pins.archive"];
}

- (BOOL)saveChanges {
    NSString *path = [self pinArchivePath];

    return [NSKeyedArchiver archiveRootObject:[Data singleton].annotations
                                       toFile:path];
}

@end

マップビューコントローラのviewDidLoadメソッドで、次のようにマップ上のシングルトン配列に注釈を配置しようとします。

for (MapPoint *mp in [Data singleton].annotations) {
        [_worldView addAnnotation:mp];
}
4

1 に答える 1

1

主な問題は、singleton次の行のメソッドにあります。

dispatch_once(&pred, ^{
    shared = [[Data alloc] init];
    shared.annotations = [[NSMutableArray alloc]init]; //<-- problem line
});

この行は、配列shared = [[Data alloc] init];をデコードして初期化します。annotations

次に、行は配列をshared.annotations = [[NSMutableArray alloc]init];再作成して再初期化し、デコードされたばかりの注釈を破棄して、シングルトンが常に空の配列を返すようにします。annotations

行を削除しshared.annotations = [[NSMutableArray alloc]init];ます。


コメントですでに述べたように、単に混乱を引き起こす他の小さな問題はNSLog、座標がデコードされている場所の配置です。デコードが完了した後NSLogなければなりません。

于 2013-01-12T14:29:11.393 に答える