Error : Can't do a substring operation with something that isn't a string

Error : Can't do a substring operation with something that isn't a string

这个问题已经被问过很多次了,我已经遍历了每一个解决方案,也尝试过实施但是 none 对我有用。

问题: 出现此错误:Can't do a substring operation with something that isn't a string 使用 NSPredicate.

过滤 NSArray

编码资料: 通过这种方式,我正在尝试过滤我的数组

NSArray *array = [[NSArray alloc]initWithArray:dataArray];

NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:@"name BEGINSWITH[c] %@", searchText];

allProductData = [[array filteredArrayUsingPredicate:resultPredicate]mutableCopy]; //Error is here

现在有两个数组,其中这适用于第一个数组,而相同的代码不适用于第二个数组。

数组 1: 这个数组工作正常。

(
        {
        "_id" = 59483833710f853221c90a92;
        attributes =         (
                        {
                key = Atributos;
                value = "-";
            }
        );
        name = "Ades Soya Bebida Chocolate 946 Ml";
        price = "-";
        uri = "http://res.cloudinary.com/cloudimp/image/upload/u3kgmm8bx5lsmmacbnrl.jpg";
    },
        {
        "_id" = 5948383f853221c90a94;
        attributes =         (
        );
        name = "Ades Soya Bebida Chocolate 200 Ml";
        price = "";
        uri = "http://res.cloudinary.com/cloudimp/image/upload/hhafrnwocqoamhhievoy.jpg";
    }

) 

过滤键: name = "Ades Soya Bebida Chocolate 946 Ml";

阵列 2: 过滤器不适用于此阵列。

(
        {
        image = "http://images.qliktag.com/image/upload/w3tb9dutynou1hlooexn.gif";
        name = Abuelita;
        products =         (
                        {
                "_id" = 594c030f124244325;
                attributes =                 (
                );
                name = "Abuelita chocolate granulado";
                price = "";
                uri = "http://images.qliktag.com/image/upload/iiqfuiilstvksdycnfbc.jpg";
            },
                        {
                "_id" = 5931c73303f737086;
                attributes =                 (
                );
                name = "ABUELITA Chocolate";
                price = "";
                uri = "<null>";
            },

             { //Crashing app for this while reading this structure.
                "_id" = 5931c73303f737086;   
                attributes =                 (
                );
                name = (
                             {
                                language = @"en"
                                value = "SOYA"
                             },
                             {
                                language = @"de"
                                value = "SOYA Bebida"
                             }
                          );
                price = "";
                uri = "<null>";
            }
        );
    }

注:两个数组中name的值是不同的。

最后我要筛选name

name1 = "Ades Soya Bebida Chocolate 946 Ml"

name2 = Abuelita; //Crashing app for this while filtering.

数组是动态变化的,它看起来类似于这样...

example-1 : 应用程序崩溃,出现此错误:无法对非字符串的内容执行子字符串操作。

          ContactName[0] "ABC"
          ContactName[1] = XYZ
          ContactName[2] = (
                             {
                                language = @"en"
                                value = "PQR"
                             },
                             {
                                language = @"de"
                                value = "QWERTY"
                             }
                          )

example-2 : 应用运行良好

          ContactName[0] = "ABC"
          ContactName[1] = "XYZ"
          ContactName[2] = "PQR"

那么,我应该如何过滤这样的数组...???

我建议 -[NSPredicate predicateWithBlock:]

测试product[@"name"]的类型。如果类型是 NSString 使用 -[NSString hasPrefix:]。如果类型是 NSArray 找到等于 NSLocale.currentLocale.languageCode 的语言,然后比较然后对值使用 -[NSString hasPrefix:]

- (void)testBeginsWithSearchText {
    NSArray<NSDictionary *> *data =
    @[@{@"image": @"http://images.qliktag.com/image/upload/w3tb9dutynou1hlooexn.gif",
        @"name": @"Abuelita",
        @"products": @[@{@"_id": @"594c030f124244325",
                         @"attributes": @[],
                         @"name": @"Abuelita chocolate granulado",
                         @"price": @"",
                         @"uri": @"http://images.qliktag.com/image/upload/iiqfuiilstvksdycnfbc.jpg"},
                       @{@"_id": @"5931c73303f737086",
                         @"attributes": @[],
                         @"name": @"ABUELITA Chocolate",
                         @"price": @"",
                         @"uri": @"<null>"},
                       @{@"_id": @"5931c73303f737086",
                         @"attributes": @[],
                         @"name": @[@{@"language": @"en",
                                      @"value": @"SOYA"},
                                    @{@"language": @"de",
                                      @"value": @"SOYA Bebida"}],
                         @"price": @"",
                         @"uri": @"<null>"}]}];

    NSString *searchText = @"SOYA";

    id beginsWithSearchText = [NSPredicate predicateWithBlock:^BOOL(NSDictionary *product, NSDictionary *bindings) {
        if ([product[@"name"] isKindOfClass:[NSString class]]) {
            return [product[@"name"] hasPrefix:searchText];
        } else if ([product[@"name"] isKindOfClass:[NSArray class]]) {
            NSUInteger index = [product[@"name"] indexOfObjectPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
                return [obj[@"language"] isEqualToString:NSLocale.currentLocale.languageCode];
            }];

            return index != NSNotFound && [product[@"name"][index][@"value"] hasPrefix:searchText];
        } else {
            return NO;
        }
    }];

    NSArray *result = [data.firstObject[@"products"] filteredArrayUsingPredicate:beginsWithSearchText];

    XCTAssertEqual(result.count, 1);
    XCTAssertEqualObjects(result.firstObject[@"_id"], @"5931c73303f737086");
}