I save some strings and numbers to NSUSerDefault,
but when I uninstall and reinstall the app the data is ereased.
Is there a possibility to store data some where else? Maybe in keychain?
There are two places where you can store data that will persist after an app is deleted, but in both cases, it's not hidden data, so if that's what you're looking for, you're out of luck.
Your two possibilities are 1) Saving data to the photo library. (However, you can't read it back unless you get the user to select the photo for you.) 2) The address book. This is one place where you can create an entry and select it without user input.
You could stash a small amount of data in the comments field of a keychain record.
However, I doubt Apple would allow it because it would violate the principle of sandboxing the apps. It's hard to think of a legitimate reason to have an app leave data behind after it's gone.
Related
I have a social app, where the user can like photos... So, in order not to wait for fetching the data from the server, I want to store to the device, an array of strings, containing the photos' objectIds.. The question is, considering the user can like thousands of photos, is it good practise to use UserDefaults to achieve that?
EDIT
As pointed out by Eric Aya in the comments, NSUserDefaults aren't loaded automatically into memory when the app launches.
NSUserDefaults are loaded into memory when your application launches If you have a particularly large amount of data stored in NSUserDefaults then the time it takes your app to launch to load NSUserDefaults will be impacted by the amount of IO required to retrieve your data. The intended use case for NSUserDefaults is to store small sets of data such as default user settings.
A Plist may be a better solution (NSUserDefaults is just a Plist, the difference being is it's loaded automatically for you when the app launches). You will still have the same issues with load times when you decide to grab the Plist as you will be loading a file (the Plist) into memory. You will be able to handle this with something like a progress bar or an activity indicator which gives the user a nicer experience. than having to wait longer than usual for an app to open. CoreData is another option (usually intended for more complex data structures than strings, on the flip side it gives you the capability to scale your storage needs very easily if the complexity of your data increases), there's a fairly steep learning curve involved but it's a wonderful feature and is well documented by Apple: https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CoreData/
I would also recommend storing the data on a server where you could expose it via an API and cache the response using a Plist/CoreData/Whatever you like. This way if your users change devices they will still have access to the same data as it's stored remotely.
Good luck!
I'm exploring a business model that specifies how many times a (costly) function may be invoked per user in an application.
Right now whatever I save, e.g. user defaults, gets deleted when the app is deleted. When the app is reinstalled, the counter is back to zero.
What I need is a way to save information such that deleting the app still leaves the information intact.
I've seen examples that mimic the deprecated unique identifier, but that's per device, which is not what I'm looking for.
KeyChains appear to be the right way to go. I can store a unique ID there specific to the user as well as in the user defaults and that way can track also if the app was reinstalled.
I want to integrate in-app purchases into my application, and so I'd like to download .plist files whenever users buy new level sets. How can I download a file from a server and save it so that it stays in my iPhone app forever ?
EDIT
I want to achieve something like that:
As there are not many of these plists (never more than 20) I could just include them into the app and set a boolean value with isPurchased or so, right ?
If the user purchased the category, the boolean is set to YES.
Whenever new categories are added by me, I'll just have a whole new update like "Cut the rope" for instance do it. Is that a good approach ?
First: Why don't you use Apple's services for In-App purchases? Why using your very own implementation? I am not sure but...do you think you will get Apple's approval? As far as I remember, Amazon did something similar in the past and they didn't get it.
Second: I wouldn't use NSData for this purpose. If you have a valid property list, then it is the best solution to use
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfURL:[NSURL URLWithString:#"foobar.com/plistfile.plist"]];
You could then store this dictionary. To be honest, I wouldn't recommend using your solution. If I understood you correctly, you would have thousands of plists after some time. My suggestion: Use a "global" mutable dictionary as ivar of your App Delegate for example. This should be empty at the beginning. Then download your helper dictionaries as mentioned above and populate your global dictionary with
[[delegateInstance globalDictionary] addEntriesFromDictionary:dict];
each time you get new data.
Save it with
[[delegateInstance globalDictionary] writeToFile:#"path" atomically:YES];
and recover it each time your app starts up.
EDIT:
Of course you can do it that way. If these plists really store information, that's fine. For example you could store billing information there, so that they are not interchangeable for other users (or shouldn't be at least). BUT: If you only want to get information about the question if a users bought a specific level or not consider combining your information within one plist (as described above). Anyway: Consider a possibility for your users to get back their data. Think of somebody deleting your app accidentally. How do you want to explain to him all his purchases are lost? In-App purchases are safer.
Or at least: Store a copy of the receipts on your server and let the users login to gather what they paid for in the past ;-)
Have fun and good luck! :-)
Quick and dirty one-liner:
[[NSData dataWithContentsOfURL:#"http://<yourfile>.plist"] writeToFile:#"pathforthefile.plist" atomically:YES];
I want to keep some of the critical(and less memory consuming) data of my App(ex: licence key or user credentials), stored in the device. In normal scenario, when the user deletes the App from the device, all the data related to the particular App gets deleted.
But I would like to override this behavior, and store some important stuff inside the device's disk, so that it does not get deleted along with the App. How to do that? Any help is much appreciated.
you can always store the license key and user credentials in the ios keychain.. it will stay there even if you delete the app. You can use the SSKeyChain API to access the key chain. Keep in mind you can only trivial string info this way.
Hopefully for obvious reasons that isn't possible. (What if every app did that? They you'd delete every app on your device and still find that gigabytes of space were being taken up by "deleted" apps.)
No, if you want data to be saved even after deletion, you'd need to store it in "the cloud" somewhere.
I like to use CoreData and their entity model into my projects.
I need to know that how to store sqllite database into Iphone securely.
As everybody knows when the Iphone broken with jailbreak it have file system navigatable, that mean for me, someone or somebody easly open or copy to another envorinment my sqllite db. How do i protect my db for these issues ?
Thank you
Answer in bold.
If they have jailbroken your iphone and have the will to steal data, they will probably have the ability to decrypt anything you put there; this is especially so if the data is of any value. To use encryption in this scenario your application will have to store the password somehow, unless you expect the user to enter this every time using the iphone keyboard -- which is a big no-no from a usability point of view. I suggest you rely on the access baricades and remote-wipe facility provided by apple.
If your a going to rely on apples 4-numeric pin as a password -- i.e., to balance useability.... well that only has 10,000 combinations.... not very secure.
However.... the simplest and the time-tested approach is to use a reversible encryption block-cypher in block-chained mode to encrypt the content of the sensitive columns, and to retrieve the password from the user every time the application is started.
-- edit : further discussion --
If I was expecting contents to be encrypted in a mobile way, I would expect the user of the contents to have a USB stick with the contents on it and a security hardened laptop/netbook with the something like truecrypt running on it.
I was not aware that a phone can be jail broken without the consent of the user ?
On the iPhone 3GS all data stored on the phone is encrypted.
I don't know what you are storing, but leaving the security to Apple may be OK.
Did you read this?
http://images.apple.com/iphone/business/docs/iPhone_Security_Overview.pdf
If you really only have under 10,000 records, and they are smallish - like say a short string or two in size, then you could just use an NSDictionary / NSArray with 10,000 items in memory at a cost of 10k*.256k = 2.5 MB in memory, which is not much. If the queries will be simple, then you don't need sql at all. Just run through all records on each search.
You could store an NSDictionary as an exncrypted file, password protected, with the user entering the password on each launch.
Are you worried about someone who has stolen the phone getting the information? Or the person who owns the phone getting to the files your app contains?
If it's not the user there are safeguards you can take, like the password presentation every time (hint: users will hate it and your app will get all 1-star reviews).
If it's the user you are worried about, you are insane to think you can protect anything the user has on their own device. You can just apply some simple obsfucation and call it good.