FMDB block my UI - ios

Fmdb in iOS, I have a task to convert 100 JSON string to my model from network and then represent them on the UITableViewCell, because I have 3 button to change the data on the UITableView , so I fmdb the data to local, when I change the data it first check to read the local data, and then request newest data to reload UITableView and save to database. All 3 changes have the same logic. Because 100 data to store I choose to asynchronous dispatch the for statement, then the problem is when the model inserts in to table it stuck my UI a little bit. My table has 10+ columns , is there any possibility just because too much columns cause insert assume too much time?

According to FMDB documentation, it's better to use FMDatabaseQueue for your case.
To perform queries and updates on multiple threads, you’ll want to use FMDatabaseQueue.
Using a single instance of FMDatabase from multiple threads at once is a bad idea. It has always been OK to make a FMDatabase object per thread. Just don’t share a single instance across threads, and definitely not across multiple threads at the same time.
Instead, use FMDatabaseQueue.
Here's the reference.

Related

Is it acceptable to load Realm objects in the main ui thread?

we are adopting (Swift)Realm as a data store in our iOS app and we are really pleased with it so far. We have a question around the design for the retrieval and storage of objects with Realm and multi-threading:
Is it acceptable to load objects in the main ui thread?
We know about the constraints that objects loaded with realm cannot be shared between threads.
We are also not seeing any performance issues yet, but our approach so far is to load all kinds of resources in background threads.
In the case where we load and filter some data and register a notification block, we don't see problems with using the main ui thread, but how would we handle a situation, where we for example want to display all data in a table view?
Is it acceptable to load objects in the main ui thread?
Yes, it is in most cases* acceptable and fast enough. It wouldn't be acceptable if reading from the database would block the user, but as there is no concept like faults, read access is always predictable fast.
Only if you have a really complex object graph, where you need to do heavy pre-processing to be able to display the objects on the UI, it would make sense to employ a background thread and/or caching to warrant a good user experience.
In the case where we load and filter some data and register a notification block, we don't see problems with using the main ui thread, but how would we handle a situation, where we for example want to display all data in a table view?
A UITableView only request those cells which are currently visible on the screen and reuses the view containers. A Realm collection is similar in this lazy nature, when you don't filter it, it doesn't enlarge the memory pressure, because you get only object accessors for those objects which you pull out of it. There is no need for pagination as long as you rely on the builtin Realm Results or List collections. Only if you need to apply a custom and complex filter in a way which isn't supported by Realm, it might be necessary to process that on a background thread.

sqlite issue in iOS accessing two table at same time

I hope all doing well, I have one query regarding the sqlite .
Is that possible that two different sqlite table access at ones .
ex.
I have table A ans B .Can access A and B at same time .insert updating table value .
I have two different table,Table1 and table2 in myDatabase( test_db.sqlite).
Table 1 is only access by main thread.
Table 2 will be only access by background thread.
Now let c.
I have open the database connection using background thread…for inserting the value into table2.
while inserting the value into table2………….my main thread tries to open the same database connection at the same time to retrieve the data from table 1……and the app crash.
how to open the same database connection concurrently.
please check this edit one
[EDIT]
You are getting problems by accessing the Database in different threads. You can deal with this problem by using thread safe mode.
From SQL docs:
SQLite support three different threading modes:
Single-thread. In this mode, all mutexes are disabled and SQLite is unsafe to use in more than a single thread at once.
Multi-thread. In this mode, SQLite can be safely used by multiple threads provided that no single database connection is used simultaneously in two or more threads.
Serialized. In serialized mode, SQLite can be safely used by multiple threads with no restriction.
So, you can use the SQLITE_THREADSAFE compile-time parameter to select the threading mode.
I suggest that you open a different DB connection in each thread, or rebuild SQLite in serialised mode (with SQLITE_THREADSAFE=1).
OLD Answer:
It's difficult to answer your problem if you do not provide the exact error you are receiving. But, making the assumption that your queries are ok, the most probable cause is that you are not handling your sqlite flow correctly.
I suppose that your problem is that you are updating table "A" and then when trying to update table "B" it crashes. That's why you are trying to create a single query to update both of them.
So, before reusing your sqlite3_stmt to make the second query, you should, first, call sqlite3_finalize(yourStatement) to release the statement from memory, and then, if you want to make the second query just call sqlite3_prepare_v2 again, so the database is ready to accept the next query after that.

