This question already has answers here:
iOS Make sure documents are open before accessing
(2 answers)
Closed 8 years ago.
My app depends on the UIManagedDocuments being open. Therefore I basically don't want the user to do anything unless the documents are open. The problem is that opening closed documents is asynchronous. What is the best way to go about this to make sure the user does not enter data to be saved before the UIManagedDocuments are open? I can think of two possible solutions:
1) Should I just wrap every call accessing the UIManagedDocuments in a check to see if it is open and run the code on the completion handler of opening a closed document? This way doesn't seem ideal because the user may do something and expect the results to be saved but it won't be saved yet.
2) The other approach I thought of is to stall the app somehow to wait for documents to open. But I read somewhere that it is bad to block the main thread to wait for the document to open. Can I somehow make the main thread do the opening itself? Or is that bad too?
Another question I have is, if I open all the documents upon loading my app (initial launch), will they stay open until the app is terminated? Or can the documents close at any time for undetermined reasons?
In short, you need to redesign your UI and/or stop using UIManagedDocument. Your Application Launch should be designed so that it can wait for the Core Data stack to be initialized. If you are not doing that now you need to redesign the launch of your application.
Further, UIManagedDocument should not be used as your primary Core Data stack. UIManagedDocument should only be used when you are building a document based application. If you build a proper Core Data stack yourself you will eliminate the need for the asynchronous start up.
However you still want to disconnect your app launch from the data display because of migrations, iCloud integration, etc. All of which can take human perceivable amounts of time and you don't want them blocking the UI.
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
In my application I update the user data when the user logs out or closes the application.
The problem is that when he closes the application, the OS stops all the processes of the application, so I can't do my writing on Firebase.
What I want to do instead is save this data locally on the device and when the user logs back in, do the update.
I was going to save them via User Defaults but I thought that if the user had a jaibreak phone, they could theoretically access that memory area and therefore change values.
Am I getting the wrong idea?
Thanks :)
You are right, normally the sandbox of your app is protected but a super-user can access to it and read data. In this case, one solution is to prevent app-launching on rooted or jailbroken phone. There are some libs like this one to detect jailbroken phone. Some times it better to stop the app and launch a pop-up explaining why the app can't run on this phone because of cybersec rule.
But doing that keep in mind you will lost some users.
To your primary issue, writing data when the user leaves the app, this has several well-supported solutions. This is a canonical example of what beginBackgroundTask(expirationHandler:) is for. Whenever you begin a Firebase update, call beginBackgroundTask, and whenever you finish the update, call endBackgroundTask. That will tell the OS that you're currently performing an action that could benefit from a little more time before being terminated. You should expect something on the order of 30 seconds to a minute. (It used to be more like 3 minutes, but it's been tightened in newer OS versions.) That should be plenty of time for most updates.
If you are using URLSession directly, you can also make use of background tasks. See Downloading Files in the Background for details. This can be used to send data, not just transfer files. It has the major advantage of queuing operations when currently offline, and the OS will perform the transfer when possible, even if your app is no longer running. That said, this is all more complex to implement, and likely overkill for this kind of problem.
That said, if you're storing the access token anywhere in your program (including in memory), a user who reverse engineers your app can always connect to Firebase directly and send anything they want. Whether you store it in UserDefaults, in a file, or just in memory doesn't really change that. Also, last I checked, Firebase doesn't support certificate pinning if you're using their SDK, so a user can just rewrite your packets using a proxy anyway without even jailbreaking the phone.
I think that would be better to store user's data in cloud.
This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
How to setup alternate entry point in Blackberry application?
I have made a blackberry application which need to run automatically after phone reboot (by pulling battery), when i pull the battery from phone and insert it again then i check from log file which I created on phone memory. By observing the log I found my Application's main method does not call after restarting.What can be the reason?
i think this question does not make any sense. After diagnosing we found that every thing was working fine, but the only problem was that, after restarting (by pulling battery) it takes some time to initialize memory card, and my db and log file is stored on memory card. After detection of problem i shifted my log file to phone memory and i found every thing was OK. Now i put some delay on the stating of application, every thing is working fine as required.
Since I've started developing my Blackberry app, the biggest problems I've encountered all had to do with SQLite Databases.
Right now I'm putting my app through a stress test, and when problems pop up I address them by printing out statuses to the console and taking care of things line by line. Right now (after mashing buttons on my app) I received a "Database is locked" error and I'm not sure what to do.
It seems that once the database is locked it's locked for good until it is unlocked........ my question is how can I unlock it?? First of all, how can I check to see if it's locked??
I'm sure our users won't be mashing buttons like I did, but you never know. I want to account for every possible scenario.
Thanks
EDIT: This is what happens in my application..... When I launch it starts a thread, this thread performs a cleanup on one of my tables based on how old certain pieces of data are (uses DELETE). The thread then continues to get a USER object from my DB (read only), it then uses this USER object as a parameter to call a web service. The data retrieved from the web service is INSERTED into my database. (It's a little more complex than that as a few read/write operations are performed at this time. After that, the thread fires a callback method to update my UI.
This all works fine. I can exit the app WHILE the thread is running and relaunch and a flag will prevent it from starting a new instance of the same thread (unless the other one is done of course).
Now my problem: My app's home screen is a list of buttons, when the user clicks one of these buttons another, more detailed list is loaded (this requires a READ ONLY call to the database). When I launch the app (firing the web service calling thread) and then click a button on the main screen right away, the table gets locked. (Not always, sometimes it takes 4 or 5 tries, sometimes more, sometimes less). But if I keep doing this it WILL eventually lock making it impossible to make any calls to my DB, hence no more UI (which depends on the DB).
The DB call that populates the UI on the second screen is READ ONLY, can't I have as many of these as I need?? What causes the DB to lock?? What's the difference between a DB lock and File System error (12)??
I seemed to have fixed the problem. I was under the impression that if a read/write connection was open then a read-only connection could be created safely.
This doesn't seem to be the case. If I have a read/write connection open then no other connections can open until that one is finished.
I basically created one read/write connection, set a flag to identify it as open, and during my read connection use the same Database object if the flag is open, or create a read only if it's closed.
So far so good.
Sqlite does not support concurrent modification. In practice on BlackBerry, this means you can only open the database from one part of the code at a time. To maintain this one-at-a-time access, you need to close the database when you are done with it, as #AnkitRox points out.
However you also need to guard against concurrent access. Even if your code properly closes the database, it is possible for two different threads to access the database. In that case, you will need one to wait. In Java-ME this is typically accomplished through the 'synchronized' keyword, and using the same lock object for all database access.
Check properly that, you are opening and closing database before and after execution of query respectively.
Because if Database is going to open without closing it properly, then it gives errors.
This question io3->ios4 upgrade said to support applicationWillResignActive. While implementing this call, I also implemented applicationDidEnterBackground and applicationWillEnterForeground. However, I found that my app would crash. After some debugging on the simulator I determined that I needed to reinitialize a key data structure in applicationWillEnterForeground. So my question is how would I have known that from reading the documentation? (In fact, I may be doing the wrong thing and just so happened to get it working again.) Is there an exact description of what to do when these methods are called?
Thanks.
The only things you should do when supporting multitasking, is saving the state of your app when it enters the background, and reload it when it becomes active. (If you generate a new template in Xcode, you'll see this.)
Saving state means writing any user preferences or data to disk. Reloading the state involves reading saved preferences and data, recreating any in memory data structures that might need it (like in your example you gave).
In most circumstances, there's little else you need to do. The only thing that would crash your app that is unique to multitasking would be trying to run code in the background for longer than the allotted amount of time, (which is 10 minutes.) Otherwise, it sounds like you have got other problems with your code.
I've been reading up on SQLite3 included in the iOS firmware which might serve my needs for the app i'm writiung.
What I can't figure out is if it is persistent or goes away like some objects do.
For example if I do sqlite3_open() which appears to be a C function rather than an Objective-C object, if I open this at the start of my application, will it stay persistent until I close it no matter how many views I push/pop all over the place.
Obviously that would depend on where I put it but if I was doing a universal app and had some central functions for loading / saving data which were common to both iPhone/iPad, if, in my didFinishLoading: I put a call to open the SQLite database and then called various exec's of queries, would it remain persistent throughout the lifecycle of the application.
or
Am I better off opening and closing as needed, i'm coming from a PHP background so i'd normally open a database at the start of the script and then run many queries and then finally close it before browser output.
From the 1,000,000th i've learned over the last few months about iOS programming, I think the latter might be the better way as there's possibility of app exit prematurely or it going to background.
I'd just like a second opinion on my thinking please.
I dont know directly, but I think you are right - you only need to open it once at the start of your app.
Looking at sqlitepersistentobjects, an ORM framework for iOS, it only opens the DB when its first used, and never closes it except when there is a problem opening it :)
Single opened sqlite database used throughout the app from different places in your app is fine.
You are using word "persistent" which is confusing. What you mean is "reuse of single connection, for executing different statements in the app, possibly from different threads". Persistence has completely different meaning in context of databases - it means that the requested modification of data has been safely stored to media (disk, flash drive) and the device can even unexpectedly shut down without affecting written data.
It's recommended to keep running sqlite statements from a single, dedicated thread.
It's not recommended to connect to sqlite database from different processes for and executing parallel modifications.
A good alternative solution is to use sqlite async extension which sends all writes to a dedicated, background thread.
You can check out https://github.com/mirek/CoreSQLite3 framework if you want to use custom built (newer version) of sqlite.