使用 RestKit 映射的 JSON Post 后 TableView 不刷新

Posted

技术标签:

【中文标题】使用 RestKit 映射的 JSON Post 后 TableView 不刷新【英文标题】:TableView not refreshing after JSON Post using RestKit mapping 【发布时间】:2012-06-24 07:18:59 【问题描述】:

我正在使用 RestKit 将 JSON 响应映射到 CoreData。我有一个带有 UITextFields 和“保存”按钮的表格视图,它应该将数据发布到服务器并保存它。服务器数据库已正确更改,但是 tableView 使用旧数据重新加载。只有当我返回并再次进入视图时,才会加载正确的数据。

我花了好几个小时寻找解决方案,但我尝试过的都没有用。如果我将 [self loadData] 放在 POST 行之后,应用程序会崩溃,可能是因为 POST 尚未完成并且存在冲突。如果我将 [self.tableview reloadData] 放在该行中,它也不起作用。

这是我的代码。我使用 NSManagedObject 来保存数据,但将新创建的 NSObject (CommunityOtherProfile) 发送回服务器。

这是我的映射:

    // CommunityProfile Object
RKManagedObjectMapping *profileMapping = [RKManagedObjectMapping mappingForClass:[CommunityProfile class] inManagedObjectStore:objectStore];
profileMapping.primaryKeyAttribute = @"uid";

[profileMapping mapKeyPath:@"uid" toAttribute:@"uid"];
[profileMapping mapKeyPath:@"nickname" toAttribute:@"nickname"];
[profileMapping mapKeyPath:@"hometown" toAttribute:@"hometown"];
[profileMapping mapKeyPath:@"male" toAttribute:@"male"];
[profileMapping mapKeyPath:@"age" toAttribute:@"age"];
[profileMapping mapKeyPath:@"description" toAttribute:@"profileDescription"];


[[RKObjectManager sharedManager].mappingProvider setMapping:profileMapping forKeyPath:@"communityProfile"];

mappingForSerialization = [profileMapping inverseMapping];
[[RKObjectManager sharedManager] setSerializationMIMEType:RKMIMETypeJSON];

[[RKObjectManager sharedManager].mappingProvider setSerializationMapping:mappingForSerialization 
                                                                forClass:[CommunityProfile class]];

[[RKObjectManager sharedManager].router routeClass:[CommunityProfile class] toResourcePath:@"/community/profile/getMyProfile/" forMethod:RKRequestMethodGET];
//[[RKObjectManager sharedManager].router routeClass:[CommunityProfile class] toResourcePath:@"/community/profile/postMyProfile/" forMethod:RKRequestMethodPOST];


// CommunityOtherProfile Object
RKObjectMapping *profileMapping2 = [RKObjectMapping mappingForClass:[CommunityOtherProfile class]];

[profileMapping2 mapKeyPath:@"uid" toAttribute:@"uid"];
[profileMapping2 mapKeyPath:@"nickname" toAttribute:@"nickname"];
[profileMapping2 mapKeyPath:@"hometown" toAttribute:@"hometown"];
[profileMapping2 mapKeyPath:@"male" toAttribute:@"male"];
[profileMapping2 mapKeyPath:@"age" toAttribute:@"age"];
[profileMapping2 mapKeyPath:@"description" toAttribute:@"profileDescription"];

[[RKObjectManager sharedManager].mappingProvider setMapping:profileMapping2 forKeyPath:@""];

mappingForSerialization = [profileMapping2 inverseMapping];
[[RKObjectManager sharedManager] setSerializationMIMEType:RKMIMETypeJSON];

[[RKObjectManager sharedManager].mappingProvider setSerializationMapping:mappingForSerialization 
                                                                forClass:[CommunityOtherProfile class]];

[[RKObjectManager sharedManager].router routeClass:[CommunityOtherProfile class] toResourcePath:@"/community/profile/postMyProfile/" forMethod:RKRequestMethodPOST];

这是 POST 发生的地方:

- (void) save_clicked:(id)sender 

CommunityOtherProfile * newProfile = [[CommunityOtherProfile alloc] init];
NSNumberFormatter * f = [[NSNumberFormatter alloc] init];
[f setNumberStyle:NSNumberFormatterDecimalStyle];
NSNumber * ageNumber = [f numberFromString:age.text];

NSString *tempDescription = @"Platzhalter (noch nicht implementiert!)";

newProfile.male = isMale;
newProfile.profileDescription = tempDescription;
newProfile.nickname = nickname.text;
newProfile.hometown = hometown.text;
newProfile.age = ageNumber;


// post Object
[[RKObjectManager sharedManager] postObject:newProfile usingBlock:^(RKObjectLoader *loader)
    loader.targetObject = nil;
    loader.delegate = profileDataLoader;
];
// I have tried to insert reloadData here 

同一个 TableViewController 类中的其他重要方法:

- (void) refreshView: (id) sender

NSFetchRequest *request = [CommunityProfile fetchRequest];
prof = [[CommunityProfile objectsWithFetchRequest:request] objectAtIndex:0];    

    self.uid = prof.uid;
    self.nickname.text = prof.nickname;
    self.age.text = [NSString stringWithFormat:@"%d", [prof.age intValue]];
    self.hometown.text = prof.hometown;

     //self.description.text = prof.description;

    if(prof.male == [NSNumber numberWithInt:1]) 
        [self clickMale:self.male];
    
    else if(prof.male == [NSNumber numberWithInt:0]) 
        [self clickFemale:self.female];
     
- (void) loadData
profileDataLoader = [[CommunityProfileDataLoader alloc] initWithDelegate:self];
[profileDataLoader loadData];

最后,我的 dataLoader 类:

    //
//  CommunityProfileDataLoader.m
//

#import "CommunityProfileDataLoader.h"
#import "CommunityProfile.h"

@interface AbstractDataLoader()
@property CommunityEditProfileViewController *view;
@end


@implementation CommunityProfileDataLoader

@synthesize responseCode = _responseCode;
@synthesize view;

- (void) loadData
    [super loadData];
    HCLog(DEBUG_MODE,@"Loading Profile Data");
    [[RKObjectManager sharedManager] loadObjectsAtResourcePath:@"/community/profile/getMyProfile/" delegate:self];



- (void) triggerDelegate
    HCLog(DEBUG_MODE,@"CommunityProfileDataLoader Triggering Delegate for %@", [super delegate]);
    [[super delegate] refreshView:self];
 /*...*/

如果你们能帮忙,我会很高兴:)

【问题讨论】:

【参考方案1】:

您的表正在运行一个核心数据支持类 CommunityProfile,但是当您发送 POST 请求时,您只需将新创建的配置文件添加到内存中的类 CommunityOtherProfile。当您尝试在 save_clicked 中重新加载数据时:在请求完成之前没有任何变化。当您稍后返回视图时,请求将返回,您的新对象将在核心数据中,因此在表视图中。

我不建议手动保存它,因为看起来您的 Web 服务将返回 uid 并且您将创建一个副本。 (提示:如果您决定这样做,请将您的 objectloader 的 targetObject 设置为以手动创建的对象为目标!)

我建议您在 Web 服务返回后重新加载表格:

[[RKObjectManager sharedManager] postObject:newProfile usingBlock:^(RKObjectLoader *loader)
    loader.onDidLoadObject = ^(id obj) 
        [self refreshView: nil];
    ;
];

【讨论】:

以上是关于使用 RestKit 映射的 JSON Post 后 TableView 不刷新的主要内容,如果未能解决你的问题,请参考以下文章

在 POST JSON RestKit 中检索 null

使用 RestKit 发送 POST 不会返回 JSON 内容

在其 HTTP 正文中嵌套 JSON 的 RestKit 对象映射请求

带有数组映射的restkit嵌套对象

RestKit 不喜欢为 POST 响应映射不同的对象

使用 RESTKit 映射带有括号的 JSON 响应