URL scheme with core data managed object (iOS) - ios

I am wanting to add URL schemes to my iOS app, however the URL needs to be able to point towards a certain NSManagedObject from Core Data. I'm quite happy for my app to have to generate the URL for the user to use, but it just doesn't seem right to use the whole NSManagedObject URI in the URL.
When I retrieve the URI of the managed object, it is like this:
x-coredata://633EAF37-A03D-4954-976D-B3B0C32F8033/MyObject/p7
I'm guessing I can drop the x-coredata:// part which I can put back in my application:openURL method, but this still leaves me with a URL like this:
myurlscheme://event_to_perform?object=633EAF37-A03D-4954-976D-B3B0C32F8033/MyObject/p7
Is there more I can do to shorten this?
What about the has part 633EAF37-A03D-4954-976D-B3B0C32F8033? Will this be the same across every device the app is installed on, or is it unique?
If it was the same across devices then i'd only really need to use the final p7 as everything else I could add back in a string.
Any advice appreciated.
Thanks

Perhaps have a look at Permanent NSManagedObjectID not so permanent? first about the fragility of passing a NSManagedObjectID around. Marcus S. Zarra claims that the objectID can change during the life of a object.
That being said, the URI for a permanent managed object id seems always to be built like this:
x-coredata://<UUID>/<EntityName>/p<Key>
where
<UUID> is the NSStoreUUIDKey value of the metadata dictionary of NSPersistentStore,
<EntityName> is the entity name :-)
<Key> is the primary key that SQLite uses internally for the table (but which is invisible
to the Core Data API).
But note that this is only what I observed. The format is not documented and can probably
change at any time.
The <UUID> is generated when a store file is created, so it is not the same across every device the app is installed on.
So if the above analysis is correct and the URI scheme does not change in the future,
then you could indeed reconstruct the managed object URI from the final component p<Key>
alone.

That feels like exposing your implementation too much. I would highly recommend you maintain your own unique id property in the entity and use it to fetch the right entity from CoreData when you get a URL lookup.
This future proofs you should you ever, say, start syncing to a web-based version of your app or some other data store that is not CoreData.

Related

How bad is it to show Parse object id's to user?

I have a built in QR Code scanner in my iOS app. My backend runs on Parse, and I want the user to be able to pick certain objects on the app and encode their id's into a QR Code and share it around so that users can later scan a QR code, receive the object id's, and query them on the database to later fetch and display them somewhere.
However, what is stopping someone from using a QR scanner outside my app, looking at the object id's encoded into the QR, and messing something up? How bad is it to somehow allow users to see the object id of an entry in your Parse database? Will this heavily compromise security?
I thought about encrypting the object id's but am afraid my app will be rejected by Apple because of not following proper standards. What do you guys suggest?
Short answer: No.
There is no major security risk in giving away object IDs. Unless the 3rd parties had access to your app keys, then there is no way for them to access your data, even if they already knew everything about it. As long as you keep your app keys well hidden, there is no way your users can change anything outwith what you've de
Remember that your object ID's are only unique in the scope of your app (perhaps only even in the scope of that particular class), so when they find the object ID, they don't know if it's your app, my app, or anyone else's app - to them, it is as useful as holding a random set of digits.
The bigger issue I would say is that you cannot set the object IDs, so if for whatever reason that line is deleted, you can reinstate every part of it, but they'll all have different object IDs. This would mean your users running around with meaningless QR codes. Sure you can restore from a backup, but you'll lose any other changes since then. This is why I would never recommend indexing using Object IDs, rather that you create a new column "ID" that can then be changed by you, and then scripting a piece of cloud code logic in the side to ensure it is unique.
Sharing the object ID is not an issue, so long as your app has proper security. Hopefully your app's security does not rely on keeping the object ID secret.
Encryption is fine in iOS apps, so long as you file the proper paperwork. One of my apps uses a very high level of encryption and is available in every country, except France. You just need to file the correct paperwork and it's not that hard to do.

RESTkit, CoreData: process object right before trasferring it to CoreData

I have a problem.
I have iOS client app that has to allow multiple users to log in and store their data locally.
Data is synchronized with RESTful service, and the latest snapshot along with user's changes should be stored locally for all users.
Previously this app was implemented with SQLlite as data storage engine.
Now I would like to migrate to CoreData.
What do I have:
server returns me entities for current user. User ID is not sent, as the user authorizes and gets their session;
I know who is logged in an should store all data for this particular user. In order to do that I need to say CoreData to store the object for the user with ID=12345.
The problem is:
I have to tell CoreData to store the particular object associated with particular user's ID.
I need a way to somehow alter the object mapped with RESTkit - setting proper ID field for it.
This task was straight and simple with SQLlite but looks problematic with CoreData.
I am still thinking that I don't know something about CoreData asking you to help me with clarifications or useful links.
There isn't a good way to do it.
Hacky, you could add the id as a parameter in the request so you can map it back again (requires RestKit dev branch at time of writing).
Non-hacky is to update and re-save the objects returned in the mapping result.
Alternatively you could use one operation to download the JSON, then mutate it, then run another operation to map it.

Remote Server Searching in RestKit with Core Data