Incremental Saving

I have an app with a lot of data (including NSMutableArrays, NSNumbers, various custom classes) that uses NSCoding protocol presently. However, I would like to implement an incremental saving system, to save time during the "saving process". The loading time is not important.
Is there any existing container that checks its members for "dirty" and only updates those values when writing to file; or better yet, a protocol that can be implemented to do the same; or any other simple, available way of doing this?
For large amount of data its better to change data model to Core Data. Otherwise, you may want to save changes after specific events, or, bad solution is to use NSTimer, to save all data every time you want to.

How to load a table downloaded from the web into core data in iOS?

How do I load a table downloaded from the web and put it into core-data?
If I have a CSV file (could be SQLite) of about 2000 rows, that's been updated, and put onto the web like Amazon Web Service, how can that be loaded into core-data while the user is using the app? I would like to completely replace the previous file, and reload the table. I imagine I save it to the documents directory, but then how to load it into core-data and it load quickly so the user does not have to wait too long?
I won't know what data the user needs, what was added or deleted since the last time it was used, so I can't make a query for just the changes. The table is made up of text, integers, and geocodes, that I will update twice a month.
Can core-data read from an external file to populate a tableView, or must it read only from what's inside itself? I don't absolutely need a relationship between tables, so if that gets in the way, I could remove it. There may or may not be a second table loaded. Would it be better to use SQLite table instead? I've not done this part of core data before. What are best practices? Code samples would be helpful.
I assume you are well versed in using Core Data and you are deploying to iOS 5 and higher. I also assume you understand the CSV format very well. Then this would be a design to start out with:
Create a parser object. This object is responsible for understanding the csv-file (this is logic that you need to write yourself, there is no native csv-parser clas). You give this object the NSString, or local URL to the file and read it line by line. Let's say every row contains the data for one Core Data entity: this parser then extracts the values from the string's first line and creates/updates an existing Core Data entity. See this link for an efficient way of updating/creating Core Data entities.
Make sure all this parsing is done on a backgroundThread, with an NSManagedObjectContext that has a private queue type.
Create a UITableViewController that utilizes an NSFetchedResultsController that you initialize with an NSManagedObjectContext that is the parent of the NSManagedObejctContext used in the parser-object. Make sure you give it the main queue concurrencytype on initialization. This way, every time the parser creates/updates an entity, it will save this up to the parent context. This context in turn notifies the NSFetchedResutsController and you can update your UI for each updated/created entity separately through the NSFetchedResultsController delegate methods, showing changes to the user as fast as you can.
Make sure some overseeing object (might be a Data-manager, or maybe a networking class, or maybe event the viewController, although I would go for a Data-manager) gets told that the complete parsing process is over, so that the managedObject in the UITableViewController can be saved (which will actually persist the data).

Fetch related Core Data objects in background? (to prevent UI freeze)

I am currently using a method where I run a fetch request in the background to obtain object IDs, and then instantiating them with -existingObjectWithID:error:.
The problem is that these objects have to-many relation to a large number of objects. And the UI freezes for a while when these objects are accessed. (They are accessed all at once.)
I am guessing that the related objects are faults. I am trying to figure out a way to preload them in the background. Is there a solution to this problem?
Do you know for sure that it is your main thread that is causing the slowdown (sure sounds like it) - I'd use Instruments and "Time Profiler" to be sure, and there is also a way to turn on SQL debugging/timing too.
If it is your main thread, there are fantastic WWDC videos (take a look at 2010 too, not just 2011) on how to optimize Core Data.
Try the setRelationshipKeyPathsForPrefetching: method on NSFetchRequest. Pass in an array of keys that represent relationships that should be fetched rather than faulted.
Core data is not thread safe. So for background thread you should have separate managed context.
Typically core data don't take lots time to load. But if you are storing blobs (like image data) it can hit the performance. You should you NSFetchRequestController with page size you want to set. It much faster So you probably wont need to worry about about background fetching

Resources