Creating iOS application with Vertabelo Mobile ORM

1. Introduction

This tutorial will walk you through the process of creating an iOS application using Vertabelo Mobile ORM. Our goal is to develop a very simple, single view application using database. It's going to be a 'collection' of people, where you can add, update or delete a person.

2. Modeling database in Vertabelo

To make the application work, we need a database. But before we create a database, we need to know how it should look like.

Go to Vertabelo and having signed in, click Create New Model.

Set the name for the model, choose SQLite 3.7.x. as database engine and empty as initial model. Then, click Start modelling.

For the application, we need only one table in the database, so let's add it.

Now, we've got a default, empty table in the diagram.

Let's rename it to person and add columns with types. Tick id column to be primary key (PK). Primary key indicate that this value is unique for every record.

Now, our simple database model is ready for the next steps!

3. Generating SQL script

As we've already got a database model, we're ready to generate SQL create script and add it to our project. To generate SQL script, we can use Vertabelo again. Before the generation, we can add some test data as an additional SQL script. Go to Model Properties and find End of the create script in Additional SQL scripts section.

Enter, for example, below statements into End of the create script as our test data.

INSERT INTO person VALUES (1, 'Jim', 'Smith');
INSERT INTO person VALUES (2, 'Mary', 'Simpson');
INSERT INTO person VALUES (3, 'Adam', 'Johnson');
            

Now, we're ready to go. Click Generate SQL script and download generated file.

4. Generating O/R mapping

You can generate O/R mapping for your project in two ways.

4.1. Generating O/R mapping using Vertabelo

Open your database model in Vertabelo and click ORM icon. Choose Objective-C platform and click Generate.

Download generated archive - it will contain all files you need to use Vertabelo Mobile ORM.

4.2. Generating O/R mapping using RubyGems

RubyGems is a package manager for Ruby. We made an executable gem for Vertabelo Mobile ORM, which allows you to generate O/R mapping for your project. You can find it here. Using it, ORM generation may be done in two ways.

4.2.1. From .xml file

Download your model as Vertabelo XML file.

Then, open terminal and enter

mobiorm mode=xml output=DESTINATION_DIRECTORY file=XML_FILE_PATH
                

4.2.2. Using Vertabelo API

Sign in to Vertabelo and open My account page.

Enable API access.

Copy and store somewhere your API Token.

Then, go to dashboard.

Go to model's Details page.

Again, copy and store somewhere model's identifier.

Now, open terminal and enter:

mobiorm mode=vertabelo output=DESTINATION_DIRECTORY token=API_TOKEN model=MODEL_IDENTIFIER
                

5. Setting up an XCode project

Open XCode and create a new project. Choose Single View Application.

At the beginning, we have to add an sqlite3 library to our project. Go to project settings by clicking on project name.

Choose Mobi ORM Tutorial target.

Go to Build Phases section.

Click '+' in Link Binary with Libraries.

Choose libsqlite3.0.dylib and click add.

The library has been added to the project, so our project is ready for the next steps.

6. Adding generated files into the project

Firstly, let's add a previously downloaded SQL create script. Click File and Add Files to Mobi ORM Tutorial.

Choose Mobi_ORM_Tutorial_create.sql file and click Add.

Now, let's take care of files generated by Vertabelo Mobile ORM.

