Iphone SQLite initializing and closing - iphone

I'm new to working with iphone and SQLite i have my app working fine with SQLite but i would like to know what you all think is the correct / best way of opening an sqlite connection and closing it..
Would you
Initialise a DB connection on app load and close on app close..
Open and close connections when is needed..
Also is it good practise to constantly update db entries as you go or store all information in an object and write out at the end when needed..
There is not to much information on this via google just some useful small tutorials that cover delete / insert / update but not as a general overview of the best practise in using SQLite with iphone..
Thanks guys

Keep the connection open.
Whenever you execute a SQL query, it has to be compiled into a prepared statement. Once it's compiled, you can use it over and over and it doesn't have to be compiled again.
However, the query is compiled against the database pointer, so if you close your connection, you have to release all of your prepared statements. When you re-open your connection, you then have to re-prepare each statement as you use it again.
Save an object whenever you make a set of changes. If you are changing several things on an object (name, address, etc.) make all the changes first, then save it. Don't wait to commit several unrelated changes all at once, though (i.e. at the termination of the app). Related changes can be delayed until they are all made, before saving them.

Related

Why is sqflite retaining open database reference on hot reload

I have an app that checks for an sqflite db file in the app storage directory and if it is present, blows away the file and creates a new one and then opens it for the remainder of the app life. What I have noticed is that hot restart fails with sql exceptions because it still sees the database as open somewhere in memory even though all my references are blown away due to the restart. This seems like a bug because I have no way to control the closing of that database unless I try to make sure it is closed if the application is killed. Is this by design? Is there a standard way to approach it?
I noticed this related post
Your assumption and investigation are correct. With bad words, what happens during hot restart is that the dart environment is restarted while the native world is still running and for sqlite that means that open databases remain opened with no easy way to know that from the dart side.
The hot-restart hack in place in sqflite is meant mainly to handle hotrestart even if you are in a sqlite transaction. Without this hack, it should happen what you describe in your scenario. That is said deleteDatabase should be used instead of removing manually the file.
In theory, this should be handled in openDatabase and deleteDatabase.
Can you confirm that you are indeed using deleteDatabase? If yes, in the mean time your workaround is safe and reporting an issue on sqflite for investigation would be great. Thanks!
After further testing it looks like 1 way to handle this is to check for the existence of the file. If the file exists, go ahead and open it using sqflite's openDatabase method. Then immediately close it. Then delete the file using io file delete method. Then you can create a new database file using the openDatabase method. This solution is maybe a little more expensive than I had hoped but it is working.

No Internet Connection

I am a little confused on how to go about and do this....
On each page of my app i connect to PHP file to drag in data from my server. I have about 10 pages. Now if there is no connection to the internet then of course now data can be received.
Often the app crashes and we are putting this down to not having the data due to a change in connection or wifi whatever.
Now i have setup the reachability thing and that works, but i dont know how to link this in with the PHP calls. Should i check the reachability and if no connection then dont run the call. If so, what about all the variables, they will still be null and cause an error then?
I dont really know what is the best solution.
Hope you can help
Alex
Are the php calls just to receive data from a database without using a built in DB framework such as SQLite? If so, I went the same route to avoid the headache at first, but running SQLite in your app is a better solution overall, and reduces multiple dependencies (such as internet connection).
Now if the php calls that give you data back are receiving this information from yet another source and then feeding it into its own DB.....
Should i check the reachability and if no connection then dont run the call
Yes you should. This is done in multiple apps already. What variables would be null in this case? Pop the code that makes the call in an "if" block below this check, and only run it if true. Error handling other variables that might be null because the php call isn't setting them is up to you. You can do this is multiple ways.
You should certainly cache the data so the App doesn't HAVE to connect to the internet to display something, other than that I would make sure to use asynchronous requests and the timeout feature of NSURLRequest to control your attempts to request data in the background. If you don't get the data, just keep using what you have cached.

What's the proper way to use sqlite on the iPhone?

Can you please give some suggestions on sqlite using on the iPhone?
Within my application, I use a sqlite DB to store all local data. Two methods can be used to retrieve those data during running time.
1, Load all the data into memory at initialization stage. (More memory used, less DB open/close operation needed)
2, Read corresponding records when necessary, free the occupied memory after using. (Good habit for memory using, but much DB open/close operations needs).
I prefer to use method 2, but not sure whether too many DB opening/closing operations could affect app's efficiency. Or do you think I can 'upgrade' method 2 by opening DB when app launches and closing DB when app quits?
Thanks for your suggestions very much!
First of all: use FMDB to access SQLite!
Then, create your own singleton "MyDB" class.
Every time you need the database, you do [MyDB instance] to get your FMDB instance.
That way you only have one DB open (in didFinishLaunching) an you close it when your app exits.
That's far and away the best way to use SQLite on the iPhone.
The other option is to use CoreData, something I find great for when you start with an empty database, but FMDB/SQLite works best for me if I have a set of data that's read-only.
Apple seems to suggest that you avoid preloading all the data during the startup in order to ensure faster and smoother startup. Supposedly you should only load data when/if the user needs it.

Can I read from a SQLite db while writing to it on the iPhone?

Is it possible to read from a SQLite db while it's being written to?
I'm aware that access is blocked for writes when it's being written to, but is that the same for reads?
It's a little convoluted, but check out the File Locking and Concurrency documentation for SQLite. It sounds like if the db is in exclusive locked mode, that is the only time reads are not allowed. Besides unlocked, when the db is not even open.
I'm not 100% sure on it, but that's what I think it means.
After some reading around, and looking through the FMDB code, I discovered that I wasn't using the SQLITE_BUSY and SQLITE_LOCKED return values correctly.
According to the FMDB code, one should loop for a limited number of retries, waiting for a short time bewteen.
So I implemented that in my code, and everything seems to work fine.
Yes, although all the relevent multithreading issues need to be account for. I generally open multiple handles to the same DB file via sqlite3_open_v2().

iPhone Core Data application will terminate save database required?

I have an application that allows you to edit some percentages, however it will only let you commit those changes if the percentages add up to 100. However because the Core Data template includes the save code in the application will terminate. If the user changed something and then exited the application, the item would be of course saved even though it did not add to a 100%.
Therefore I simply decided to comment out the save in the application will terminate. I know the other option would be to use another context for the edit and then merge the changes or setting my context values until the actual save point. However I do not see any harm in commenting out this line, since I save whatever I want in my application when the user clicks the save button, so my question is: is the save on the application will terminate mandatory? what possible consequences could this have?. It is important to note that the application continues to work just fine after commenting this lines (which is what I expected).
Thank you in advance.
-Oscar
You can save whenever you like.
However, you will never know when the app will terminate. Unlike applications on more conventional platforms e.g desktops, the iPhoneOS will terminate your app (from the apps perspective) at random. The only warning you will get will be the applicationWillTerminate message sent to the app delegate. If you don't handle saves there then it is highly likely that at some point, your users will lose data.
I think you should reconsider your design. It sounds like you're putting calculation into the managedobjects that could (1) be handled elsewhere in code or (2) be handled by transient properties. You shouldn't have a condition in which the managedobject can't be saved at the drop of hat. Doing so makes your datamodel utterly dependent on external code for its internal integrity. This causes problem with maintenance, portability and upgrading.
Its not mandatory to save on application will terminate. You can save when ever you feel appropriate for the context of the app.