ParseSwift queryConstraint on object - ios

How can i add a queryConstraint on a object?
This is my current code but it returns no objects. I guess my current code is actually to query on arrays and not objects. But I can't find a way to do this for objects.
let query = Device.query()
.where(containsString(key: "apps", substring: "Google"))
This is the database

I recommend looking at the playgrounds to see how to use ParseSwift properly. More specifically, finding objects.
The first problem is apps is an object, which is actually a dictionary. You can’t use a substring constraint on a dictionary or other object. The actual way to do it is:
let objectToFind = [“Google”: “300”]
let query = Device.query("apps" == objectToFind),

Related

Is there a way to access properties of an x-coredata:// object returned from an NSFetchRequest?

TL;DR: Is there a way to programmatically read/recall (NOT write!) an instance of a Core Data entity using the p-numbered "serial number" that's tacked on to the instance's x-coredata:// identifier? Is this a good/bad idea?
I'm using a method similar to the following to retrieve the instances of an Entity called from a Core Data data store:
var managedContext: NSManagedObjectContext!
let fetchRequest : NSFetchRequest<TrackInfo> = TrackInfo.fetchRequest()
fetchResults = try! managedContext.fetch(fetchRequest)
for (i, _) in Global.Vars.numberOfTrackButtons! {
let workingTrackInfo = fetchResults.randomElement()!
print("current track is: \(workingTrackInfo)")
The list of tracks comes back in fetchResults as an array, and I can select one of them at random (fetchResults.randomElement()). From there, I can examine the details of that one item by coercing it to a string and displaying it in the console (the print statement). I don't list the code below, but using workingTrackInfo I am able to see that instance, read its properties into other variables, etc.
In the console, iOS/Xcode lists the selected item as follows:
current track is: <MyProjectName.TrackInfo: 0x60000374c2d0> (entity:
TrackInfo; id: 0xa7dc809ab862d89d
<x-coredata://2B5DDCDB-0F2C-4CDF-A7B9-D4C43785FDE7/TrackInfo/p22>;
data: <fault>)
The line beginning with x-coredata: got my attention. It's formatted like a URL, consisting of what I assume is a UUID for the specific Core Data store associated with the current build of the app (i.e. not a stable address that you could hardcode; you'd need to programmatically look up the Core Data store, similar to the functions we use for programmatically locating the Documents Folder, App Bundle, etc.) The third item is the name of the Entity in my Core Data model -- easy enough.
But that last number is what I'm curious about. From examining the SQLite database associated with this data store, it appears to be a sort of "instance serial number" associated with the Z_PK field in the data model.
I AM NOT interested in trying to circumvent Core Data's normal mechanisms to modify the contents of a managed object. Apple is very clear about that being a bad idea.
What I AM interested in is whether it's possible to address a particular Core Data instance using this "serial number".**
In my application, where I'm randomly selecting one track out of what might be hundreds or even thousands of tracks, I'd be interested in, among other things, the ability to select a single track on the basis of that p-number serial, where I simply ask for an individual instance by generating a random p-number, tack it on to a x-coredata:// statement formatted like the one listed above, and loading the result (on a read-only basis!) into a variable for further use elsewhere in the app.
For testing purposes, I've tried simply hardcoding x-coredata://2B5DDCDB-0F2C-4CDF-A7B9-D4C43785FDE7/TrackInfo/p22 as a URL, but XCode doesn't seem to like it. Is there some other data Type (e.g. an NSManagedObject?) that allows you to set an x-coredata:// "URL" as its contents?
QUESTIONS: Has anyone done anything like this; are there any memory/threading considerations why grabbing instance names in this manner is a bad idea (I'm an iOS/Core Data noob, so I don't know what I don't know; please humor me!); what would the syntax/method for these types of statements be?
Thanks!
You are quite close.
x-coredata://2B5DDCDB-0F2C-4CDF-A7B9-D4C43785FDE7/TrackInfo/p22
is the uriRepresentation() of the NSManagedObjectID of the record.
You get this URL from an NSManagedObject with
let workingTrackInfo = fetchResults.randomElement()!
let objectIDURL = workingTrackInfo.objectID.uriRepresentation()
With this URL you can get the managed Object ID from the NSPersistentStoreCoordinator and the coordinator from the managed object context.
Then call object(with: on the context to get the object.
let persistentStoreCoordinator = managedContext.persistentStoreCoordinator!
if let objectID = persistentStoreCoordinator.managedObjectID(forURIRepresentation: objectIDURL) {
let object = managedContext.object(with: objectID) as! TrackInfo
print(object)
}

objectID many to many relationship

I need some help with my Swift rookie programming...
In a many-to-many relationship, I have a NSManagedObjectID that I`ve segued from another view controller.
To retrive data from it I have used this:
var elevid :NSManagedObjectID?
let person = context.object(with: studentId!)
nameTextField.text = person.value(forKey: "name") as? String
This works fine, but when I try to get an attribute from a relationship I`m stuck.
I´ve tried this:
let isAtSchool = person.value(forKeyPath: "isAtSchool.monday") as! Bool
but I get an error telling me:
Could not cast value of type '__NSSingleObjectSetI' (0x10ac63aa8) to 'NSNumber' (0x109e5a4a8).
If I use ? after as instead of ! it returns nil.
Someone know how to do this?
When you ask for the name property you're asking for a single value, so that's no problem. But when you're using this key path you're traversing a to-many relationship. There could be 2 or 10 or a million related objects, but you you're asking for a single Bool. How is that supposed to work?
It's not clear what you actually want in this situation. Of those potentially millions of related objects, how do you want to calculate the value of that Bool? Probably you want to do something like pick out a single related object out of those (potential) millions and get the Bool from that single instance. But for all I know you might want to scan over all of them and see what the most common Bool value is.
How to change your code depends on what you really need, how that single Bool value should be determined. One way or another you need to get from (potential) millions of related objects to a single Bool-- and you can't do that via a key path lookup.

Core data: Object ID changes

I'm trying to fetch object by object ID in a simple core data implementation. Using this api
let targetObj = CoreDataManager.sharedInstance.privateQueueContext.object(with: self.objectID) as! MyObj
but it seems object id changes. Here is the console log
(lldb) po self.objectID
0xd000000000280000 <x-coredata://551DDB76-537D-41FA-B923-F772E5EE5D29/MyObj/p10>
(lldb) po CoreDataManager.sharedInstance.privateQueueContext.object(with: self.objectID).objectID
0xd000000000280006 <x-coredata://551DDB76-537D-41FA-B923-F772E5EE5D29/MyObj/p10>
Please let me know if I'm doing anything wrong. Actually I'm book keeping these objectIds in an queue and need to dequeue the object based on these objectIds.
Thanks
Ankit
The only difference you're seeing when you print each object ID is the address in memory where the object ID is stored.
So, if you take those two objects and compare them with == they will be different, because that is testing referential equality.
If you compare those two objects with isEqual:, it will return true, because isEqual: is testing whether the values they each represent are equal.
You can't reliably compare objects by reference, you need to use isEqual:.

how to convert RealmSwift List to Results?

I am using a Realm List/Results as my dataSource for a UITableView. At some point I assign a list to it. like:
var dataSource:List<SomeObject>! // Or >> Results<SomeObject>!
let aRealmObject = realm.objectForPrimaryKey(SomeObject.self, key: objectId)
dataSource = aRealmObject.someList // dataSource should be List
Then I have a filter on this list If the user changed the filter dates, I do like this:
dataSource = dataSource.filter("FILTER THE DATES",newDates) // dataSource should be Results
But the line above causes an error as the return type of filter is a Results object and aRealmObject.someList is a List.
What is the best way to deal with this situation?
make dataSource as a List and convert the Results object to List? How??
make dataSource as a Results and convert the List to Results? How??
Or may be you have a better way of doing it, Please share it with me.
Thanks,
I have found A simple way to convert List to Results making use if the filter method, it always returns Results object. Just gave it a true predicate.
dataSource = aRealmObject.someList.filter("TRUEPREDICATE") //this is a Results object.
Both List and Results (as well as LinkingObjects) can be converted into an AnyRealmCollection type. I think this is probably the best way to standardize all of Realm's array-type types:
var dataSource:AnyRealmCollection!
let aRealmObject = realm.objectForPrimaryKey(SomeObject.self, key: objectId)
dataSource = AnyRealmCollection(aRealmObject.someList)

Update dictionary with previously deleted items

I have two dictionaries. Both declared in a viewController, both based on a model structure class.
// ItemDictionary
var ItemDictionary = ItemModel()
var JSONDictionary = ItemModel()
JSON data is fed into the JSONDictionary and then this data is passed to ItemDictionary which feeds a table within ViewDidLoad.
self.ItemDictionary = self.JSONDictionary
All good. The table is nicely populated from JSON data. I can also delete items from the table and the ItemDictionary. However, when I try and add items back by referring to the original dictionary (JSONDictionary) the item has gone.
I understand this is expected. If Dictionary1 = Dictionary2, a new dictionary is not actually created. Only an second address. So if you change Dictionary1, Dictionary2 also changes.
A practical example could be setting a price range. You can reduce the range and have less items displayed on the table. But you can't replace previously deleted items if you wanted to increase the price range. I do not want to recall the JSON script each time I edit the range. Advice appreciated.
As confirmed by the OP, ItemModel is a class and not a Dictionary. To fix this you need to make ItemModel a real Dictionary and thus a value type. This is probably the preferred choice but will be more work.
An alternative would be to add an convenience initializer to the ItemModel class that instantiates a new copy of itself and call that instead of setting self.ItemDictionary = self.JSONDictionary.
Something like this.
init(model: ItemDictionary) -> ItemDictionary {
// copy properties
}
Then create the new copy.
self.ItemDictionary = ItemDictionary(self.JSONDictionary)
Later you can reinitialize ItemDictionary with the same call.
Try this code out-
var dictionary1 = ["name": "Magnus"]
var dictionary2 = dictionary1
dictionary2.removeAll()
print("\(dictionary2) \(dictionary1)")
The output is :-
[:] ["name": "Magnus"]
Thus 2 new dictionaries are being created. If you refer to the Swift documentation, You will find that in swift, references are hardly present.
Some other portion of code might be responsible. Hope this helps :-)

Resources