How to filter object from Realm database in Swift
You are using the wrong operator in a realm, please check my answer below.
for item in realm.objects(data.self).filter("id == 2 AND user_id == 4") {
print(item)
}
How to filter a realm subclass swift
There are actually multiple questions here. First we need to change the use of of the word subclass
to instance
. There are no subclasses in the question.
Note that Realm is conceptually an `Object' database so we're going to use the word 'object' to refer the objects stored in Realm (the 'instances' when they've been loaded in to memory)
I will rephrase each for clarity:
- How do I return all
SubscriptionClass
objects?
let results = realm.objects(SubscriptionClass.self)
- How do I return one specific
SubscriptionClass
object if I know the
primary key?
let oneObject = realm.object(ofType: SubscriptionClass.self, forPrimaryKey: theObjectsPrimaryKey)
- How do I return all of the
SubscriptionClass
objects that match a
specific criteria; where the question property equalsWhat is 5*5
let results = realm.objects(SubscriptionClass.self).filter("question == 'What is 5*5'")
and I will slide in #4: this queries for all questions as in #3 but only returns the very first one it finds. This can be dangerous because Realm objects are unordered so if there are ever more than one object, it could return a different first object each time it's used
if let oneObject = realm.objects(SubscriptionClass.self).filter("question == 'What is 5*5'").first {
//do something with the object
}
Subclass:
A subclass inherits the superclass's functionality and extends it to provide additional functionality. Here's a subclass that adds a difficulty property to a subclass of SubscriptionClass (the 'super class')
class SubscriptionWithDifficultySubClass: SubscriptionClass {
var difficulty = "" //Easy, Medium, Hard etc
}
and then a different subclass that provides a subject property:
class SubscriptionWithSubjectSubClass: SubcriptionClass {
var subject = "" //Math, Grammar, Science etc
}
Filter in realm list swift
This was a very challenging query but I think I have a solution.
First however; Primitives in Realm Lists are not well supported and are not yet queryable. See here and this for more reading.
EDIT: Release 10.7 added support for filters/queries as well as aggregate functions on primitives so the below info is no longer completely valid. However, it's still something to be aware of.
So we will need to add another class to hold the string data
class StringClass: Object {
@objc dynamic var myString = ""
}
so the following class will be updated to match
class ParamsModel: BaseResponse {
var options = List<StringClass>()
}
Then to peform the query we need to leverage a Subquery due to the depth of the objects.
let predicate = NSPredicate(format: "SUBQUERY(customFields, $customField, ANY $customField.params.options.myString == 'custom').@count > 0")
let results = realm.objects(RetailerModel.self).filter(predicate)
This will return all Retailer Models whose CustomFieldsModel has a ParamsModel options List property StringClass myString property equal to 'custom'
Realm Swift Filter Query Based On List Property
Let me restate the question;
You want an artist to be able to query for all new shows in cities
they are interested in where they have not yet responded.
If that's the question, let me start with some simple sample data
Two artists that have each have two cities if interest
let a0 = Artist()
a0.name = "Jim"
a0.citiesOfInterest.append(objectsIn: ["Austin", "Memphis"])
let a1 = Artist()
a1.name = "Henry"
a1.citiesOfInterest.append(objectsIn: ["Austin", "Memphis"])
and then two shows, one in each city
let s0 = Show()
s0.name = "Austin Show"
s0.city = "Austin"
let s1 = Show()
s1.name = "Memphis Show"
s1.city = "Memphis"
but artist a0 (Jim) has responded to the s0 (Austin) show
let r0 = ArtistResponse()
r0.show = s0
r0.artist = a0
r0.available = true
s0.artistResponses.append(r0) //jim responded to the Austin show
The result we want is that when Jim the artist logs on, he will see the Memphis show because he already responded to the Austin show.
let realm = try! Realm()
if let jim = realm.objects(Artist.self).filter("name == 'Jim'").first {
let myCities = jim.citiesOfInterest
let showResults = realm.objects(Show.self)
.filter("city IN %@ AND !(ANY artistResponses.artist.name == 'Jim')", myCities)
for show in showResults {
print(show.name)
}
}
And the output is
Memphis Show
We first get the Jim's cities of interest as an array, then we filter the shows that match those cities of interest but where there are no artist responses associated with Jim. This filter was based on the name but you could use the Artist id or even the Artist object itself as the comparator.
Realm filter results based on values in child object list
Here's one possible solution - add a reverse refererence to the restaurant for each meal object
class Restaurant: Object {
@objc dynamic var name: String? = nil
let meals = List<Meal>()
}
class Meal: Object {
@objc dynamic var mealName: String? = nil
let tag = RealmOptional<Int>()
@objc dynamic var restaurant: Restaurant? //Add this
}
then query the meals for that restaurant with the tags you want.
let results = realm.objects(Meal.self).filter("restaurant.name == %@ AND tag IN %@", "Foo", [1,2])
LinkingObjects could also be leveraged but it depends on what kind of queries will be needed and what the relationships are between Restaurants and Meals - I am assuming 1-Many in this case.
if you want ALL restaurants, then LinkingObjects is the way to go.
Edit:
Thought of another solution. This will work without adding a reference or an inverse relationship and will return an array of restaurants that have meals with the selected tags.
let selectedTags = [1,2]
let results = realm.objects(Restaurant.self).filter( {
for meal in $0.meals {
if let thisTag = meal.tag.value { //optional so safely unwrap it
if selectedTags.contains(thisTag) {
return true //the tag for this meal was in the list, return true
}
} else {
return false //tag was nil so return false
}
}
return false
})
How to filter Realm objects by list
try this solution
If you use a to-many relationship, You use an ANY
operator
Please read this well so you understand what to use because there is another operator ex ALL,ANY,NONE
Predicate Programming Guide
private func getDeviceContacts(_ phoneNumbers: [Int64]) -> [DeviceContactModel] {
do {
let realm = try Realm()
let deviceContacts = Array(realm.objects(DeviceContactModel.self).filter("ANY phones.fullNumber IN %@", phoneNumbers))
return deviceContacts
} catch {
debugPrint(error.localizedDescription)
return []
}
}
Filtering query for Realm
If your StoredExercise model looks like this
class StoredExercise: Object {
@objc dynamic var muscle = ""
}
then to get all of the exercises that are for the biceps, it's this
let bicepResults = realm.objects(StoredExercise.self).filter("muscle == 'biceps'")
iOS Realm Filter objects in a list of a relationship
Realm doesn't have any sort of concept of a deep-filtered view, so you can't have a Results<Canteen>
which restricts the List
s contained in related objects to vegan meals.
There are several similar things which you can do. You could add inverse relationship properties, and then query Meal
objects instead:
class Canteen: Object {
dynamic var name: String?
let lines = List<Line>()
}
class Line: Object {
dynamic var name: String?
let meals = List<Meal>()
let canteens = LinkingObjects(fromType: Canteen.self, property: "lines")
}
class Meal: Object {
dynamic var name: String?
dynamic var vegan: Bool = false
let lines = LinkingObjects(fromType: Line.self, property: "meals")
}
let meals = realm.objects(Meal).filter("vegan = true AND ANY lines.canteens.name = %@", selectedCanteenType.rawValue)
(Or rather, you will be able to once Realm 0.102.1 is out; currently this crashes).
If you just need to iterate over the meals but need to do so from the Canteen down, you could do:
let canteens = realm.objects(Canteen).filter("name = %@ AND ANY lines.meals.vegan = true", selectedCanteenType.rawValue)
for canteen in canteens {
for line in canteen.lines.filter("ANY meals.vegan = true") {
for meal in line.meals.filter("vegan = true") {
// do something with your vegan meal
}
}
}
This unfortunately has some duplication due to needing to repeat the filter for each level of the references.
How can I filter by specific date from realm object in swift?
My original answer is below which, after a lot of research was only somewhat correct.
The actual answer has to do with the timestamp portion of the date.
So... if we create a date object using the below code and set it to a known date,
let stringDate = "2020-03-08"
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let searchDate:Date = dateFormatter.date(from: stringDate)!
the actual object will look like this
2020-03-08T05:00:00.000Z
However, how the Profile object is being created is like this
convenience init(_ content: String) {
self.init()
self.content = content
self.date = Date()
}
and that date object looks like this
2020-03-08T16:10:25.123Z
so as you can see, if we filter for a specific date these are not equal
2020-03-08T05:00:00.000Z != 2020-03-08T16:10:25.123Z
which is why this
let stringDate = "2020-03-08"
let searchDate:Date = dateFormatter.date(from: stringDate)!
let searchResults = realm.objects(Profile.self).filter("date == %@", searchDate)
could not find the date because it's filtering for this
2020-03-08T05:00:00.000Z
To fix, change the profile class with a date stamp with a default time stamp
class Profile: Object {
@objc dynamic var date: Date!
@objc dynamic var content: String!
convenience init(_ content: String) {
self.init()
self.content = content
let formatter = DateFormatter()
formatter.timeStyle = .none
formatter.dateFormat = "MM/dd/yy"
let today = Date()
let s = formatter.string(from: today)
let d = formatter.date(from: s)
self.date = d
}
}
or, store your dates as a string yyyymmdd which will remove the ambiguity completely.
-- ORIGINAL ANSWER BELOW ---
Filtering by date is fully supported on date objects. Here's two quick examples. One for filtering for a specific date (for your question) and one for a date range using BETWEEN.
Note, I have a function makeDate that casts a string to a date object. This example uses a Realm DogClass object that has a dog_birthdate Date property.
This filters for objects with a specific date
let searchDate = self.makeDate(fromString: "06/01/2019")
let specificDateResults = realm.objects(DogClass.self)
.filter("dog_birthdate == %@", searchDate)
for dog in specificDateResults {
print(dog.dog_name)
}
This filters for objects within a date range
let startDate = self.makeDate(fromString: "06/01/2019")
let endDate = self.makeDate(fromString: "06/20/2019")
let dateRangeResuls = realm.objects(DogClass.self)
.filter("dog_birthdate BETWEEN {%@,%@}", startDate, endDate)
for dog in dateRangeResuls {
print(dog.dog_name)
}
EDIT: Using the code in the comment from the OP for testing
let stringDate = "2019-06-01"
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let searchDate:Date = dateFormatter.date(from: stringDate)!
let result = realm.objects(DogClass.self).filter("dog_birthdate == %@", searchDate)
for dog in result {
print(dog.dog_name)
}
which works perfectly.
realm swift - filter objects with a property that starts with a string included in a list
There are a number of ways to do that. One option (which is not really practical in this use case) is to use the Realm Swift Query UI
let results2 = realm.objects(Item.self).where {
$0.name.starts(with: "x0") ||
$0.name.starts(with: "x1") ||
$0.name.starts(with: "x2")
}
As you can see, for a few items it's ok. What if there are dozens? Not very practical. That's where a NSCompoundPredicate really shines. Check this out
var predicateArray = [NSPredicate]()
for name in ['x0', 'x1', 'x2'] {
let predicate = NSPredicate(format: "name BEGINSWITH[cd] %@", name)
predicateArray.append(predicate)
}
let compoundPredicate = NSCompoundPredicate(orPredicateWithSubpredicates: predicateArray)
let results = realm.objects(Item.self).filter(compoundPredicate)
Way more practical as the elements in the list can be as many as needed.
There are some other options as well but the NSPredicate route is suggested in this use case.
Related Topics
Convert Time String into Date Swift
Easiest Way to Truncate Float to 2 Decimal Places
How to Cast from Cftyperef to Axuielement in Swift
Swift System Version Checking on Ubuntu
Iterating Through an Array of Strings, Fetched from Mongodb
What Does an Underscore "_" Mean in Swift
Error Loading Media Sources in Mlmedialibrary
Emitting a Warning for a Deprecated Swift Protocol Method in Implementing Types
Xcode Failed to Resolve Dependency Firebase - Googleappmeasurement Does Not Match Requirement
Why I Can Not Use Setvalue for Dictionary
Implement Protocol with Different Associated Type
Does Swift Allow Code Blocks Without Conditions/Loops to Reduce Local Variable Scope
Control a Nstabviewcontroller from Parent View
Views Are Merged Instead of Showing Them Separately