Let's take a look at iOS local persistent storage (focusing on the SQLite database)

Let's take a look at iOS local persistent storage (focusing on the SQLite database)

The company's project has been in existence for two years, and the version is about 3. However, the local persistent data storage has always used GVUserDefaults, a third-party library that extends NSUserDefaults. However, with the development of the business, more and more places need to be stored, and GVUserDefaults can no longer meet the needs. When we couldn't stand it anymore, after some discussion, we decided to use FMDB, a third-party library that encapsulates SQLite3. This article takes this as the main line and sorts out some knowledge about databases and local storage, but this article does not mention CoreData at all. Students who like to use CoreData, I would like to say sorry for wasting your precious 20 seconds of time.

The logic of this article is shown in the following figure:

Overview of iOS local persistent storage

Speaking of iOS local storage methods, everyone is probably familiar with them. NSUserDefault, File, Keychain, and DataBase are nothing more than these methods.

NSUserDefault, File: Both of these methods are very simple to use. One thing that needs to be noted is that the stored objects need to comply with and implement the two methods in the NSCoding protocol. The applicable scope is also some small-scale data. In fact, the underlying implementation of NSUserDefault is still stored in .plist files.
Keychain: used to store some private information, such as passwords, certificates, etc. The information stored in the Keychain will not be lost when the App is deleted and will remain valid after the user reinstalls the App. It is also applicable to data sharing between applications.
DataBase: When it comes to storage, we have to mention the DataBase technology. The DBMS used on mobile terminals is generally SQLite3. Under iOS, the API of SQLite3 is pure C language. So our friends who have been doing object-oriented development suddenly can't find the object, which is a bit panic. Fortunately, there are excellent third-party frameworks like FMDB in the open source community to help us find the object. Similarly, Apple has also released a new technology called CoreData (but CoreData is not the focus of this article). Databases are suitable for storing large-scale data, and it is more convenient to search than the above methods. Therefore, when storing a large amount of data, you still have to use the database, which is why we gave up GVUserDefaults.

Basic knowledge of database
database

First, there must be data Data, and then as the data increases, the name is upgraded to database DataBase. At this time, a management system is needed to manage the database, which is DataBaseManagerSystem. Finally, with the help of DataBaseAdministrator and the above names, it becomes a system, the so-called DataBaseSystem.

  1. Data --> DataBase --> DataBaseManagerSystem --> DataBaseSystem

Data: The basic object stored in the database.
DataBase: When it comes to database, everyone has a vague concept. Isn't it just a big warehouse for storing data? What else is there to say? In fact, this understanding is already very good, but to put it more professionally, a database is a collection of data stored in a certain organized way.
DataBaseManagerSystem: Database management system is a layer of data management software located between users and operating systems. Common DBMS include MySQL, PostgreSQL, Microsoft SQL Server, Oracle, Sybase, IBM DB2. Of course, these are all DBMS used for the server side. The DBMS used for the mobile side is SQLite3, which is also the focus of this article.
DataBaseSystem: After the introduction of database into the computer system, the system is generally composed of database, database management system, application system, and database management member (DBA). In general, the database system is called database, so sometimes we feel confused. You say DBS, he thinks DB, you switch to DB, he starts talking about DBS again. So when you really want to understand some knowledge thoroughly, the basic concepts must be clear, so that you will not be easily confused.

SQL Statements

SQL (Structured Query Language) is a language used to communicate with databases. Since you want to operate a database, you must be able to write SQL statements. Below I will briefly list a few simple SQL statements for reference. If you want to learn more about SQL statements, please refer to other materials. This article will not go into details here.

Here we take the student table as an example to write a few simple SQL statements

  1. // Create a table (table) a student table Table name: student
  2. Field id: student number, as primary key, type is integer
  3. Field name: student name, type is string, and cannot be empty
  4. Field age: student age, integer type, can be empty.
  5. The fields are also called columns.
  6. create table if not exists student (
  7. id integer primary key autoincrement,
  8. name text not null,
  9. age integer);
  10. // Delete the student table
  11. drop table if exists student;
  12. // Insert a record, the primary key id will be automatically assigned a value by itself, and the record is also called a row
  13. insert into student (name, age) values ​​('Xiao Ming', 20);
  14. // Delete the student named Xiaoming. The keyword where is the condition. If there is no such condition, the entire table will be affected.
  15. delete from student where name = 'Xiao Ming' ;
  16. // Update records that meet the criteria
  17. update student set age = 21 where name = 'Xiao Ming' ;
  18. // Query records that meet the conditions
  19. select * from student where name = 'Xiao Ming' ;

