Confronta il numero intero con la stringa in NSPredicate

Sep 23 2020

Ho in progetto una serie di programmi di allenamento (il codice per loro si trova su Objective-C) e in ogni programma che ho @property (nullable, nonatomic, copy) NSString *scheduleStr;per la durata del programma. Questa proprietà memorizza valori come 1 settimana , 2 settimane , 3 settimane e così via. Devo filtrare tutti i valori maggiori di 6 settimane. Sto cercando di applicare NSPredicate:

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

dopodiché ricevo solo programmi della durata di 6-9 settimane, ma niente di più di 10 settimane, ma di sicuro ho diversi programmi nel database con durata pari a 12 settimane. Se sto cercando di applicare qualcosa di simile:

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

Riceverò quasi tutti i programmi. Come ottenere tutti i programmi con più di valori selezionati?

Risposte

1 pbasdf Sep 24 2020 at 03:48

Il problema è che, sebbene tu specifichi integerValue, quando usi il predicato come parte di un recupero, CoreData tratta la tua stringa come una stringa. In termini di stringa, 10 weeksè "minore di" 6 weeks, quindi è escluso dai risultati.

Dovresti memorizzare il numero (come Int) invece di memorizzare la stringa. L'aggiunta del testo "settimane" è quindi qualcosa che fai per scopi di visualizzazione. Se memorizzi il numero, anziché la stringa, CoreData può eseguire un confronto numerico e il tuo predicato funzionerà come previsto.

Se davvero non vuoi farlo, c'è una soluzione alternativa e un hack. La soluzione è filtrare gli oggetti in memoria anziché come parte di un recupero. Il integerValueverrà quindi correttamente interpretato e il confronto sarà numerico.

L'hack consiste nel forzare CoreData a trattare la tua stringa come se fosse un numero, utilizzando una funzione numerica, come abs(supponendo che tu abbia solo un numero positivo di settimane, prendendo il valore assoluto lascia il valore invariato):

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

Per ottenere la parte intera nella stringa nel tuo caso puoi esaminare qualcosa come:

Supponiamo allora che l'elemento sia la tua stringa

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

Questo ti darà la parte intera della stringa che può essere usata per filtrare l'array.