Querying multiple (n=7) classes with pointers - ios

I need to produce a 'feed' of activities using a PFQueryTableViewController.
I have 7 classes that all contain various activities (ie. Paymenmt, Meal, Note....). They all contain pointers to the Child class.
What I'd like to do is query all these classes to pull the latest activities for the corresponding child and return the objects for each class.
I have tried,
override func queryForTable() -> PFQuery {
let queryNote = PFQuery(className: "Note")
queryNote.whereKey("child", equalTo: passedChildID!)
let queryPayment = PFQuery(className: "Payment")
queryItem.whereKey("child", equalTo: passedChildID!)
return queryNote
}
However I am running into trouble as I can't return an array of queries.
I also tried query.orQueryWithSubQueries but that only works with queries of the same class.
Parse documentation gives examples, but only for 2 classes (for example).
query.whereKey("post", equalTo: PFObject(withoutDataWithClassName: "Post", objectId: "1zEcyElZ80"))
Any help would be appreciated.

Unfortunately, there is no way to do this. You can only query 1 class at a time.
A possible workaround could be to create an Activity class that contains the gist of each activity and then add a pointer to the correct activity (i.e. a Meal).
In this way, you could query for all the latest activities, and also get the Meal/Payment/Note objects using the include statement.
However, each Activity object would need to have a column for each type of activity, so if you had 10 different activity classes like Meal, the Activity class would then need 10 such pointer columns. It is not a beautiful workaround, but it would work.
Not knowing your datamodel I would still advise that you rethink it and see if it could be possible to do it differently. When you develop a mobile application you should plan your data model based on the queries you need to make rather than the old-fashioned RDBM way of thinking strictly in autonomous objects.

Related

Fetching the latest entity from a relationship in Swift Core Data

Im trying to find the best way to get the latest entity from a relationship with swift and core data.
For example I have a Conversation with many Messages:
Conversation Entity:
id = 1, name = "Test"
Message Entity:
id = 1, body = "Test", conversation = 1
id = 2, body = "Test", conversation = 1
In my SwiftUI View I have this FetchRequest:
#FetchRequest(sortDescriptors: []) var conversations: FetchedResults<Conversation>
What would be the best way to access the relation and get the latest result while looping over the conversations in View like this:
List(conversations) { conversation in
Text(conversation.name ?? "")
Text(conversation.messages.latest.body ?? "") // <--- Trying to do something like this
}
The best way is to store the data you need in the entity you are fetching. So in your case make a latestMessageBody property on the conversation entity. Apple provide derived attributes to automate this.
It's a common mistake to think of Core Data as a relational database, instead just think of it as a way to persist what you see on screen and design your entities based on how you want to fetch and display them. If you are making too many fetches on one screen then its time to redesign the entities.
I.e. you wouldn't want to fetch the latest message for all the converstations you want to show that is too many fetches. And you don't want to load in all the messages for every conversation just to find the latest, that has too high memory overhead. This is why Core Data offers denormalisation via the derived attributes feature.
Another point is #FetchRequest (which is powered by NSFetchedResultsController by the way) only tracks changes to the entity that is currently fetched. So if you reach into relations to show data, that view won't update when the related object changes. You can work around this by passing the object into another View marked with #ObservedObject however that doesn't work for a 1-to-many relation.
There is a neat trick using entity inheritance to allow a NSFetchedResultsController to work on multiple entities however I don't think that is suitable for this use case.

Parse & Swift - How to Reduce Server Load/Requests?

