如何在具有transient属性的NSManagedObject子类上实现MKAnnotation

时间:2015-09-11 00:47:01

标签: ios core-data struct mkannotation transient

我在名为Restaurant的NSManagedObject子类上有以下MKAnnotation协议实现:

接口:

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


@interface Restaurant : NSManagedObject <MKAnnotation> {
    CLLocationCoordinate2D coordinate;
}

@property (nonatomic, assign) CLLocationCoordinate2D primitiveCoordinate;
@property (nonatomic, copy) NSString * title;
@property (nonatomic, copy) NSString * subtitle;
@property (nonatomic, retain) NSNumber * longtitude;
@property (nonatomic, retain) NSNumber * latitude;

@end

实现:

#import "Restaurant.h"


@implementation Restaurant

@dynamic title;
@dynamic subtitle;
@dynamic coordinate;
@dynamic longtitude;
@dynamic latitude;

-(void)setCoordinate:(CLLocationCoordinate2D)newCoordinate{
    [self willChangeValueForKey:@"coordinate"];
    [self setPrimitiveCoordinate:newCoordinate];
    [self didChangeValueForKey:@"coordinate"];
    [self setValue:[NSNumber numberWithDouble:newCoordinate.latitude] forKey:@"latitude"];
    [self setValue:[NSNumber numberWithDouble:newCoordinate.longitude] forKey:@"longtitude"];
}

-(CLLocationCoordinate2D)coordinate{
    [self willAccessValueForKey:@"coordinate"];
    CLLocationCoordinate2D temp = [self primitiveCoordinate];
    [self didAccessValueForKey:@"coordinate"];
    return temp;
}

-(void)setPrimitiveCoordinate:(CLLocationCoordinate2D)primitiveCoordinate{
    coordinate = primitiveCoordinate;
}

-(CLLocationCoordinate2D)primitiveCoordinate{

    return coordinate;
}

-(void)awakeFromFetch{
    [super awakeFromFetch];

    double longtitude = [[self longtitude] doubleValue];
    double latitude = [[self latitude] doubleValue];

    if(!isnan(longtitude) && !isnan(latitude)){
        CLLocationCoordinate2D temp = CLLocationCoordinate2DMake(latitude, longtitude);
        [self setPrimitiveCoordinate:temp];
    }

}

@end

我跟着Apples Core Data programming guide关于非标准持久性属性和documentation of the MKAnnotation protocol来实现MKAnnotation的CLocation2DCoordinate属性作为瞬态实例变量,因为Core Data不支持存储C结构。

我的问题是:这个实现是正确的还是你在我的实现中改变了什么?也许使用NSValue来存储C结构而不是NSNumber个对象(latitudelongtitude)?使用NSValue代替哪些优点和缺点?其余的代码怎么样?

谢谢!

1 个答案:

答案 0 :(得分:0)

将坐标作为瞬态实现的问题是,当设置纬度或经度时,将不会触发坐标KVO。因此,您最好将其实现为计算属性。您还缺少awakeFromSnapshotEvents,当子上下文保存到没有更新过的经度或纬度的餐厅时,如果您没有keyPathsForValuesAffecting会自动为您完成此操作,则更新{@ 1}是必需的。

对于计算属性,它是:

// this means setting latitude or longitude causes coordinate KVO notification to be sent which the map is observing.
+ (NSSet<NSString *> *)keyPathsForValuesAffectingCoordinate
{
    return [NSSet setWithObjects:@"latitude", @"longitude", nil];
}

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

- (void)setCoordinate:(CLLocationCoordinate2D)newCoordinate{
    self.latitude = newCoordinate.latitude;
    self.longitude = newCoordinate.longitude;
}

乍看之下,似乎setCoordinate发送过多通知存在问题,但是地图实际上在下一个runloop上更新了其注释视图,所以没关系。