ruby-on-rails – iOS核心数据:为Rails多态关联设置关系的方法
我有一个iOS应用程序,其核心数据模型模仿我的Rails后端数据模型.在我的Rails后端模型中,我使用了多个实体的多态关联.我的Rails模型看起来像这样:
Airport < ActiveRecord::Base has_many :reviews,:as => :reviewable Restaurant < ActiveRecord::Base has_many :reviews,:as => :reviewable Review < ActiveRecord::Base belongs_to :reviewable,:polymorphic => :true 在我的核心数据模型中,我有三个独立的实体,MyAirport,MyRestaurant和MyReview,具有如下所示的相关属性: MyAirport @property (nonatomic,retain) NSSet* reviews; //inverse is airport MyRestaurant @property (nonatomic,retain) NSSet* reviews; //inverse is restaurant MyReview @property (nonatomic,retain) NSNumber* reviewablId; @property (nonatomic,retain) NSString* reviewableType; @property (nonatomic,retain) MyAirport* airport; //inverse is reviews @property (nonatomic,retain) MyRestaurant* restaurant; //inverse is reviews 我的问题与Core Data中的MyReview类有关.根据reviewableId和reviewableType中的值设置正确的核心数据关系(例如机场或餐厅)的最佳方法是什么? 我尝试过以下内容,但出于某种原因,所有人都显得有点不洁净.一般来说,在设置正确的关联之前,我需要确保我有可用的reviewableId和reviewableType,这似乎是与感知清洁度相关的主要问题.在从JSON中保护这些模型对象时,我并没有真正控制在新的MyReview对象上填充reviewableId和reviewableType的顺序. 1)在reviewableId和reviewableType中的一个或两个上的自定义setter – 我最终在每个setter方法中使用逻辑来检查其他属性的值,以确保在我可以在MyReview模型对象上设置机场或餐馆关系之前填充它.一般来说,这是有效的,但它感觉不对,同时在每个setter中也有一些丑陋的重复代码. - (void)setReviewableId:(NSNumber*)reviewableId { [self willChangeValueForKey:@"reviewableId"]; [self setPrimitiveReviewableId:reviewableId]; [self didChangeValueForKey:@"reviewableId"]; if (reviewableId && [reviewableId intValue] != 0 && self.reviewableType) { if (self.airport == nil && [self.reviewableType isEqualToString:@"Airport"]) { MyAirport myAirport = <... lookup MyAirport by airportId = reviewableId ...> if (myAirport) { self.airport = myAirport; } } else if (self.restaurant == nil && [self.reviewableType isEqualToString:@"Restaurant"]) { MyRestaurant myRestaurant = <... lookup MyRestaurant by restaurantId = reviewableId ...> if (myRestaurant) { self.restaurant = myRestaurant; } } } } - (void)setReviewableType:(NSString*)reviewableType { [self willChangeValueForKey:@"reviewableType"]; [self setPrimitiveReviewableType:reviewableType]; [self didChangeValueForKey:@"reviewableType"]; if (self.reviewableId && [self.reviewableId intValue] != 0 && reviewableType) { if (self.airport == nil && [reviewableType isEqualToString:@"Airport"]) { MyAirport myAirport = <... lookup MyAirport by airportId = self.reviewableId ...> if (myAirport) { self.airport = myAirport; } } else if (self.restaurant == nil && [reviewableType isEqualToString:@"Restaurant"]) { MyRestaurant myRestaurant = <... lookup MyRestaurant by restaurantId = self.reviewableId ...> if (myRestaurant) { self.restaurant = myRestaurant; } } } } 2)关于reviewableId和reviewableType的KVO – 在awakeFromInsert和awakeFromFetch中,我通过KVO将模型对象注册到观察者自己的reviewableId和reviewableType属性.这个对象观察自己感觉真的很难看,但至少我有一个处理填充关联的方法,这似乎比#1有点改进.请注意,我最终在这里使用removeObserver:forKeyPath:在dealloc方法中遇到了一些崩溃(例如崩溃表明我已经删除了一个不存在的观察者?),所以这远远不是经验证的代码. - (void)awakeFromFetch { [super awakeFromFetch]; [self addObserver:self forKeyPath:@"reviewableId" options:0 context:nil]; [self addObserver:self forKeyPath:@"reviewableType" options:0 context:nil]; } - (void)awakeFromInsert { [super awakeFromInsert]; [self addObserver:self forKeyPath:@"reviewableId" options:0 context:nil]; [self addObserver:self forKeyPath:@"reviewableType" options:0 context:nil]; } - (void)dealloc { [self removeObserver:self forKeyPath:@"reviewableId"]; [self removeObserver:self forKeyPath:@"reviewableType"]; [super dealloc]; } - (void)updatePolymorphicAssociations { if (self.reviewableId && [self.reviewableId intValue] != 0 && self.reviewableType) { if (self.airport == nil && [self.reviewableType isEqualToString:@"Airport"]) { MyAirport myAirport = <... lookup MyAirport by airportId = self.reviewableId ...> if (myAirport) { self.airport = myAirport; } } else if (self.restaurant == nil && [self.reviewableType isEqualToString:@"Restaurant"]) { MyRestaurant myRestaurant = <... lookup MyRestaurant by restaurantId = self.reviewableId ...> if (myRestaurant) { self.restaurant = myRestaurant; } } } } - (void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary*)change context:(void*)context { [self updatePolymorphicAssociations]; } 3)使用上面的updatePolymorphicAssociations方法覆盖willSave.这似乎有效,但它推迟了对关联的所有更改,直到我们去保存对象,这通常不是我们对reviewableId和reviewableType进行初始更改时.这里似乎也存在一些限制,涉及通过后台线程插入一堆新的MyReview对象,可能与willSave相关,实际上导致我们刚刚保存的对象的更改,从而再次触发willSave.即使在updatePolymorphicAssociations中进行nil检查,我仍然可以使用这种方法使应用程序崩溃. - (void)updatePolymorphicAssociations { if (self.reviewableId && [self.reviewableId intValue] != 0 && self.reviewableType) { if (self.airport == nil && [self.reviewableType isEqualToString:@"Airport"]) { MyAirport myAirport = <... lookup MyAirport by airportId = self.reviewableId ...> if (myAirport) { self.airport = myAirport; } } else if (self.restaurant == nil && [self.reviewableType isEqualToString:@"Restaurant"]) { MyRestaurant myRestaurant = <... lookup MyRestaurant by restaurantId = self.reviewableId ...> if (myRestaurant) { self.restaurant = myRestaurant; } } } } - (void)willSave { [self updatePolymorphicAssociations]; } 4)覆盖didSave,而不是willSave.这解决了我们在#3中使用后台进行大量导入的保存问题,但随后我们最终得到了未保存的更改,这很难看. 所以,我似乎在这里有很多选项,但是没有人能够解决在使用由Rails云数据库支持的Core Data的iOS应用程序中看起来常见的问题.我是否过度分析了这个?或者,还有更好的方法? 更新:请注意,目标是根据reviewableType是“Airport”还是“Restaurant”,仅在MyReview上设置其中一个关系.这种关系设置本身就很难看,但这就是我问这个问题的原因. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |