JSON请求后以编程方式TableView不会重新加载数据
Posted
技术标签:
【中文标题】JSON请求后以编程方式TableView不会重新加载数据【英文标题】:Programmatically TableView won't reloadData after JSON request 【发布时间】:2013-08-30 17:37:01 【问题描述】:我正在尝试使用有效的 TableView 填充 KGModal 视图 (https://github.com/kgn/KGModal),但在通过 JSON 获取数据后我无法重新加载数据,而不会导致应用崩溃。
cellForRowAtIndexPath
方法正在正确返回 JSON 结果,我认为问题出在 reloadData 方法中,因为 _tv 已被 KGModal 使用? itemNutriFeed.*
只是一个 JSON 模型。
//itemNutriModal.h
#import <UIKit/UIKit.h>
@interface itemNutriModal : UIViewController <UITableViewDataSource, UITableViewDelegate>
- (void)showNutri; //:(NSArray*)nutri;
@end
//itemNutriModal.m
#import "itemNutriModal.h"
#import "JSONModelLib.h"
#import "itemNutriFeed.h"
#import "KGModal.h"
@interface itemNutriModal ()
itemNutriFeed* _feed;
UITableView* _tv;
@end
@implementation itemNutriModal
- (void)didReceiveMemoryWarning
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
- (void)showNutri //:(NSArray*)nutri
_tv = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 200, 400)];
_tv.backgroundColor = [UIColor clearColor];
_tv.scrollEnabled = FALSE;
[_tv setDataSource:self];
[_tv setDelegate:self];
[[KGModal sharedInstance] showWithContentView:_tv andAnimated:YES];
_feed = [[itemNutriFeed alloc] initFromURLWithString:@"http://c..../.../nutri.php?inid=1000"
completion:^(JSONModel *model, JSONModelError *err)
//hide the loader view
//[HUD hideUIBlockingIndicator];
//json fetched
NSLog(@"Results: %@", _feed.results);
[_tv reloadData];
];
//;
//NSLog(@"SHOW NUTRIS!");
#pragma mark - TableView
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
return 8;
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
return 1;
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
static NSString *CellIdentifier = @"nutriTableCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
cell = [[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleValue1
reuseIdentifier:CellIdentifier];
itemNutriModel* nutrivals = _feed.results[indexPath.row];
NSLog(@"nutrivals: %@", _feed.results);
cell.backgroundColor = [UIColor clearColor];
[cell.textLabel setTextColor:[UIColor whiteColor]];
[cell.textLabel setText:[NSString stringWithFormat:@"%@", nutrivals.type]];
[cell.detailTextLabel setText:[NSString stringWithFormat:@"%@", nutrivals.value]];
return cell;
@end
在 JSON 完成方法中放置 [[KGModal sharedInstance] showWithContentView:_tv andAnimated:YES];
也会崩溃。
崩溃表明 EXC_BAD_ACCESS;
2013-08-30 19:13:56.634 xapp[91159:a0b] *** -[itemNutriModal tableView:cellForRowAtIndexPath:]: message sent to deallocated instance 0xd8add90
---- 第一个 cellForRowAtIndexPath 调用的堆栈跟踪(有效)----
2013-08-30 19:34:00.229 xapp[91619:a0b] Stack trace : (
0 xapp 0x0002dec3 -[itemNutriModal showNutri] + 483
1 xapp 0x0001a60f -[favouritesTableViewController tableView:accessoryButtonTappedForRowWithIndexPath:] + 175
2 UIKit 0x009baa25 -[UITableView _accessoryButtonAction:] + 310
3 libobjc.A.dylib 0x01b7c874 -[NSObject performSelector:withObject:withObject:] + 77
4 UIKit 0x008e424c -[UIApplication sendAction:to:from:forEvent:] + 108
5 UIKit 0x008e41d8 -[UIApplication sendAction:toTarget:fromSender:forEvent:] + 61
6 UIKit 0x009daa5d -[UIControl sendAction:to:forEvent:] + 66
7 UIKit 0x009dae20 -[UIControl _sendActionsForEvents:withEvent:] + 577
8 UIKit 0x009da0cf -[UIControl touchesEnded:withEvent:] + 641
9 UIKit 0x00c5440f _UIGestureRecognizerUpdate + 7166
10 UIKit 0x00920e9a -[UIWindow _sendGesturesForEvent:] + 1291
11 UIKit 0x00921dba -[UIWindow sendEvent:] + 1030
12 UIKit 0x008f5b86 -[UIApplication sendEvent:] + 242
13 UIKit 0x008e035f _UIApplicationHandleEventQueue + 11421
14 CoreFoundation 0x01d7396f __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 15
15 CoreFoundation 0x01d732fb __CFRunLoopDoSources0 + 235
16 CoreFoundation 0x01d903ce __CFRunLoopRun + 910
17 CoreFoundation 0x01d8fbf3 CFRunLoopRunSpecific + 467
18 CoreFoundation 0x01d8fa0b CFRunLoopRunInMode + 123
19 GraphicsServices 0x03125a27 GSEventRunModal + 192
20 GraphicsServices 0x0312584e GSEventRun + 104
21 UIKit 0x008e2f0b UIApplicationMain + 1225
22 xapp 0x0001313d main + 141
23 libdyld.dylib 0x03d05725 start + 0
)
---- 从 JSON 完成调用第二个 cellForRowAtIndexPath 的堆栈跟踪(异常)----
2013-08-30 19:34:00.332 xapp[91619:a0b] Stack trace : (
0 xapp 0x0002e1a6 __27-[itemNutriModal showNutri]_block_invoke + 230
1 xapp 0x0000b3d0 __58-[JSONModel(Networking) initFromURLWithString:completion:]_block_invoke_2 + 112
2 libdispatch.dylib 0x03a60818 _dispatch_call_block_and_release + 15
3 libdispatch.dylib 0x03a754b0 _dispatch_client_callout + 14
4 libdispatch.dylib 0x03a62a0e _dispatch_after_timer_callback + 98
5 libdispatch.dylib 0x03a754b0 _dispatch_client_callout + 14
6 libdispatch.dylib 0x03a6be6b _dispatch_source_latch_and_call + 150
7 libdispatch.dylib 0x03a66443 _dispatch_source_invoke + 411
8 libdispatch.dylib 0x03a636f6 _dispatch_main_queue_callback_4CF + 228
9 CoreFoundation 0x01e4fb6e __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 14
10 CoreFoundation 0x01d907eb __CFRunLoopRun + 1963
11 CoreFoundation 0x01d8fbf3 CFRunLoopRunSpecific + 467
12 CoreFoundation 0x01d8fa0b CFRunLoopRunInMode + 123
13 GraphicsServices 0x03125a27 GSEventRunModal + 192
14 GraphicsServices 0x0312584e GSEventRun + 104
15 UIKit 0x008e2f0b UIApplicationMain + 1225
16 xapp 0x0001313d main + 141
17 libdyld.dylib 0x03d05725 start + 0
)
【问题讨论】:
只是一个猜测,因为您决定通过不包括崩溃细节来强迫人们猜测,您的tableView:numberOfRowsInSection:
返回 8,它应该返回您的数据的实际计数,而不是硬编码常量。
抱歉,添加了异常,但调试对我来说是新的。
“完成 JSON 查询后”——具体是什么意思?哪条线?它在您的代码中,一些框架代码吗?你有堆栈跟踪吗?你启用僵尸了吗?
谢谢,已经添加了具体的错误和堆栈跟踪。
参考这个How to reloadData for tableview after data been prepared in a asynchronously method
【参考方案1】:
一旦您分配了数据源/委托,tableview 就会查询它的数据。您的 JSON 回调可能尚未完成运行。您需要检查它是否已完成,如果尚未完成则返回 0 行。如果您在 JSON 查询实际完成之前返回 8 行,您将崩溃。检查_feed中是否有numberOfRowsInSection中的数据,如果没有则返回0。
【讨论】:
返回 8 只是为了调试。在 JSON 完成设置 dataSource/delegate:self 时(但在 KGModal 中使用 _tv 之后),不会调用数据源方法。返回 _feed.results.count(未完成时为 0)显示一个带有单元格的模态框,但 _tv dataReload 仍然崩溃。 如果你稍后设置datasource/delegate,之后你将不得不手动调用reloadData。 试过了,reloadData 还是有问题,和主要问题一样。【参考方案2】:似乎这是 KGModal 的问题 - 分配给 KGModal 对象时视图/控制器的解除分配意味着它不能再被 reloadData 命令操作。
我解决这个问题的方法是制作我自己的自定义 UIScrollView,在分配给模式窗口之前填充它。
【讨论】:
以上是关于JSON请求后以编程方式TableView不会重新加载数据的主要内容,如果未能解决你的问题,请参考以下文章
首次加载后以编程方式突出显示 tableview 中的第一行
UITableView 滚动后以编程方式创建的 UITableViewCell 未正确显示
iOS UITableView 在设置 TableHeaderView 后以编程方式覆盖自动布局约束