Compare inteiro com string em NSPredicate

Sep 23 2020

Tenho em projeto uma série de programas de treino (o código para eles está em Objective-C) e em todos os programas que tenho @property (nullable, nonatomic, copy) NSString *scheduleStr;para durações de programa. Esta propriedade armazena valores como 1 semana , 2 semanas , 3 semanas e etc. Eu preciso filtrar todos os valores maiores que 6 semanas. Estou tentando aplicar o NSPredicate:

predicates.append(NSPredicate(format: "scheduleStr.integerValue >= 6"))

e depois disso estou recebendo apenas programas com duração de 6 a 9 semanas, mas nada mais que 10 semanas, mas com certeza tenho vários programas em banco de dados com duração igual a 12 semanas. Se estou tentando aplicar algo assim:

predicates.append(NSPredicate(format: "scheduleStr.integerValue >= 10"))

Receberei quase todos os programas. Como obter todos os programas com mais do que os valores selecionados?

Respostas

1 pbasdf Sep 24 2020 at 03:48

O problema é que, embora você especifique integerValue, ao usar o predicado como parte de uma busca, CoreData trata sua string como uma string. Em termos de string, 10 weeksé "menor que" 6 weeks, portanto, é excluído dos resultados.

Você deve armazenar o número (como um Int) em vez de armazenar a string. Adicionar o texto "semanas" é algo que você faz para fins de exibição. Se você armazenar o número, em vez da string, o CoreData pode fazer uma comparação numérica e seu predicado funcionará conforme o esperado.

Se você realmente não quiser fazer isso, há uma solução alternativa e um hack. A solução alternativa é filtrar os objetos na memória, em vez de como parte de uma busca. O integerValueserá então interpretado corretamente e a comparação será numérica.

O truque é forçar o CoreData a tratar sua string como se fosse um número, usando uma função numérica, como abs(supondo que você tenha apenas um número positivo de semanas, tomar o valor absoluto deixa o valor inalterado):

predicates.append(NSPredicate(format: "abs:(scheduleStr) >= 6"))
AnjaliAggarwal Sep 23 2020 at 22:26

Para obter a parte inteira da string no seu caso, você pode analisar algo como:

Suponha que o elemento seja a sua string, então

let component = element.components(separatedBy: .letters) // this will give you the non letter values 
let integerValues = component.filter({ $0 != "" }) 
print(integerValues[0]) // As first value in your input string is an integer

Isso lhe dará a parte inteira da string que pode ser usada para filtrar o array.