从数组中删除项目(来自 API 的带有 JSON 的 Restkit 项目)

Posted

技术标签:

【中文标题】从数组中删除项目(来自 API 的带有 JSON 的 Restkit 项目)【英文标题】:Remove items from array (Restkit project with JSON from API) 【发布时间】:2014-06-05 23:58:37 【问题描述】:

我有一个leafs 数组,我想删除数组中的一些对象。

数组中有大约 50 个对象,我只想要数组中的大约 10 个;数组中需要的 10 个对象混合在数组中的 50 个对象中。

我在我的项目中使用 RestKit,并将 leafs 放入表视图中。

ViewController.m

@property (strong, nonatomic) NSArray *springs;
@property (strong, nonatomic) NSMutableArray *leafs;

@end

@synthesize tableView=_tableView;
@synthesize springs;
@synthesize leafs;

- (void)viewDidLoad

    [super viewDidLoad];
    // Do any additional setup after loading the view.
    [self configureRestKit];
    [self loadLeafs];


- (void)didReceiveMemoryWarning

    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.


- (void)configureRestKit 
    // initialize AFNetworking HTTPClient
    NSURL *baseURL = [NSURL URLWithString:@"https://api.e.com"];
    AFHTTPClient *client = [[AFHTTPClient alloc] initWithBaseURL:baseURL];

    // initialize RestKit
    RKObjectManager *objectManager = [[RKObjectManager alloc] initWithHTTPClient:client];

    // setup object mappings
    RKObjectMapping *springMapping = [RKObjectMapping mappingForClass:[Spring class]];
    [springMapping addAttributeMappingsFromArray:@[@"name"]];

    RKObjectMapping *leafMapping = [RKObjectMapping mappingForClass:[Leaf class]];
    [leafMapping addAttributeMappingsFromArray:@[@"abbreviation", @"shortName", @"id"]];

    [springMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"leafs" toKeyPath:@"leafs" withMapping:leafMapping]];

// Wain, this is where I'm getting that error:
// "property discardsinvalidobjectsoninsert not found on object of type RKObjectMapping"
springMapping.discardsInvalidObjectsOnInsert = YES;

    // register mappings with the provider using a response descriptor
    RKResponseDescriptor *responseDescriptor =
    [RKResponseDescriptor responseDescriptorWithMapping:springMapping
                                                 method:RKRequestMethodGET
                                            pathPattern:nil
                                                keyPath:@"springs"
                                            statusCodes:[NSIndexSet indexSetWithIndex:200]];
    [objectManager addResponseDescriptor:responseDescriptor];


- (void)loadLeafs 
    NSString *apikey = @kCLIENTKEY;

    NSDictionary *queryParams = @@"apikey" : apikey,;

    [[RKObjectManager sharedManager] getObjectsAtPath:@"v1/springs/"
                                           parameters:queryParams
                                              success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) 
                                                  springs = mappingResult.array;
                                                  [self.tableView reloadData];


                                              
                                              failure:^(RKObjectRequestOperation *operation, NSError *error) 
                                                  NSLog(@"No springs?': %@", error);
                                              ];


#pragma mark - Table View

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView

    return springs.count;


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

    Spring *spring = [springs objectAtIndex:section];
    return spring.leafs.count;


- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section 
    Spring *spring = [springs objectAtIndex:section];
    return spring.name;


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

    static NSString *CellIdentifier = @"standardCell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    Spring *spring = [spring objectAtIndex:indexPath.section];
    Leaf *leaf = [spring.leafs objectAtIndex:indexPath.row];
    cell.textLabel.text = leaf.shortName;

    return cell;

春天.h

@property (nonatomic) NSString *name;
@property (nonatomic) NSNumber *id;
@property (nonatomic) NSArray *leafs;

叶子.h

@property (nonatomic) NSString *name;
@property (nonatomic) NSString *abbreviation;
@property (nonatomic) NSString *shortName;
@property (nonatomic) NSNumber *id;

每个 Wain,我在 Spring.h 中添加了这个

@property (nonatomic, assign) BOOL discardsInvalidObjectsOnInsert;

Per Wain,我在 Spring.m 中添加了这种东西

- (BOOL)validateName:(id *)ioValue error:(NSError **)outError 

    if([(NSString *)*ioValue  isEqualToString:@"cricket"])

        NSLog(@"old name: %@, new name: %@", self.name, *ioValue);

// Wain: set the names to nil for the objects you don't want
ioValue = nil;

        return NO;

// Wain: should I keep this line?
        self.discardsInvalidObjectsOnInsert = YES;

        

        else
            return YES;
        


每个 Wain,我在 ViewController.m 中添加了这个

- (void)loadLeafs 

    NSString *apikey = @kCLIENTKEY;

    NSDictionary *queryParams = @@"apikey" : apikey,;

        [[RKObjectManager sharedManager] getObjectsAtPath:@"v1/springs/"
                                               parameters:queryParams
                                                  success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) 
                                                      springs = mappingResult.array;
                                                      [self.tableView reloadData];


                                                  
                                                  failure:^(RKObjectRequestOperation *operation, NSError *error) 
                                                      NSLog(@"No springs?': %@", error);
                                                  ];
        // Wain: filter (using a predicate) the mapping array (name != nil)
        NSPredicate *bPredicate = [NSPredicate predicateWithValue:NO];
        self.filteredArray = [self.sports filteredArrayUsingPredicate:bPredicate];
    

