Filter on first letter of property - ios

I've got a local db (Realm) with drinks. Each drink has a name.
I want to get all the drinks starting with a certain letter.
This is what I came up with:
let objects = realm.objects(Drank.self)
.filter{($0.name.characters.first)?.description == section}
The problem I am having now is that the objecttype I get is a 'LazyFilterBidirectionalCollection'. But I need Results.
Does anybody know a way to convert it to the correct type or maybe a different way to filter the resultset?

This is straight from the realm docs on sorting/filtering:
let sortedDogs = realm.objects(Dog.self).filter("color = 'tan' AND name BEGINSWITH 'B'").sorted(byProperty: "name")
So to filter something you are looking for maybe something like this:
let objects = realm.objects(Drank.self)
.filter("name BEGINSWITH '\(column)'")
A safer option proposed below by Thomas Goyne,
let objects = realm.objects(Drank.self)
.filter("name BEGINSWITH %#", column)
Since you are now filtering data with the way the docs use you should receive a Results object
Don't be afraid to read documentation, not only will you be able to get the satisfaction of figuring it out on your own, you will also learn a bunch of other things along the way.

Related

How to make predicate with dynamic where clause of SQL format

I have a requirement for the enterprise app that I'm working on where the SQL queries are stored in the system.
For example:
WORKTYPE not in('PM','PM1','EV','OP')
:worktype <>'PM' AND :worktype <>'PM1' AND
:worktype <>'EV' AND :worktype <>'OP'
WORKTYPE n :worktype are the attributes of an entity
PM, PM1, EV and OP are the values to be filtered
=======================================================================
These are some of example where clauses that I have to handle in the NSPredicate.
Programming Language: Swift 4
Database: Coredata
Any suggestion of how to handle these expressions ?
You can create NSPredicate at run time and at the end combine predicate using NSCompoundPredicate. Like in below syntax
let predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicate1, predicate2])
BTW - I agree with the comments - you should provide more information in your question and explain what you have tried, including attempts at code, etc... however failing that...
Read about the NSExpression class, from the Apple Developer documentation...
NSExpression
An expression for use in a comparison predicate.
Overview
Comparison operations in an NSPredicate are based on two expressions, as represented by instances of the NSExpression class.
Expressions are created for constant values, key paths, and so on.
Although it is an archived document, Apple's "Predicate Programming Guide" is still relevant to those using predicates with Core Data in both Swift and Objective-C. I recommend you read it.
Within this documentation, I specifically point you to...
Creating Predicates > Creating Predicates Using Predicate Templates
The example from the documentation (translated to Swift)...
The following example uses a format string to create a predicate with
a right-hand side that is a variable expression.
let predicateTemplate = NSPredicate(format: "lastName like[c] %#", argumentArray: [$LAST_NAME])
This is equivalent to creating the variable expression directly as
shown in the following example.
let lhs = NSExpression(forKeyPath: "lastName"]
let rhs = NSExpression(forVariable: "LAST_NAME"]
let comparisonPredicate = NSComparisonPredicate(leftExpression: lhs,
rightExpression: rhs,
modifier: .direct,
type: .like,
options: [.caseInsensitive])
So enough of the lecture and to your question...
WORKTYPE not in('PM','PM1','EV','OP')
I assume here that you have the knowledge to parse your SQL expressions to extract the information set out in the first two lines of code below.
let keyPath: String = "WORKTYPE"
let arrayWorkTypes: [String] = ["PM", "PM1", "EV", "OP"]
var arrayComparisonPredicates = [NSPredicate]()
for workType in arrayWorkTypes {
let expressionLHS = NSExpression(forKeyPath: keyPath)
let expressionRHS = NSExpression(forConstantValue: workType)
let comparisonPredicate = NSComparisonPredicate(leftExpression: expressionLHS,
rightExpression: expressionRHS,
modifier: .direct,
type: .notEqualTo,
options: [.caseInsensitive])
arrayComparisonPredicates.append(comparisonPredicate)
}
let andPredicate = NSCompoundPredicate(andPredicateWithSubpredicates: arrayComparisonPredicates)
With your andPredicate built dynamically in this manner, you should be able to run your fetch request successfully.
I haven't tested this code so let me know how you go and I'll update if/when necessary.
And finally... your database is not Core Data.
If you’re using the Core Data framework in an Xcode project, your database is most likely SQLite.
Simply and according to Wikipedia, Core Data is “a model object graph and persistence framework...”
I highly recommend that you read and read and read some more until you truly understand the difference. I guarantee it will be a worthwhile investment of your time.

Grab the highest date inside of an array of entities.

