【问题标题】:Create section in TableView from NSDictionary从 NSDictionary 在 TableView 中创建部分
【发布时间】:2013-06-23 14:01:03
【问题描述】:

我正在从服务器获取表数据。它是一个 JSON 数据,每个数组都保存为字典。我有一个 JSON 对象数组。

JSON 是:

{
    sAlbum = Fallen;
    sArtist = Evanescence;
    sId = 1;
    sRate = 3;
    stitle = "Everybody's Fool";
},
    {
    sAlbum = Fallen;
    sArtist = Evanescence;
    sId = 2;
    sRate = 4;
    stitle = "Going Under";
}

当我拥有它时,我会使用(使用 AFnetwrking)

[AFJSONRequestOperation JSONRequestOperationWithRequest:request
 // The success block runs when (surprise!) the request succeeds.
                                                success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {

                                                    self.musicLibraryArr  = [(NSDictionary*)JSON  objectForKey:@"array"];


                                                    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"stitle" ascending: YES];
                                                    NSArray *sortedArray = [self.musicLibraryArr sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];

                                                    self.musicLibraryArr = [[NSMutableArray alloc] initWithArray:sortedArray];

                                                    self.loadingView.hidden = YES;

                                                    // partition
                                                    self.tableData = [self partitionObjects:self.musicLibraryArr collationStringSelector:@selector(self)];
                                                    NSLog(@"HEADER: %@", self.tableData);

                                                    [self.tableView reloadData];
                                                }

现在我调用 self.tableData = [self partitionObjects:self.musicLibraryArr collat​​ionStringSelector:@selector(self)];为了创建节数组

但我得到了从 A 到 Z 的部分,并且在每个部分中我都有所有 JSON 数据(数据在每个部分中重复,而不是将数据拆分为部分)。

分区方法是:

-(NSArray *)partitionObjects:(NSArray *)array collationStringSelector:(SEL)selector

{ UILocalizedIndexedCollat​​ion *collat​​ion = [UILocalizedIndexedCollat​​ion currentCollat​​ion]; NSInteger sectionCount = [[collat​​ion sectionTitles] count]; NSMutableArray *unsortedSections = [NSMutableArray arrayWithCapacity:sectionCount];

for (int i = 0; i < sectionCount; i++) {
    [unsortedSections addObject:[NSMutableArray array]];
}

for (id object in array) {
    NSInteger index = [collation sectionForObject:[object objectForKey:@"sArtist"] collationStringSelector:selector];
    [[unsortedSections objectAtIndex:index] addObject:object];
}

NSMutableArray *sections = [NSMutableArray arrayWithCapacity:sectionCount];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"sArtist" ascending:YES selector:@selector(localizedCaseInsensitiveCompare:)];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];


for (NSMutableArray *section in unsortedSections) {
    NSArray *sortedArray = [section sortedArrayUsingDescriptors:sortDescriptors];

// collat​​ionStringSelector:selector]]; [部分 addObject:sortedArray]; }

return sections;

}

编辑 - #2 我在这里初始化了数据:

AFJSONRequestOperation *operation =
[AFJSONRequestOperation JSONRequestOperationWithRequest:request
 // The success block runs when (surprise!) the request succeeds.
                       success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
                                      self.noMusicView.hidden = YES;

//从json数组中获取数据数组
self.musicLibraryArr = [(NSDictionary*)JSON objectForKey:@"array"]; NSLog(@"JSON 数据:%@", self.musicLibraryArr); // 对数组进行排序
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"stitle" 升序:YES]; NSArray *sortedArray = [self.musicLibraryArr sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];

                                        self.musicLibraryArr = [[NSMutableArray alloc] initWithArray:sortedArray];

                                        self.loadingView.hidden = YES;
                                         self.indexPathController.dataModel = [[TLIndexPathDataModel alloc] initWithItems:self.musicLibraryArr                                                   andSectionNameKeyPath:@"sTitle"                                              andIdentifierKeyPath:@"sId"];

//这里我 GET NULL(我检查我是否可以看到 NSLog 中的数据)

                                                  NSLog(@"DATA MODEL %@", self.indexPathController.dataModel);

                                                    [self.tableView reloadData];
                                                }
 // The failure block runs if something goes wrong, such as when the network isn’t available. If that happens, you display an alert view with an error message.
                                                failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
                                 // Error view
                                 self.noMusicView.hidden = NO;
                                 self.loadingView.hidden = YES;
                                 self.noMusicViewLabel.text = error.localizedDescription;
                                                }];

可能我在 partitionObjects 方法中遗漏了一些东西,请帮助

