Filtering through CD relationships in swift - swift

How can an array of person objects be extracted from an array of memberships that have person.personId != self.id?
For an array of memberships, each has a person object. I would like to get all the person objects directly for all other persons.
If getting the first one like this
if let memberships = self.memberships.allObjects as? [Membership],
let person = memberships.filter({$0.person.personId != userId}).first?.person {
How can every person be extracted and returned in an array using swifts collection functions?

You could try something like this:
if let memberships = self.memberships.allObjects as? [Membership] {
// Filter to remove the membership with userID,
// and then map to an array of people
let people = memberships.filter({$0.person.personId != userId}).map { $0.person }
}
Somewhere it looks like you are going to need to map an array of Memberships to an array of person objects. Hopefully if the above isn't exactly right it will point you in the right direction.

Related

Query MongoDB Realm array only at first index

I need to query MongoDB Realm from synced iOS and Android app. In Swift I can write something like this:
let dictionary = realm?.objects(myReamlObject.self)
let results = dictionary?.where {
$0.senses.glosses.term == "the term I want"
}
or using predicate:
let results = dictionary?.filter("ANY senses.glosses.term == %#", "the term I want")
Both work well, but I don't want to check ALL senses.glosses.term.
Every entry has (or could have) many senses and many glosses.
I would like to check term of first senses in first glosses only.
Something I would write like this:
let results = dictionary?.where {
$0.senses[0].glosses[0].term == "the term I want"
}
But it gives error:
Referencing subscript 'subscript(_:)' on 'Query' requires that
'List<myRealmObject_senses>' conform to 'RealmKeyedCollection'
Any suggestion on how to query only first index of an array in MongoDB Realm? Thank you
Let me re-state the question
How to query a Realm objects' List property - but only query on the first
element in the List.
The answer is going to depend on the amount of results being worked with.
Here's how to do it in a way that's O.K. for small datasets but NOT RECOMMENDED
Your models were not included in the question so let me use a simplified model of a PersonClass that as a List of DogClass objects
class PersonClass: Object {
#Persisted var name = ""
#Persisted var dogList = List<DogClass>()
}
class DogClass: Object {
#Persisted var name = ""
}
The idea here is to use Swift high-level functions to only test the first item in each persons doglist for a match (this can be applied to other languages as well)
//get all the people
let peopleResults = realm.objects(PersonClass.self)
//use the high-level Swift function compactMap to return all of
// the people whose first dog is named "Spot"
let persons = peopleResults.compactMap { person -> PersonClass? in
if person.dogList.first?.name == "Spot" {
return person
}
return nil
}
The downside is that this code overrides a fundamental advantage of Realm - that Realm objects are lazily loaded if Realm functions are used e.g. as soon as a high-level Swift function is used, ALL of the objects are loaded into memory, potentially overwhelming the device.
A better option is to simply add a managed property to the PersonClass that also points to the 0'th element in the list.
class PersonClass: Object {
#Persisted var name = ""
#Persisted var dogList = List<DogClass>()
#Persisted var mainDog: DogClass?
func addMainDog(withDog: DogClass) {
self.dogList.append(withDog)
self.mainDog = withDog
}
}
as you can see, there's also a function to add that first dog to the list and also populates the mainDog property which points to the same object. It's one property so the overall impact is very low but the advantages for simple queries are very high.
From there the query becomes trivial
let peopleResults = realm.objects(PersonClass.self).where { $0.mainDog.name == "Spot" }
Expanding on this, you could save the 0th element of each List object in the Parent object or even have a property in each child object that points to the first element in it's respective list.

Delete specific object from LinkingObjects list - Realm Swift

I am currently trying out Realm on a test project and I have been struggling with removing a specific object from a List. LensDBObject and ListDBObject. LensDBObject contains a list of lenses and ListDBObject are lists of existing lenses. A lens can be in multiple lists and I'd like to remove a specific lens from a specific list but not remove if from the other lists.
Below are my two classes:
#objcMembers class LensDBObject: Object {
dynamic var id = UUID().uuidString
dynamic var manufacturer = ""
dynamic var series = ""
dynamic var serial = ""
dynamic var isSelected = false
override static func primaryKey() -> String? {
return "id"
}
let objects = LinkingObjects(fromType: ListDBObject.self, property: "lensList")
}
#objcMembers class ListDBObject: Object {
dynamic var listName = ""
let lensList = List<LensDBObject>()
}
Below is my code to find a specific lens in the list I want. The values returned are what I expect.
let listToSearch = realm.objects(ListDBObject.self).filter("listName == %#", "List 542")
print(listToSearch)
let filteredResults = listToSearch[0].lensList.filter("manufacturer == %# AND series == %# AND serial == %#", "Panavision" , "Primo Prime", "407")
print(filteredResults)
However, when I try to delete filteredResults, it deletes it from the lensDBOject altogether. I just want to be able to delete this specific lens from this specific list.
try! realm.write {
realm.delete(filteredResults)
}
I tried using for loops to get the index of the lens in the list and then delete it directly from that. But it still deletes the lens everywhere.
Am I missing something? Should I be using a one-to-many relationship as opposed to a LinkingObject?
Thanks for you help!
Try something like this. You only want to remove the lens from the list, not delete it from the Realm.
try! realm.write {
filteredResults.forEach { lens in
if let index = listToSearch[0].lensList.index(of: lens) {
listToSearch[0].lensList.remove(at: index)
}
}
}
Note that this will remove from that one specific list all lenses that match your filter.
Edit: Updated to reflect Realm's custom List class.
The if let is required, because index(of:) could potentially return nil if the object is not found in the list. Additionally, we must do it one item at a time rather than getting all the indexes first, since removing an item would cause the index array to be wrong.