I have the following array :
let messages = (fetchedResultsController.fetchedObjects as! [Message])
essentially, each element in this array is of the entity Message, where each Message has 5 core data attributes. Notably, the attribute I care about in this case is timestamp which is of type NSDate !!!!!!. I want to grab the message with the maximum date inside of this array using the reduce function. Please do not suggest to sort the messages first. I'am trying to avoid that. Thank you !
Not sure why you would want to use reduce, but I think this will work and fits with what you are looking for (assuming Swift 3):
let result = messages.max(by: {$0.timeStamp < $1.timeStamp})

How to perform a compound query against to many relationships in CoreData

I am looking for some assistance in understanding NSPredicates and how to query CoreData. Here is what I have:
I have two entities: 1. Capture that represents a "capture" of some data and it has a to many relationship to 2. Identity tags.
I am looking to essentially get a Set of "Identity" tags from a particular Set of "Captures". i.e. I want to know all the unique identities of name 'X' for captures that are also tagged with an id of Int 'y'.
In swift I would model this like:
let captures: [Capture]
let identities = captures.flatmap({ $0.identities }).filter({ $0.id == "y" })
let uniqueIdentitiesOfParticularType: Set<Identity> = Set(identities.flatMap({ $0.name })
Any help please?
First, definitely start with the Predicate Programming Guide, which covers more of this in detail. See particularly "Using Predicates with Core Data."
Your solution is likely something along these lines if you wanted to be a bit careful about faulting:
let request = NSFetchRequest(entityName: "Capture")
let id = "y"
request.predicate = NSPredicate(format: "id == %#", id)
let identities = try context.executeFetchRequest(request) as NSArray
let names = identities.valueForKeyPath("#distinctUnionOfObjects.name")
Note that iOS 10 adds better bridges for this to Swift (you may not need as NSArray), but I haven't really explored them yet.
For more on #distinctUnionOfObjects and its friends, see Collection Operators.

Searching for Parse objects where an object's array property contains a specified string

I have a PFObject subclass which stores an array of strings as one of its properties. I would like to query for all objects of this class where one or more of these strings start with a provided substring.
An example might help:
I have a Person class which stores a firstName and lastName. I would like to submit a PFQuery that searches for Person objects that match on name. Specifically, a person should be be considered a match if if any ‘component’ of either the first or last name start with the provided search term.
For example, the name "Mary Beth Smith-Jones" should be considered a match for beth and bet, but not eth.
To assist with this, I have a beforeSave trigger for the Person class that breaks down the person's first and last names into separate components (and also lowercases them). This means that my "Mary Beth Smith-Jones" record looks like this:
firstName: “Mary Beth”
lastName: “Smith-Jones”
searchTerms: [“mary”, “beth”, “smith”, “jones”]
The closest I can get is to use whereKey:EqualTo which will actually return matches when run against an array:
let query = Person.query()
query?.whereKey(“searchTerms”, equalTo: “beth”)
query?.findObjectsInBackgroundWithBlock({ (places, error) -> Void in
//Mary Beth is retuned successfully
})
However, this only matches on full string equality; query?.whereKey(“searchTerms”, equalTo: “bet”) does not return the record in question.
I suppose I could explode the names and store all possible sequential components as search terms (b,e,t,h,be,et,th,bet,etc,beth, etc) but that is far from scalable.
Any suggestions for pulling these records from Parse? I am open to changing my approach if necessary.
Have you tried whereKey:hasPrefix: for this? I am not sure if this can be used on array values.
https://parse.com/docs/ios/guide#queries-queries-on-string-values

What is the labels order in ABMultiValueCopyLabelAtIndex()

I am testing with iOS AddressBook framework and I am trying to figure what, what's the best way to extract the value at specific label and wondering at the same time if the order of these labels change, for any random reason.
This is what I am doing when I am adding a new contact or adding to an existing one:
let phone:ABMutableMultiValue = ABMultiValueCreateMutable(
ABPropertyType(kABStringPropertyType)).takeRetainedValue()
ABMultiValueAddValueAndLabel(phone, phoneNumber, kABPersonPhoneMainLabel, nil)
And later on in the delegate call to unknownPersonViewController() I am doing this:
let phone: ABMultiValueRef = ABRecordCopyValue(person,
kABPersonPhoneProperty).takeRetainedValue()
firstPhone = ABMultiValueCopyValueAtIndex(phone, 0).takeRetainedValue() as! String
Notice that I am assuming that the main label is at index 0. I know that a comparison with CFString label is possible, but these labels look funny, giving me this weird gut feeling when comparing agains them. So, I am not really sure how to go about this.
You should not assume any order. You have to read the value of the label. They do "look funny" but they are easy to deal with: they are of the form "_$!<Label>!$_", where "_$!<" and ">!$_" are merely delimiters that you can rely on.

Resources