I have an application that talks to a remote API using RestKit with an SQLite store for Core Data. When I got to the point of adding server-side searching, I was faced with having to find a way to efficiently display search results. To accomplish this, I used an NSFetchedResultsController that is tied to another in-memory store of the same schema as the SQLite store, and also backed by RestKit. When RestKit searches against the API's search endpoint, it maps the responses back to the in-memory store.
This works really well for what I need, but has now caused another issue. When I get these "transient" objects back from the server, and the user selects one, it needs to be copied into the persistent store at that point (various interactions beyond that point will load additional objects from the server and attempt to tie them back to the original object - which will fail if they're in two different object contexts).
tl;dr
Does anyone have any suggestions on how to copy an entire object (entity and relations) from one core data store to another? Or, is that even necessary? Is there an easier way to accomplish this same task using RestKit?
Would I be better served by changing my search instead, to not use an in-memory store? If so, how should I store these objects?
I wouldn't use the in-memory store. I'd just put the search results into the main store and bypass the issues with copying. I'd then have a purge that ran to clean out the old search results that aren't required any more. You might want to tag search results that need to be kept around for some reason. And you can get RestKit to do the purge automatically when each new search is performed (see "Fetch Request Blocks and Deleting Orphaned Objects" in these docs)
For your other question, about tagging. When you make the search request, the search term is in the URL. If you use RKObjectManager and routing then you can access the metadata that is provided to the mapping to get the search term and store it into the returned objects. Something like:
#"#metadata.routing.parameters.searchTerm": #"searchTerm",
See the metadata docs here.

CoreData Update Database Leaving User Entries

First, Thank you for any help provided.
I have an iOS leveraging CoreData to retain various presentations, this data comes from a sqlite file and there is no server connection.
I will have to be able to provide App updates (via appstore), this update may add more data to the database.
The tricky part is that it can not simply overwrite the current database, there are a few user tables that I will not like touched.
Please provide any information I should consider when accomplishing this or any links are greatly appreciated.
Thank you.
Given your app has no server connection, you will have to rely on shipping data within the updated application itself. I would recommend using a plist file or define your own xml or json structure. You can then read this data to create/update core data nsmanagedobjects.
It looks like someone in the past was using plist->coredata on SO
Would you have relationships between user created data and shipped data?
If not, you might go the route of connecting two stored to the persistent store coordinator. The shipped store would be read-only. The store with user created data would be read-write. You can use this approach, too, if you have relationships between shipped and user-created objects, but it's a lot more complicated, since CoreData doesn't manage cross-store relationships for you, and you'll need to write your own logic (doable, but not straight forward).
If you need to have relationships between shipped and user-created objects, you can still ship a CoreData store. When the app launches for the first time (no user-created objects), you copy the store to the Documents folder and user this store to create your CoreData stack. User created objects will be added to this store. Once you have new 'shipped' objects (i.e. a new store in the app-bundle), you'll have to manually migrate that stores data into the store that the user has changed. You'll have to be able to find
(1) objects that need to be deleted
(2) objects that need to be updated (changed)
(3) objects that need to be added
If you mark your shipped objects with a special flag such that you can tell if it's a user created object or a shipped one, that would be doable. You also have to have some sort of ID to be able to tell which objects in the new store correspond to which ones in the existing (old) store.
You do not need to go the route of using plists. In fact, I'd recommend against it. You can easily open two stores at the same time. Either to use both stored, or just to migrate objects from one store to the other store.

Rails - Store unique data for each open tab/window

I have an application that has different data sets depending on which company the user has currently selected (dropdown box on sidebar currently used to set a session variable).
My client has expressed a desire to have the ability to work on multiple different data sets from a single browser simultaneously. Hence, sessions no longer cut it.
Googling seems to imply get or post data along with every request is the way, which was my first guess. Is there a better/easier/rails way to achieve this?
You have a few options here, but as you point out, the session system won't work for you since it is global across all instances of the same browser.
The standard approach is to add something to the URL that identifies the context in which to execute. This could be as simple as a prefix like /companyx/users instead of /users where you're fetching the company slug and using that as a scope. Generally you do this by having a controller base class that does this work for you, then inherit from that for all other controllers that will be affected the same way.
Another approach is to move the company identifying component from the URL to the host name. This is common amongst software-as-a-service providers because it makes sharding your application much easier. Instead of myapp.com/companyx/users you'd have companyx.myapp.com/users. This has the advantage of preserving the existing URL structure, and when you have large amounts of data, you can partition your app by customer into different databases without a lot of headache.
The answer you found with tagging all the URLs using a GET token or a POST field is not going to work very well. For one, it's messy, and secondly, a site with every link being a POST is very annoying to work with as it makes navigating with the back-button or forcing a reload troublesome. The reason it has seen use is because out of the box PHP and ASP do not have support routes, so people have had to make do.
You can create a temporary database table, or use a key-value database and store all data you need in it. The uniq key can be used as a window id. Furthermore, you have to add this window id to each link. So you can receive the corresponding data for each browser tab out of the database and store it in the session, object,...
If you have an object, lets say #data, you can store it in the database using Marshal.dump and get it back with Marshal.load.

Resources