2
votes

I have in project array of workout programs (code for them are on Objective-C) and in every program I have @property (nullable, nonatomic, copy) NSString *scheduleStr; for program durations. This property stores values such as 1 week, 2 weeks, 3 weeks and etc. I need to filter all values bigger than 6 weeks. I'm trying to apply NSPredicate:

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

and after this I'm receiving only programs with length 6-9 weeks, but nothing more than 10 weeks, but for sure I have several programs in database with length equal 12 weeks. If I'm trying to apply something like this:

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

I will receive almost all the programs. How to get all programs with more than selected values?

2
Are you using your predicate(s) on Core Data or an array, it reads like it is an array but you have tagged the question with Core Data so it is not clear. Also, you append your predicate to an array, so do you have multiple predicates (a compound predicate) you use at once? I tried to reproduce this in a playground using a custom class and NSArray but then the predicates worked fine. - Joakim Danielson
Yes, this is Core Data. I'm making request to get a suitable array of programs. - Maxvale
And have you tested this predicate alone without any others for a fetch request? - Joakim Danielson

2 Answers

1
votes

The problem is that, although you specify integerValue, when using the predicate as part of a fetch, CoreData treats your string as a string. In string terms, 10 weeks is "less than" 6 weeks, so it's excluded from the results.

You should store the number (as an Int) instead of storing the string. Adding the text " weeks" is then something you do for display purposes. If you store the number, rather than the string, then CoreData can do a numerical comparison and your predicate will work as you expect.

If you really don't want to do that, there is one workaround, and one hack. The workaround is to filter the objects in memory rather than as part of a fetch. The integerValue will then be correctly interpreted and the comparison will be numerical.

The hack is to force CoreData to treat your string as though it is a number, by using a numeric function, like abs (assuming you only have a positive number of weeks, taking the absolute value leaves the value unchanged):

predicates.append(NSPredicate(format: "abs:(scheduleStr) >= 6"))
0
votes

To get the integer part in the string in your case you can look into something like:

Suppose element is your string then

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

This will give you the integer part of the string which can be used to filter the array.