Use of database

If you don't use CoreData, whether you use the pure C language SQLite3 library or the encapsulated FMDB, you have to design a table structure that suits your business. There are two design patterns for table design.
Database table design
The first design method

Using each attribute in the model as a field in the table makes it easier to query and read data, but I personally feel that this mode is suitable for businesses with a small number of records. And try not to change the fields as much as possible. After creating a table, it is still troublesome to modify the table structure. For specific usage, please refer to the following code:

  1. @interface Student : NSObject
  2.  
  3. @property (nonatomic, copy) NSString *name;
  4. @property (nonatomic, assign) NSUInteger age;
  5.  
  6. @end    
  7.  
  8. //Path where data is stored  
  9. NSString *document = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
  10. NSString *dbpath = [document stringByAppendingPathComponent:@ "toyun.sqlite" ];
  11. // Link to database  
  12. self.db = [FMDatabase databaseWithPath:dbpath];
  13. // Open the database  
  14. if ([self.db open]) {
  15. [self.db executeUpdate:@ "create table if not exists student (id integer primary key autoincrement, name text not null, age integer not null)" ]; }
  16. //Instantiate the object, that is, the object to be stored  
  17. NSMutableArray *array = [NSMutableArray array];
  18. for (NSInteger i = 0 ; i < 10 ; i++) {
  19. Student *student = [[Student alloc] init];
  20. student.name = [NSString stringWithFormat:@ "Xiao Ming%ld" , i];
  21. student.age = arc4random() % 20 + 10 ;
  22. [array addObject:student];
  23. }
  24.  
  25. //Insert the database into the table  
  26. for (Student *student in array) {
  27. [self.db executeUpdateWithFormat:@ "insert into student (name, age) values ​​(%@, %ld)" , student.name, student.age]; }
  28. [self.db close];
  29. NSLog(@ "dbpath === %@" , dbpath);

The second design method