MOAExpNegation.h MOColumn.m MOLExpBoth.m MOSQLiteDataSource.h MORowHandlerForData.m
MOUpdateQuery.h PersonRowHandler.m MOAExpNegation.m MODbType.h MOLExpLeft.h
MORowHandlerForDate.h MOSQLiteManager.h MOUpdateQuery.m MOAExpOperator.h MODeleteQuery.h
MOLExpLeft.m MORowHandlerForDate.m MOSQLiteManager.m MOValue.h MOAExpOperator.m
MODeleteQuery.m MOLExpParentheses.h MORowHandlerForNumber.h MOSQLiteOpenHelper.h MOValue.m
MOAExpParentheses.h MOExpression.h MOLExpParentheses.m MORowHandlerForNumber.m MOSQLiteOpenHelper.m
MOWhereQuery.h MOAExpParentheses.m MOExpressionConstants.h MOLExpRight.h MORowHandlerForObject.h
MOSelectQuery.h MOWhereQuery.m MOAExp.m MOAExpValue.h MOInsertQuery.h
MOLExpRight.m MORowHandlerForObject.m MOSelectQuery.m Person.h MOAExpFunction.h
MOAExpValue.m MOInsertQuery.m MOOrderBy.h MORowHandlerForString.h MOSubselect.h
Person.m MOAExpFunction.m MOAsterisk.h MOLExp.h MOOrderBy.m
MORowHandlerForString.m MOSubselect.m PersonDAO.h MOAExpList.h MOAsterisk.m
MOLExp.m MORowHandler.h MORowHandlerRawData.h MOTableExpression.h PersonDAO.m
MOAExpList.m MOColumn.h MOLExpBoth.h MORowHandlerForData.h MORowHandlerRawData.m
MOTableExpression.m PersonRowHandler.h

Well, that's a lot of files, but those with prefix MO are classes used for query building - DAO classes are using them in their implementation, but they may be as well used to create your own queries. To learn more check Query Language Guide.

From the above files, your database model is represented by these ones:

Person.h Person.m PersonDAO.h PersonDAO.m PersonRowHandler.h PersonRowHandler.m
            
  • Person - it's just the objective representation of a database table.
  • PersonDAO (Data Access Object) - class used to perform operations on database, to learn more about them check DAO Guide.
  • PersonRowHandler - class used under the hood by PersonDAO to convert rows from database to objects

Add all files to your XCode project. The amount of them may make a little mess, but you can organize them using groups. For example, move all files with prefix MO to Query Language group. Select and right-click on them, then choose New Group from Selection.

Now, it looks definitely better.

7. Designing an application

In this section, we're going to design a UI for our application using Storyboard.

Go to Main.storyboard file and add two Text fields.

Now it's time for labels. Place them on the left side above the fields and change them to First name and Last name

Add 4 button and name them Next, Delete, Update and Insert respectively.

8. Connecting application to database

At first, we have to create a class, which conforms to MOSQLiteDataSource protocol. We will use provided MOSQLiteOpenHelper class. We need to create a new class inheriting from MOSQLiteOpenHelper. Right-click on Query Language directory and click New File...

Choose Cocoa Touch Class

Name the new class, for example, DatabaseHelper and make it a subclass of MOSQLiteOpenHelper.

Now, we have to implement configure method in DatabaseHelper class. We will add Mobi_ORM_Tutorial_create.sql script and set database version to be 1.

@implementation DatabaseHelper

- (void)configure {
    [self addCreateScript:@"Mobi_ORM_Tutorial_create.sql"]
    [self setDbVersion:1];
}

@end
            

Finally, we're ready to make use of Vertabelo Mobile ORM!

9. Vertabelo Mobile ORM in action

Open Main.storyboard and go to Assistant editor.

Select with Ctrl First name text field and place the arrow on interface inside ViewController.m.

Set name to firstName and click Connect. Do the same with Last name text field.

Now, select with Ctrl Next button and also place an arrow on interface. Set connection to Action and name it next. Repeat that for three remaining buttons.

You should get something like the below.

@interface ViewController ()

@property (weak, nonatomic) IBOutlet UITextField *firstName;
@property (weak, nonatomic) IBOutlet UITextField *lastName;

- (IBAction)next:(id)sender;
- (IBAction)delete:(id)sender;
- (IBAction)update:(id)sender;
- (IBAction)insert:(id)sender;
@end
            

Go to ViewController.m and import PersonDAO.h.

#import "PersonDAO.h"
            

Add PersonDAO property to the class. We will use it to communicate with database.

@property PersonDAO *dao;
            

Now, we need to initialize dao property in viewDidLoad method. To initialize DAO object, we need a data source, which we have already created - DatabaseHelper. Don't forget to import it!

@implementation ViewController

- (void)viewDidLoad {
 [super viewDidLoad];
 DatabaseHelper *helper = [[DatabaseHelper alloc] initWithDbName:@"database.sqlite"];
 self.dao = [PersonDAO daoWithDataSource:helper];
}