成功阻止

NSPredicate *filterPredicate = [NSPredicate predicateWithFormat:@"name != nil"];
                                                  springs = [mappingResult.array filteredArrayUsingPredicate:filterPredicate];

                                                  // You need to loop over the springs after you filter them and then filter the leafs of each spring
                                                  for (Spring *spring in springs) 
                                                      for (Leaf *leaf in spring.leafs)
                                                          NSPredicate *filterPredicate2 = [NSPredicate predicateWithFormat:@"shortName != nil"];
                                                          leafs = [spring.leafs filteredArrayUsingPredicate:filterPredicate2];
                                                      
                                                  

                                                  [self.tableView reloadData];

【问题讨论】:

创建一个新的 NSMutableArray,遍历你的数组,将你想要的添加到新数组中? 您使用什么标准来确定是否要移除叶子? @Mike 好问题,我也会在我原来的问题中说明这一点。我想指定leafs 要包含的shortNames。比如leafs数组中,我只想要shortNames:aaa, bbb, ccc, ddd, eee。这样说清楚了吗? @jraede 感谢您的回复!你有如何做到这一点的链接,或者你可以发布一个sn-p代码吗?我也有点理解我需要尝试做的事情的总体思路,但具体的实现是我在这里做的不足之处? 【参考方案1】:

如果您想在映射期间过滤掉项目,请考虑使用带有 RestKit 的 KVC 验证。

如果您希望设备上的所有项目都可用并且只过滤显示,请使用谓词过滤数组。

【讨论】:

如果我使用谓词,是在loadLeafs 方法中,还是在tableView 方法中,或其他什么? 目前我尝试在cellForRowAtIndexPathLeaf *leaf = [spring.leafs objectAtIndex:indexPath.row]; 之后但在cell.textLabel.text = leaf.shortName; 之前添加3 行来做谓词,但它不太有效:NSPredicate *predicate = [NSPredicate predicateWithFormat:@"leaf.shortName CONTAINS %@", @"BBB" ]; NSArray *filtered = [leafs filteredArrayUsingPredicate:predicate]; NSLog(@"Filter: %@", filtered); 通常您运行谓词并缓存结果,通常在viewWillAppear: 中调用的方法中,并且只要源数据发生更改(调用RestKit 成功块)。无论如何,在表格方法之前,您需要将过滤后的计数提供给表格视图... 所以在我上面的原始问题中,我更新了 3 个部分的代码以反映我认为你在说什么。 1 - 添加了filterLeafs 方法。 2 - 添加了调用filterLeafs 方法的viewWillAppear。 3 - 在成功块的末尾调用filterLeafs。你说的基本是这个吗?当我在 filterLeafs 方法中使用 NSLog 时,null 返回 filtered 数组和 leafs 数组,这让我感到惊讶,因为 leagues 在表格视图中工作正常? 是的,验证名称并在成功块内。所以把springs = mappingResult.array;改成springs = [mappingResult.array filteredArray...;【参考方案2】:

按照您的要求进行操作的简单方法如下:

for (Leaf *leaf in leafs) 
    if (![leaf.shortName isEqualToString:@"aaa"] && ![leaf.shortName isEqualToString:@"bbb"] && ![leaf.shortName isEqualToString:@"ccc"] && ![leaf.shortName isEqualToString:@"ddd"]) 
        [leafs removeObject:leaf];
    

这基本上会遍历您的叶子对象数组,如果遇到具有除这四个字符串之外的任何东西的 shortName 属性的叶子对象,则该对象将被删除。

【讨论】:

说得有道理,不过我应该把它放在我的 ViewController 哪里? 也许在 loadLeafs 中?对您的代码一无所知,我无法为您提供最佳答案。 我在loadLeafs 中尝试过,并在上面的问题中发布了我的代码,我尝试过,但它没有删除我要求的任何内容。有什么想法或更多细节会有所帮助吗? 首先,您不希望将 for 循环放在另一个循环中,在该循环中循环通过弹簧。把它拿出来,然后再做。其次,右添加 NSLog(@"%@", leafs);在你运行循环之前和之后告诉我输出是什么。 NSLog 在该方法中两次都是null。假设这可能与 springs = mappingResult.array 被加载在那里有关,因此我试图弄清楚如何获得嵌套在 springs 内的 leafs

以上是关于从数组中删除项目(来自 API 的带有 JSON 的 Restkit 项目)的主要内容,如果未能解决你的问题,请参考以下文章

带有 Google PHP SDK 的 YouTube API - 以 JSON 格式响应

从javascript钛中的数组中删除项目

Angular 5,来自 API 的 JSON 数组

尝试将来自 API 的 JSON 数据显示为数组

将来自 Json 响应的 HTML 标记渲染到模板文字

带有来自链接的属性的 JSON 附加响应