CoreData: Trying to sort

I have two entities : EntityA and (<-->>) EntityB
and I am trying to fetch all EntityA sorted by EntityB.displayOrder
let request: NSFetchRequest<EntityA> = EntityA.fetchRequest()
context.perform {
do{
var data = try self.context.fetch(request)
let sort = NSSortDescriptor(key: "displayOrder", ascending: true)
for (index,dat) in data.enumerated() {
let entitiesB = (dat.entitiesB?.sortedArray(using: [sort]))
data[index].entitiesB! = NSSet(array: entitiesB!)
}
self.testListTableVC.testData2 = data
self.testListTableVC.tableView.reloadData()
}
}
}
sort seems to be working, but when setting it back to data it isn't sorted..
You are sorting entitiesB, and then setting the data[index].entitiesB equal to entitiesB casted as an NSSet. If you read about NSSets in the docs, you'll see that they are not sorted lists.
You're essentially doing superfluous work, because you're sorting this array and then casting it as an unsorted NSSet
I don't know how you have your model setup, but it looks like you need this data for your testListTableVC.testData2 property. And it seems like whatever kind of array data is, it has a property called entitiesB which is an NSSet. I would recommend making it so that you can use a Swift Array, which would stay organized.

load from json array into object array swift

I have array of user
var User:[User] = []
I want by alamofire and swiftyjson get info from http://jsonplaceholder.typicode.com/users
I know how to request and then i have array of json
how i can make loop through json array and create object of user then append in array User[]
I think my problem with loop , this is from swifty json page
for (index,subJson):(String, JSON) in json {
//Do something you want
}
how i can use it in my App?
You can use similar following code
for (_, subDataJSON): (String, JSON) in dataJSON {
let u = User()
u.name = subDataJSON["name"].stringValue
u.id = subDataJSON["id"].intValue
u.active = subDataJSON["active"].boolValue
self.User.append(u)
}
Parse your data json in loop then at the end of loop append single user object to global class User array like that.
Then use your class scoped User array like as you want.

Realm: Query with variable in Swift 2

absolute newbie-question: I have a model that consists of two objects in a Realm-database: Person and Dog. Person contains a list of Dogs. How can I query/filter for a list of dogs when the name of the Person is being handed over from a previous VC? For a tableView I need the query at the top of my VC-code. To access a single Person, I tried
personName: String! (derived from previous VC)
let predicate = NSPredicate(format: "name = %#", personName)
let currentPerson = try! Realm().objects(Person).filter(predicate)
but I get
Instance member 'personName' cannot be used on type 'dogsVC'
What I want is simply list all the dogs of a specific person in a tableView.
Thanks in advance!
You will need to instantiate your predicate in viewDidLoad for example.
Or make it a computed property:
var predicate:NSPredicate {
return NSPredicate(format: "name = %#", personName)
}
And that's because you need to wait for your class to initialize before using self.