- (void)didReceiveMemoryWarning {
 [super didReceiveMemoryWarning];
 // Dispose of any resources that can be recreated.
}

@end
            

Next step is to display first records from database after loading a view. We need two additional properties: array for objects representing persons and index to iterate through the objects.

@interface ViewController ()

@property PersonDAO *dao;
@property NSArray *people;
@property NSInteger index;

@property (weak, nonatomic) IBOutlet UITextField *firstName;
@property (weak, nonatomic) IBOutlet UITextField *lastName;

- (IBAction)next:(id)sender;
- (IBAction)delete:(id)sender;
- (IBAction)update:(id)sender;
- (IBAction)insert:(id)sender;
@end
            

Let's initialize index to 0 and get the array of all people in the database.

- (void)viewDidLoad {
 [super viewDidLoad];
 DatabaseHelper *helper = [[DatabaseHelper alloc] initWithDbName:@"database.sqlite"];
 self.dao = [PersonDAO daoWithDataSource:helper];
 self.index = 0;
 self.people = [self.dao getPersonArray];
}
            

DAO method getPersonArray returns an array containing all records from the table, but as Person objects. Now, we want to display the first record's first name and last name. We need to implement a method called printPerson. But at first, add it declaration to the interface.

- (void)printPerson;
            

Method will use current index and print first and last name of the person with that index.

- (void)printPerson {
 Person *person = self.people[self.index];
 self.firstName.text = person.columnFirstName;
 self.lastName.text = person.columnLastName;
}
            

Now, invoke this method in viewDidLoad.

- (void)viewDidLoad {
 [super viewDidLoad];
 DatabaseHelper *helper = [[DatabaseHelper alloc] initWithDbName:@"database.sqlite"];
 self.dao = [PersonDAO daoWithDataSource:helper];
 self.index = 0;
 self.people = [self.dao getPersonArray];
 [self printPerson];
}
            

Run the application and check if the previously added Jim Smith will be displayed.

It works! Now it's time to make Next button usable. What next method is going to do is just increasing the index and displaying the new person. The corner case is the situation when we're displaying the last person from database - then, we should go to the person with index zero.

- (IBAction)next:(id)sender {
 if (self.index + 1 >= [self.people count]) {
 self.index = 0;
 } else {
 self.index++;
 }
 [self printPerson];
}
            

Run the application and check whether new people are displaying and loop is working correctly.

Now, we will implement insert method. Inserting in our application will add to the database anything that is already written to the text fields. If you don't change anything, duplicate will be added. Before we do it, we need a very simple method to reload the array of person to the application.

- (void)reload {
 self.people = [self.dao getPersonArray];
}
            

Now, we're ready to implement insert.

- (IBAction)insert:(id)sender {
 Person *person = [Person person];
 person.columnFirstName = self.firstName.text;
 person.columnLastName = self.lastName.text;
 [self.dao insertPerson:person];
 [self reload];
 [self printPerson];
}
            

At the end, we are printing to the screen the person from current index just to indicate to the user that the insert did happenned.

Method updatewill modify the person at current index. To use it, just find the person you want to update using next, then make changes in text field and click update.

- (IBAction)update:(id)sender {
 Person *person = self.people[self.index];
 person.columnFirstName = self.firstName.text;
 person.columnLastName = self.lastName.text;
 [self.dao updatePerson:person];
 [self reload];
 [self next:self];
}
            

Invocation of method next is again just to indicate to the user that the update happened.

The last feature to implement is delete method, which will delete a person with current index from database.

- (IBAction)delete:(id)sender {
 Person *person = self.people[self.index];
 [self.dao deletePerson:person];
 [self reload];
 [self next:self];
}
            

Now, run the application and check if all the features work. Our application is finished!

10. Summary

Have you noticed how painless working with SQLite using Vertabelo Mobile ORM is? You don't have to worry almost about anything - no SQLite functions in C, no strings with queries, no bothering about SQL Injection - just invoking methods in one line, what's more you're guaranteed that they're working correctly. With Vertabelo Mobile ORM you no longer have to work with databases - now, databases are finally working for you! To learn more about Vertabelo Mobile ORM check DAO Guide and Query Language Guide.