MagicalRecord 调用多个保存方法
Posted
技术标签:
【中文标题】MagicalRecord 调用多个保存方法【英文标题】:MagicalRecord call multiple save methods 【发布时间】:2015-05-27 14:19:48 【问题描述】:我是 MagicalRecord 的新手。我从不同的方法更新相同的实体时遇到问题。这是我的例子:我有一些从网络服务获得的广告。完成后,如果有任何将它们的活动属性设置为 0,我需要更新数据库中的广告。立即,我需要调用保存我的广告的函数或只更新它们。之后,我需要删除所有过期的广告,然后删除不活动的广告。这些广告实际上是基于语言的,所以每次我更改应用程序的语言时,一些广告就会变得无效。它需要是这样的。这是我的保存和删除代码:
- (void) saveBanners:(NSDictionary *)activeBanner
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss"];
if (activeBanner != nil || [activeBanner count] != 0)
for (int i = 0; i<[activeBanner.banners count]; i++)
NSDate *dateTo = [formatter dateFromString:[activeBanner.banners[i] DateValidTo]];
NSDate *dateFrom = [formatter dateFromString:[activeBanner.banners[i] DateValidFrom]];
NSLog(@"%@ %@", dateTo, [activeBanner.banners[i] DateValidTo]);
[MagicalRecord
saveWithBlock:^(NSManagedObjectContext *localContext)
Banner *banner = [Banner MR_findFirstByAttribute:@"serverId" withValue:[activeBanner.banners[i] ID] inContext:localContext];
Banner *localBanner;
if (banner != nil)
localBanner = [banner MR_inContext:localContext];
else
localBanner = [Banner MR_createInContext:localContext];
localBanner.serverId = [activeBanner.banners[i] ID];
localBanner.name = [activeBanner.banners[i] Name];
localBanner.text = [activeBanner.banners[i] BannerText];
localBanner.dateFrom = dateFrom;
localBanner.dateTo = dateTo;
localBanner.image = [activeBanner.banners[i] ImageData];
localBanner.active = [NSNumber numberWithBool:YES];
localBanner.country = [activeBanner.banners[i] CountryCode];
];
- (void)setBannerInactive:(NSString *)country
NSPredicate *bannerFilter = [NSPredicate predicateWithFormat:@"country IN %@", @[[country uppercaseString]]]; // paziti na upperCase, tako vraca u bazi
NSArray *banners = [Banner MR_findAllWithPredicate:bannerFilter];
NSNumber *bannersCount = [Banner MR_numberOfEntitiesWithPredicate:bannerFilter];
if (bannersCount.integerValue != 0)
for (int i = 0; i < bannersCount.integerValue; i++)
[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext)
Banner *banner = [Banner MR_findFirstByAttribute:@"serverId" withValue:[banners[i] serverId] inContext:localContext];
if (banner != nil)
Banner *localBanner = [banner MR_inContext:localContext];
localBanner.active = [NSNumber numberWithBool:NO];
completion:^(BOOL success, NSError *error)
NSLog(@"I am here");
];
- (void)deleteInactiveBanners
NSPredicate *inactiveBannerFilter = [NSPredicate predicateWithFormat:@"active = NO"]; // NO = neaktivni
NSArray *banners = [Banner MR_findAllWithPredicate:inactiveBannerFilter];
if (banners != nil || [banners count] != 0)
for (int i = 0; i < [banners count]; i++)
Banner *banner = banners[i];
if (banner != nil)
[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext)
Banner *localBanner = [banner MR_inContext:localContext];
[localBanner MR_deleteEntity];
];
我在我的视图控制器中从我的视图模型中调用它们,在我的 RAC 信号的完整块中获取我的广告:
[self.viewModel setBannerInactive:appLanguage];
if (self.viewModel.activeBanner != nil)
[self.viewModel saveBanner:self.splashViewModel.activeBanner];
[self.viewModel deleteInactiveBanners];
我知道 saveWithBlocks 是在后台线程中执行的。问题是当我调用 setBannerInactive 时,它在调用 saveBanners 时并未完成,因此一切都无法正常工作。如何使用 MagicalRecord 正确调用这些方法。我使用的是最新的 2.x MagicalRecord,而不是 v3。?
【问题讨论】:
【参考方案1】:类似的东西(我没有尝试也没有尝试编译它,所以它可能包含错误但想法就在那里)
- (void) saveBanners:(NSDictionary *)activeBanner withCompletion:(void(^)())completionBlock
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss"];
if (activeBanner != nil || [activeBanner count] != 0)
for (int i = 0; i<[activeBanner.banners count]; i++)
NSDate *dateTo = [formatter dateFromString:[activeBanner.banners[i] DateValidTo]];
NSDate *dateFrom = [formatter dateFromString:[activeBanner.banners[i] DateValidFrom]];
NSLog(@"%@ %@", dateTo, [activeBanner.banners[i] DateValidTo]);
[MagicalRecord
saveWithBlock:^(NSManagedObjectContext *localContext)
Banner *banner = [Banner MR_findFirstByAttribute:@"serverId" withValue:[activeBanner.banners[i] ID] inContext:localContext];
Banner *localBanner;
if (banner != nil)
localBanner = [banner MR_inContext:localContext];
else
localBanner = [Banner MR_createInContext:localContext];
localBanner.serverId = [activeBanner.banners[i] ID];
localBanner.name = [activeBanner.banners[i] Name];
localBanner.text = [activeBanner.banners[i] BannerText];
localBanner.dateFrom = dateFrom;
localBanner.dateTo = dateTo;
localBanner.image = [activeBanner.banners[i] ImageData];
localBanner.active = [NSNumber numberWithBool:YES];
localBanner.country = [activeBanner.banners[i] CountryCode];
completion:^(BOOL success, NSError *error)
if(completionBlock)
completionBlock();
NSLog(@"I am here");
];
- (void)setBannerInactive:(NSString *)country withCompletion:(void(^)())completionBlock
NSPredicate *bannerFilter = [NSPredicate predicateWithFormat:@"country IN %@", @[[country uppercaseString]]]; // paziti na upperCase, tako vraca u bazi
NSArray *banners = [Banner MR_findAllWithPredicate:bannerFilter];
NSNumber *bannersCount = [Banner MR_numberOfEntitiesWithPredicate:bannerFilter];
if (bannersCount.integerValue != 0)
for (int i = 0; i < bannersCount.integerValue; i++)
[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext)
Banner *banner = [Banner MR_findFirstByAttribute:@"serverId" withValue:[banners[i] serverId] inContext:localContext];
if (banner != nil)
Banner *localBanner = [banner MR_inContext:localContext];
localBanner.active = [NSNumber numberWithBool:NO];
completion:^(BOOL success, NSError *error)
NSLog(@"I am here");
if(completionBlock)
completionBlock();
];
- (void)deleteInactiveBanners withCompletion:(void(^)())completionBlock
NSPredicate *inactiveBannerFilter = [NSPredicate predicateWithFormat:@"active = NO"]; // NO = neaktivni
NSArray *banners = [Banner MR_findAllWithPredicate:inactiveBannerFilter];
if (banners != nil || [banners count] != 0)
for (int i = 0; i < [banners count]; i++)
Banner *banner = banners[i];
if (banner != nil)
[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext)
Banner *localBanner = [banner MR_inContext:localContext];
[localBanner MR_deleteEntity];
completion:^(BOOL success, NSError *error)
NSLog(@"I am here");
if(completionBlock)
completionBlock();
];
这样使用
[self.viewModel setBannerInactive:appLanguage withCompletion:^()
if (self.viewModel.activeBanner != nil)
[self.viewModel saveBanner:self.splashViewModel.activeBanner withCompletion:^()
[self.viewModel deleteInactiveBanners withCompletion:nil];
];
else
[self.viewModel deleteInactiveBanners withCompletion:nil];
];
【讨论】:
你的回答对我有帮助,所以我会支持你以上是关于MagicalRecord 调用多个保存方法的主要内容,如果未能解决你的问题,请参考以下文章
导入时保存所有内容之前的 MagicalRecord 完成块
MagicalRecord 2.3.0/3.0 在对象内保存对象
在 for 循环中传递数据时,MagicalRecord 正在保存 null