I've been developing an application that has a home page, similar to that of Instagram's where the number of comments is displayed below a post as the user scrolls. Once the user taps on the label with the number of comments, the actuals comments will then load onto the screen. I've been trying to achieve something similar to that with my application, but I feel as if the method that I am doing this with is sending to many requests (queries) to the server in order to get the number of comments to display below each post. I was wondering if there was a more efficient/concise way to do this that would reduce the server load, but still have the same effect.
To add more context (Note: I'm using Parse):
I have a class named Posts which contains the posts
I have a class named Comments which contains all of the submitted comments. In order to obtain the comments for a particular post, I query for comments (which have a column named: "parentObjectID") whose column ("parentObjectID") matches with the parent post's object ID.
Example code is below:
let query = PFQuery(className: "Comments")
query.whereKey("parentObjectID", equalTo: objectIDs[indexPathNums])
query.order(byDescending: "createdAt")
query.findObjectsInBackground { (objects, error) in
if error != nil {
print("An error occured (USQVC Comments Query)")
}else {
if let tempArray = objects {
for comment in tempArray {
if let x = comment {
myArray.append(x)
}
}
commentsCount = myArray.count
myArray.removeAll()
}
}
}
Even though they've updated their UI, I just wanted to include a picture in case what I was describing was unclear:
I'd appreciate it if anybody could help me out with this. Thanks!
As you pointed out in your comment above, you certainly can use the function incrementKey to increment the numberOfComments.
The best part is, this method is atomic, that means no matter how many people like the same post at the same time, say 5 people like a photo at exact same time, numberOfComments will increment by 5 instead of 1.
So this function will be executed one by one instead of concurrently. You absolutely can use it.

Realm Many to Many Query (Inverse too!)

My app's db has a many to many relationship between a Feed object and a Tweet object. This is to keep track of which feeds every tweet belongs in. If you're familiar with Twitter, imagine the main feed, a list feed, a user profile feed, etc.
How can I make a query using an NSPredicate to get a list of Tweets that exist in a specific Feed (and, inversely, get a list of Feeds that a Tweet exists in)? It seems that queries on inverse relationships does not work in Realm, so what are my options?
If I understand your question correctly this part of the documentation should be helpful:
Inverse Relationships Links are unidirectional. So if a to-many
property Person.dogs links to a Dog instance and a to-one property
Dog.owner links to Person, these links are independent from one
another. Appending a Dog to a Person instance’s dogs property, doesn’t
automatically set the dog’s owner property to this Person. Because
manually synchronizing pairs of relationships is error prone, complex
and duplicates information, Realm exposes an API to retrieve backlinks
described below.
With inverse relationships, you can obtain all objects linking to a
given object through a specific property. For example, calling
Object().linkingObjects(_:forProperty:) on a Dog instance will return
all objects of the specified class linking to the calling instance
with the specified property.
I guess you can do something like:
//assuming your Tweet object has a property like "let feeds = List<Feed>()"
someTweet.linkingObjects(Feed.self, forProperty: "feeds") //should return feeds your Tweet is in
But still I don't think I understand your question clearly. From my point of view your first requirement:
get a list of Tweets that exist in a specific Feed
should have a straightforward solution such as having a property in your Feed object like:
let tweets = List<Tweet>()
I wish you can clarify your situation further.
I wonder if it's possible to simplify the model a bit so many-to-many isn't necessary.
My understanding of Twitter is that tweets aren't 'owned' by any feeds. They simply exist on the platform, and are referenced by any number of feeds, but don't actually belong to any specific feed.
So a model setup like this should be appropriate:
class Tweet : Object {
}
class Feed : Object {
let tweets = List<Tweet>()
}
You can do a reverse lookup on a Tweet to see if there are any feeds in which it is currently visible, and you can simply use the tweets property of Feed objects to see which tweets they're displaying
Since the linkingObjects reverse lookup method of Realm simply returns a standard Swift Array, if you did want to filter that further, you could just use the system APIs (like filter or map) to refine it further.
Otherwise, if you really do want to be able to use Realm's NSPredicate filtering system both ways, then, as messy as it is, you would need to manually have each model linking to a list of the other:
class Tweet : Object {
let feeds = List<Feed>()
}
class Feed : Object {
let tweets = List<Tweet>()
}
While it's not recommended (Since it adds additional work), it's not disallowed.
Good luck!

How to get all Created Class Names in Parse using swift?

Can anyone please tell me a way to Query the list of classes created in the Parse Core. I am using Swift 2.0 and XCode 7.
Basically, I have 4 different classes (example : Class1, Class2, ClassName3, ClassName4) holding the different data. I want to get only the class Names and display it in my app using PFQueryTableViewController.
override func queryForTable() -> PFQuery {
var query : PFQuery = PFQuery(className: "ClassName1")
query.orderByAscending("songName")
return query
}
Above code queries the data from ClassName1, however, I want to display the class names not the data within a particular class.
Thanks
Thanks a lot
It isn't available via the iOS SDK.
You can get it via the REST interface if you use the master key to fetch the app schema: https://api.parse.com/1/schemas
It may be easier for you to just add a Classes class with rows for each of the classes, which you manage manually and can simply query with PFQuery...

How to Access Pointer Values in Parse Database

I am working on an iOS app, running on Parse(backend).
I am having problems with accessing the contents of another class from a query I made.
So I have this table. Let's call it "Contests". it has the following data:
name,
date start,
date end,
pointer to organization table (the objectid)
And then the organization table:
name,
number of Facebook likes,
I want to be able to access the name of the organization and every other detail a certain contest has. Will I have to put a query inside another query, slight problem with that is that the queries require waiting time and it accomplishes it in the background. So I have:
findInBackground() {
findInBackground() {
}
}
Is there any better way to do this? Also I am getting multiple objects at the same time.
You need to do a query on your Contest table with whatever requirements you have but then add an includeKey call:
var query = PFQuery(className:"Contests")
//...Other query requirements
query.includeKey("organization")
query.findObjectsInBackgroundWithBlock {
}
includeKey will force fetch of the organization along with the contest details in 1 query.

Resources