UITableView 没有正确填充 NSArray 内容的部分
Posted
技术标签:
【中文标题】UITableView 没有正确填充 NSArray 内容的部分【英文标题】:UITableView not properly populating sections with NSArray contents 【发布时间】:2014-06-23 20:05:41 【问题描述】:我的 Parse 云代码使用以下结构将 JSON 发送回我的 ios 应用程序:
我想要做的是遍历它并在 UITableView 中为 matchCenterArray
中的每个对象创建一个新部分。
在本例中,数组中有三个对象,每个对象都包含一个Top 3
NSDictionary,其值是一个包含 3 个项目的数组,每个项目都是另一个属性数组。如您所见,我希望将其设置为每个部分都有 3 个单元格,每个单元格用于相应 matchCenterArray
对象的前 3 个项目。然后我希望它提取每个项目的属性并将其显示为每个单元格中的texLabel
、detailTextLabel
和缩略图。
我尝试使用 for 循环作为解决方案,但这会在数组的所有单元格中显示相同的项目。这可能是因为我只循环了 matchCenterArray 对象,而不是另外循环了这些对象中的项目,如下所示:
cell.textLabel.text = [[[[_matchCenterArray objectAtIndex:i] objectForKey:@"Top 3"] objectAtIndex:0]objectForKey:@"Title"];
我想做的是在这个循环中嵌套一个 for 循环,代替 objectAtIndex:0
,但是向 for 循环发送消息是行不通的。
MatchCenterViewController.m:
#import "MatchCenterViewController.h"
#import <UIKit/UIKit.h>
@interface MatchCenterViewController () <UITableViewDataSource, UITableViewDelegate>
@property (nonatomic, strong) UITableView *matchCenter;
@end
@implementation MatchCenterViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
return self;
- (void)viewDidLoad
[super viewDidLoad];
self.matchCenter = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewCellStyleSubtitle];
self.matchCenter.frame = CGRectMake(0,50,320,self.view.frame.size.height-100);
_matchCenter.dataSource = self;
_matchCenter.delegate = self;
[self.view addSubview:self.matchCenter];
_matchCenterArray = [[NSArray alloc] init];
- (void)viewDidAppear:(BOOL)animated
self.matchCenterArray = [[NSArray alloc] init];
[PFCloud callFunctionInBackground:@"MatchCenterTest"
withParameters:@
@"test": @"Hi",
block:^(NSArray *result, NSError *error)
if (!error)
_matchCenterArray = result;
[_matchCenter reloadData];
NSLog(@"Result: '%@'", result);
];
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
return _matchCenterArray.count;
//the part where i setup sections and the deleting of said sections
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
return 21.0f;
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 21)];
headerView.backgroundColor = [UIColor lightGrayColor];
// _searchTerm = [[self.matchCenterArray firstObject] objectForKey:@"Search Term"];
UILabel *headerLabel = [[UILabel alloc] initWithFrame:CGRectMake(8, 0, 250, 21)];
// headerLabel.text = [NSString stringWithFormat:@"%@", searchTerm];
// headerLabel.font = [UIFont boldSystemFontOfSize:[UIFont systemFontSize]];
// headerLabel.textColor = [UIColor whiteColor];
headerLabel.backgroundColor = [UIColor lightGrayColor];
[headerView addSubview:headerLabel];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.tag = section + 1000;
button.frame = CGRectMake(300, 2, 17, 17);
[button setImage:[UIImage imageNamed:@"xbutton.png"] forState:UIControlStateNormal];
[button addTarget:self action:@selector(deleteButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
[headerView addSubview:button];
return headerView;
- (IBAction)deleteButtonPressed:(UIButton *)sender
NSLog(@"Search Term: '%@'", _searchTerm);
[PFCloud callFunctionInBackground:@"deleteFromMatchCenter"
withParameters:@
@"searchTerm": _searchTerm,
block:^(NSDictionary *result, NSError *error)
if (!error)
NSLog(@"Result: '%@'", result);
];
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
return 3;
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
// Initialize cell
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell)
// if no cell could be dequeued create a new one
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
for (int i = 0; i<[_matchCenterArray count]; i++)
// populate dictionary with results
//NSDictionary *matchCenterDictionary= [_matchCenterArray objectAtIndex:indexPath.row];
// title of the item
cell.textLabel.text = [[[[_matchCenterArray objectAtIndex:i] objectForKey:@"Top 3"] objectAtIndex:0]objectForKey:@"Title"];
cell.textLabel.font = [UIFont boldSystemFontOfSize:12];
// price of the item
cell.detailTextLabel.text = [NSString stringWithFormat:@"$%@", [[[[_matchCenterArray objectAtIndex:i] objectForKey:@"Top 3"] objectAtIndex:0]objectForKey:@"Price"]];
cell.detailTextLabel.textColor = [UIColor colorWithRed:0/255.0f green:127/255.0f blue:31/255.0f alpha:1.0f];
// image of the item
NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:[[[[_matchCenterArray objectAtIndex:i] objectForKey:@"Top 3"] objectAtIndex:0] objectForKey:@"Image URL"]]];
[[cell imageView] setImage:[UIImage imageWithData:imageData]];
//imageView.frame = CGRectMake(45.0,10.0,10,10);
return cell;
- (void)didReceiveMemoryWarning
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
/*
#pragma mark - Navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
*/
@end
【问题讨论】:
您在使用情节提要吗?此外,它看起来不像在 cellForRowAtIndexPath 中您再次通过 matchCenterArray 进行迭代。它不应该是一个不同的数组吗? matchCenterArray 是您用来创建部分的内容。这可能就是为什么它显示相同的对象 我一般使用故事板,但不是创建UITableView
,这是以编程方式完成的。是的,这就是我想不通的,我正在考虑在其中放置另一个 for 循环,但我不确定如何编写将消息发送到 for 循环的语法。
向 for 循环发送消息是什么意思?你不能只遍历字典中的数组吗?如果可以,请更详细地更新您的答案。
我更新了我的问题来解释我的意思。
我仍然不明白发送消息到 for 循环的事情。我会把每个单元的所有东西都拆开。因此,为 _matchCenterArray 中的每个位置创建一个新的字典实例,然后创建一个与字典中的键匹配的新数组,然后从新数组中加载标签值。每个单元格都会有新的对象来简化你的遍历。您可以嵌套 for 循环,然后在最里面的循环中吐出单元格。
【参考方案1】:
忘掉循环吧,委托方法已经在迭代次数等于数据源计数的循环上运行了。
numberOfSectionsInTableView
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
return _matchCenterArray.count;
numberOfRowsInSection
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section
return _matchCenterArray[section][@"Top 3"].count;
cellForRowAtIndexPath
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
// Initialize cell
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell)
// if no cell could be dequeued create a new one
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:CellIdentifier];
// title of the item
cell.textLabel.text = _matchCenterArray[indexPath.section][@"Top 3"][indexPath.row][@"Title"];
cell.textLabel.font = [UIFont boldSystemFontOfSize:12];
// price of the item
cell.detailTextLabel.text = [NSString stringWithFormat:@"$%@", _matchCenterArray[indexPath.section][@"Top 3"][indexPath.row][@"Price"];
cell.detailTextLabel.textColor = [UIColor colorWithRed:0/255.0f green:127/255.0f blue:31/255.0f alpha:1.0f];
// image of the item
NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:_matchCenterArray[indexPath.section][@"Top 3"][indexPath.row][@"Image URL"]]];
[[cell imageView] setImage:[UIImage imageWithData:imageData]];
return cell;
不要对您的数组计数进行硬编码,如果您的 json 更改,您的代码将需要更改。
以后您应该考虑使用像 SDWebImage 这样的库来异步加载图像以避免延迟。
【讨论】:
【参考方案2】:cellForRowAtIndexPath:
每个 numberOfRowsInSection:
调用一次
您还需要添加numberOfSections
:
应该是这样的:
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
return 3;
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
// Initialize cell
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell)
// if no cell could be dequeued create a new one
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
// the following will set the cell attributes for cells in each section
// to customize per section, use indexPath.section to get which section you are at
// title of the item
cell.textLabel.text = [[[[_matchCenterArray objectAtIndex:indexPath.row objectForKey:@"Top 3"] objectAtIndex:0]objectForKey:@"Title"];
cell.textLabel.font = [UIFont boldSystemFontOfSize:12];
// price of the item
cell.detailTextLabel.text = [NSString stringWithFormat:@"$%@", [[[[_matchCenterArray objectAtIndex:indexPath.row] objectForKey:@"Top 3"] objectAtIndex:0]objectForKey:@"Price"]];
cell.detailTextLabel.textColor = [UIColor colorWithRed:0/255.0f green:127/255.0f blue:31/255.0f alpha:1.0f];
// image of the item
NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:[[[[_matchCenterArray objectAtIndex:indexPath.row] objectForKey:@"Top 3"] objectAtIndex:0] objectForKey:@"Image URL"]]];
[[cell imageView] setImage:[UIImage imageWithData:imageData]];
return cell;
请参考apple's tableView guide
【讨论】:
以上是关于UITableView 没有正确填充 NSArray 内容的部分的主要内容,如果未能解决你的问题,请参考以下文章
如何从使用 JSONKit 创建的 NSDictionary 中正确填充 UITableView NSArray?
使用 NSUserdefaults 填充 UITableView