This design pattern is to use the model as a field and directly convert the model to NSData and store it in this field. It should be pointed out here that the model must implement the NSCoding protocol. However, in actual projects, we mostly use third-party libraries to convert dictionaries to models. The three more popular third-party libraries for converting dictionaries to models, Mantle, MJExtension, and YYModel, all handle this by default, so just pay a little attention here. The second method is more suitable for a large number of records, and the relevance to the business is not too sensitive. If there is a need for search and sorting, some attributes can be selected from the model as some fields attached to the table. For specific use, refer to the following code:

  1. @interface Student : NSObject <NSCoding>
  2. @property (nonatomic, copy) NSString *name;
  3. @property (nonatomic, assign) NSUInteger age;
  4. @end    
  5. @implementation Student
  6.  
  7. - ( void )encodeWithCoder:(NSCoder *)aCoder {
  8. [aCoder encodeObject:_name forKey:@ "name" ];
  9. [aCoder encodeInteger:_age forKey:@ "age" ];
  10. }
  11.  
  12. - (nullable instancetype)initWithCoder:(NSCoder *)aDecoder {
  13.     if (self = [ super init]) {
  14. _name = [aDecoder decodeObjectForKey:@ "name" ];
  15. _age = [aDecoder decodeIntegerForKey:@ "age" ];
  16. }
  17.     return self;
  18. }
  19. @end    
  20.  
  21. NSString *document =[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
  22. NSString *dbpath = [document stringByAppendingPathComponent:@ "yeemiao.sqlite" ];
  23. self.db = [FMDatabase databaseWithPath:dbpath];
  24.  
  25. if ([self.db open]) {
  26. [self.db executeUpdate:@ "create table if not exists student (id integer primary key autoincrement, model blob)" ]; }
  27.  
  28. NSMutableArray *array = [NSMutableArray array];
  29. for (NSInteger i = 0 ; i < 10 ; i++) {
  30. Student *student = [[Student alloc] init];
  31. student.name = [NSString stringWithFormat:@ "Xiao Ming%ld" , i];
  32. student.age = arc4random() % 20 + 10 ;
  33. [array addObject:student];
  34. }
  35.  
  36. // Convert to NSData and store in database  
  37. for (Student *student in array) {
  38. NSData *data = [NSKeyedArchiver archivedDataWithRootObject:student];
  39. [self.db executeUpdateWithFormat:@ "insert into student (model) values ​​(%@)" , data];
  40. }
  41. //Query data from the database  
  42. FMResultSet *set = [self.db executeQuery:@ "select * from student" ];
  43. NSMutableArray *resultArray = [NSMutableArray array];
  44. while (set.next) {
  45. NSData *data = [set objectForColumnName:@ "model" ];
  46. Student *student = [NSKeyedUnarchiver unarchiveObjectWithData:data];
  47. [resultArray addObject:student];
  48. }
  49. [self.db close];

Thread safety in database use

When operating a database in multiple threads, we must consider thread safety issues, otherwise data may be confused. There are many solutions. You can lock it yourself, but if the read and write speed requirements are high, it is not recommended to lock it. SQLite3 directly supports multi-threading. The SQLite3 library provides three methods: single thread, multi thread, and serialized. FMDB also provides the FMDatabaseQueue class for multi-threaded database operation, which is relatively simple to use.
Delete the cache

Most apps now have local storage, but not every app has a corresponding cache deletion function. At least our own app does not have this function. Caching is to save traffic, and deleting cache is to save space. I think these two functions are equally important, but this requirement has been raised several times, but the product does not pay much attention to it! Especially in the 16G version, this function can also improve some user experience.

This function is not difficult to implement. Just figure out the folders where the files are stored in various storage methods. Different data is obviously stored in different places. Then delete the corresponding data as needed. The specific directory of the sandbox is as follows:

  1. // Folder directory under the sandbox  
  2. Documents: iTunes will sync this folder and should not be deleted
  3. Library
  4. Caches: Cache folder, delete the main folder to delete when deleting cache
  5. Preferences: NSUserDefault is written to this folder, iTunes will synchronize it, and it should not be deleted
  6. tmp: A temporary folder created by the system that may be deleted at any time

When clearing the cache, you can delete all files in the Library/Caches folder, or you can delete a specified folder based on business needs.
Summarize

This article is more focused on the principles, and does not say too much about the specific uses. There are various specific uses, but the basic principles are relatively unified. As for database CURD, since we are not doing server-side development, we did not delve into it. If you want to study it, you can refer to other materials. In addition to the above, you may also need to consider database version migration, database synchronization and other requirements in specific use. Due to my limited level, I did not mention that you can refer to a reference blog post I wrote when I wrote this article, iOS Application Architecture Talks about Local Persistence Solutions and Dynamic Deployment. The usage of NSUserDefault and File is very simple and is not introduced. CoreData is too heavyweight, and I have never actually used it in my project, so it is not introduced here.

(Copyright belongs to the author. Please contact the author for authorization if you want to reprint this article. The author has authorized this article to be reprinted.)

<<:  Agile development is good, but don’t follow it blindly

>>:  iOS runtime practical application: member variables and properties

Recommend

Do brand marketing ads need conversions?

The dispute between brand advertising and perform...

3000 words revealing the secrets of advertising on Xiaohongshu!

When it comes to the most popular APP in 2019, Xi...

Will artificial starch advance the progress of human civilization?

After six years of exploration, the research team...

Activity case: How to conduct fission activities through product thinking?

In the second half of the Internet , the user div...

Brain development: the “infrastructure powerhouse” above our heads

Produced by: Science Popularization China Author:...

Tips for planning landing pages for information flow ads!

Landing page planning has always been a headache ...

The "traffic secret" behind Zhang's sudden popularity

The fact that "Teacher Zhang"'s con...

Do you really know how to set promotion goals for your APP?

Nowadays, many newcomers who are engaged in app p...

Review of the 2017 Double 11 event operation routines, have you been fooled?

In 2017, the transaction volume on Double 11 reac...

Cross-border marketing creative advertising case!

What is cross-border marketing ? As American adve...