【问题讨论】:

    标签: uitableview


    【解决方案1】:

    您可以使用 TLIndexPathTools 尝试解决方案 here。这种方法使您不必自己操作传入的数据。您只需要提供您的字典数组和sectionNameKeyPath。请参阅示例代码。

    编辑根据您在下面的评论,我添加了一个示例项目,该示例项目演示了一个嵌入在 UIViewController 中的表格视图,对 TLIndexPathTools 的依赖最小。尝试运行Minimal project。视图控制器的源码如下:

    #import <UIKit/UIKit.h>
    
    #import "TLIndexPathController.h"
    
    @interface ViewController : UIViewController <TLIndexPathControllerDelegate, UITableViewDataSource>
    @property (strong, nonatomic) IBOutlet UITableView *tableView;
    @end
    
    #import "ViewController.h"
    
    @interface ViewController ()
    @property (strong, nonatomic) TLIndexPathController *indexPathController;
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        self.indexPathController = [[TLIndexPathController alloc] initWithItems:@[
                                    @"Chevrolet",
                                    @"Bubble Gum",
                                    @"Chalkboard"]
                                    ];
    }
    
    #pragma mark - UITableViewDataSource
    
    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
    {
        return self.indexPathController.dataModel.numberOfSections;
    }
    
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    {
        return [self.indexPathController.dataModel numberOfRowsInSection:section];
    }
    
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
        NSString *title = [self.indexPathController.dataModel itemAtIndexPath:indexPath];
        cell.textLabel.text = title;
        return cell;
    }
    
    #pragma mark - TLIndexPathControllerDelegate
    
    - (void)controller:(TLIndexPathController *)controller didUpdateDataModel:(TLIndexPathUpdates *)updates
    {
        [updates performBatchUpdatesOnTableView:self.tableView withRowAnimation:UITableViewRowAnimationFade];    
    }
    
    @end
    

    以此为基础,您将配置数据模型,如链接帖子中所示。

    EDIT #2 数据模型配置如下所示:

    - (void)viewDidLoad
    {
        [super viewDidLoad];
    
        self.indexPathController = [[TLIndexPathController alloc] init];
    
        //if you get your JSON asynchronously, you would make the request after initializing
        //the index path controller, possibly right here. Assuming your JSON request
        //passes the result back through a callback block, the block would process
        //the incoming array like this block:
        ^(NSArray *jsonData){
            self.indexPathController.dataModel = [[TLIndexPathDataModel alloc] initWithItems:jsonData
                                                                       andSectionNameKeyPath:@"sTitle"
                                                                      andIdentifierKeyPath:@"sId"];
        };
    
        //or if you already have the data, just set the data model directly:
        self.indexPathController.dataModel = [[TLIndexPathDataModel alloc] initWithItems:jsonData
                                                               andSectionNameKeyPath:@"sTitle"                                                         
                                                               andIdentifierKeyPath:@"sId"];
    }
    

    如果需要动态更新数据,只需如上图创建一个新的数据模型,并重新设置索引路径控制器的dataModel属性即可。控制器将调用其controller:didUpdateDataModel 方法,并且如上面的示例代码所示,委托将在更新对象上调用performBatchUpdatesOnTableView:,从而使新数据平滑地动画化。

    【讨论】:

    • 谢谢,我会尝试并建议
    • 这个类应该是完美的,但我需要将它与 UIViewcontroller 一起使用,并且在示例中它们显示您需要使用 UITableViewcontroller。你知道我是否可以通过继承 UIViewController 来使用它吗?
    • TLTableViewController 类只是转发到TLTableViewDelegateImpl 的一个实例,该类提供了UITableViewDataSourceTLTableViewDelegate 协议的最小实现。您可以在视图控制器中保存TLTableViewDelegate 的内部实例,并以两种方式之一使用它:1)视图控制器是表的委托,它根据需要将消息转发到TLTableViewDelegate 实例或2)@987654336 @ 是表的委托,您可以根据需要对其进行子类化以添加/更改委托/数据源逻辑。
    • 另外,您可以将TLIndexPathController 的实例直接集成到您的视图控制器中。委托/数据源实现看起来就像您在 TLTableViewDelegateImpl 中看到的那样,只是您将从 TLIndexPathController 而不是回调块中获取数据模型。如果有帮助,我可以添加一个示例项目来演示这一点。其实很简单。
    • 我设法编译它并通过执行以下操作显示数据: self.indexPathController = [[TLIndexPathController alloc] initWithItems:@[@"stitle]]; 但正如你所说,它是数据模型,但是在第一个示例中,我得到的印象是它是部分的分隔符。我应该将 JSON 数组放在哪里以显示部分?谢谢您的回答
    猜你喜欢
    • 1970-01-01
    • 2020-05-01
    • 2011-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-22
    相关资源
    最近更新 更多