I am using the NSUserDefaults' api -registerDefaults api to register the factory defaults of my application. All is fine for the first version of the application. But when I provide an update for the iPhone application, I have 3 criteria to make sure:
The user preferences of older version app should be intact.
Addition to the factory defaults specific to the new version should be applied.
Providing flexibility in the design to the future version updates so that the user defaults modifies itself based on the new version.
The api -registerDefaults does not register factory defaults in new version updates because a plist file containing user preferences already exists in the /Library/Preferences of sandbox. And in case if we reset the preferences with new factory defaults, user preferences of previous version will be lost.
I think there should be a design pattern to handle such cases, so in general how do we cater with such situations? Doesnt Apple provide any inherent support for this? Or am I missing some links, I tried googling around without any success.
Thanks,
Raj
If this list of items you're talking about is an array registered under a single key, then yes, a larger array passed to -registerDefaults: will be ignored in favor of the smaller array stored in the persistent plist. NSUserDefaults tracks stuff on a per-key basis, and doesn't do any interpretation of the contents you store in there, so it's not going to try to automagically merge previous array values with new array values, or anything daft like that.
If you want new items to be added to this array by default when the user upgrades, I would recommend adding the items explicitly to the key yourself by fetching the existing array, adding the new items, and then saving the larger array back to the user defaults again. You can use a separate boolean flag to indicate that the upgrade has been done, to ensure that the addition doesn't get performed multiple times.
What is the problem? If the user never changes (or more exactly: sets) a preference, the factory default will be used. If an update of your app changes the factory defaults, those will be used instead. If the user has set his own preference, that will continue to be used.
A new factory default doesn't (and shouldn't) overwrite an user set preference. NSUserDefaults does exactly what you seem to be after.
I agree with Johan Kool. User defaults work as they should. If there's a preference that you want changed (for whatever reason) in an updated app version, just slightly rename the preference. For example, if someValue was a preference in version 1, then in version 2 name it someValue_v2 and your new factory default will take effect.
Related
I have added a 'number_of_members' value to the Customer DocType via customization.
In my application I have tried several ways to update the value. However the value never updates in the webpage. I feel like I'm missing some sort of save or update or commit step.
For example I have tried:
frappe.client.set_value('Customer', '00042', 'number_of_members', 8887)
frappe.set_value('Customer', '00042', 'number_of_members', 8887)
frappe.db.set_value('Customer', '00042', 'number_of_members', 8887)
and also
customer = frappe.get_doc('Customer', '00042')
customer.number_of_members = 8887
customer.save()
In each case I can do something like frappe.get_value, or frappe.get_doc and it shows the value is set to 8887. However it never updates in the web side. This is what makes me think I'm updating some sort of cache or database transaction and I need some way to save it, but have not had any luck.
I am mostly testing this via bench console if that has any bearing on it, but I've tried a couple of the methods in my application code as well.
Relevant documentation:
Frappe Developer API - Document
Frappe Developer API - Database
Turns out the answer is to call frappe.db.commit() after making changes. If someone can point this out in the documentation so I can better understand how I'm missing stuff, I would appreciate it.
I also noticed if you try to Save something in the UI before you send frappe.db.commit() the UI will hang.
So I made an iOS app in Swift, and published it to the app store. In that app, I have saved some important KVPs in UserDefaults.standard. Typically, when updating the app, the KVPs would transfer over to the updated version without issue.
Now I'm remaking the app in Flutter/Dart. I want a smooth transition for existing users. Specifically, when users update from the Swift version to the Flutter version, the UserDefaults data should still be stored. However, when I tried testing this out (using Flutter's shared_preferences module to get existing keys), the keys appeared to be "gone".
The reason they're "gone" is that Flutter prefixes all keys with "flutter.". As such, when it saves key XX, it's actually saving flutter.XX, and when you try to retrieve key XX, you're actually retrieving flutter.XX. But in the Swift version of the app, I saved it as XX, not flutter.XX (obviously), so now Flutter "can't find it".
The functionality that enforces the prefix is spread across shared_preferences.dart and SharedPreferencesPlugin.m. I could technically modify these files to remove the prefix, but I'm not aware if there would be any negative side effects to doing so.
Any ideas on either how to access my old KVPs without entirely modifying the Shared Preferences plugin? And/or anyone know whether modifying the plugin to remove the prefix would cause any unintended side effects?
I have a project and I am using core data.
I have some entities, with attributes. When I started the project I choose some atributes and now I want to change their types (Int to String for example). ANd so I did it.
THe thing is, I am getting errors...
I checked the code, I think every thing is ok.
I even deleted the entire entity and made a new one with some name but it doesn't work.
How can I change it with success?
You can use code data migration for this by creating new version..
To change data types you need to create a new version of the database, you can not just simply modifie it because that way your users would have to delete and redownload your app every time you change something.
Here you can read how to do this.
The simulator or device you are running the app on still 'remembers' the old type and data. Simply hold down on the app and press the 'X' to delete it. When you press play in XCode it will reinstall the app with the new data types.
I use doctrine2.2.2 with Zend Framework1 and am currently working on an editing tool.
A user clicks a link to move someting "up" in the list, my action does its work, changes are made to teh database, i redirect but then the result, newly fetched from the database is still the old version.
I would figure it has to do with cache since i am not temporarily storing the object in the session or anything.
So the Question is: Is there a way to fetch something and tell Doctrine, not to use the cache for this specific request? Or is there a possibility to delete certain cache entries?
Yep, take a look at http://readthedocs.org/docs/doctrine-orm/en/latest/reference/caching.html?highlight=cache#result-cache .
There is a query api to enable, disable, ... result cache for example, individuallty on each query; or globally.
I have an iPhone app that stores some settings using NSUserDefault standardUserDefaults.
When I add new features to the app I need to add new default settings and so I have to migrate/upgrade the NSUserDefaults. For now, I just store the version number and check this when the app is launched. It has quickly become very messy as I have to add lots of if statements. I cannot assume that the user is just upgrading from the previous version but perhaps even a couple of versions before.
I like the way that CoreData seems to handle migrating table changes but I want to provide 2.2.1 SDK compatibility and of course CoreData is not the same thing as NSUserDefaults.
Any suggestions or best practices?
Hmm… I wouldn't "upgrade" the user defaults in this way, but instead query NSUserDefaults as usual, only if the default isn't set (objectForKey will return nil in that case), use a default value (which may then be written back to the user defaults to save time the next time). Since you'll have to do this every time a "new" default (i.e. one that didn't exist in 1.0) is read, I advise doing a wrapper class/file that does this, this way the code is written only once for each "new" default.
Also, while the question/problem is different, this answer works just as well in your case.