Today we have just released the first trial version of our Action Data suite for Swift and Xcode. Action Data is a suite of backend controls designed to quickly and easily add support for several common databases and data formats (such as SQLite, JSON, XML and CloudKit) to your iOS, tvOS or macOS apps.

Action Data provides both light weight, low-level access to the data sources along with high level Object Relationship Management (ORM) support using Swift 4’s new Codable, Encodable and Decodable protocols and our custom Encoders and Decoders to move data between the data source and your custom data models with minimal code.

Using our Action Data Providers you can either manipulate data directly using SQL (even on data sources that do not typically provide SQL support) or create a Swift Class or Structconforming to the ADDataTable protocol and have the Data Provider handle all of the heavy lifting for you.

Additionally, we expose our Action SQL Parser to you to provide support for your own custom data sources. The ADSQLParser provides the ability to parse text containing one or more SQL commands into an Action Data SQL Document Object Model (DOM) that can easily be executed against a data source.

What’s Included

Action Data adds the following functionality:

  • Action Codable – Uses Swift 4’s new Codable, Encodable and Decodableprotocols to move information between your data models and our portable ADRecordand ADRecordSet formats.
    • Swift Portable Object Notation – The new Swift Portable Object Notation (SPON) data format that allows complex data models to be encoded in a portable text string that encodes not only property keys and data, but also includes type information about the encoded data.
  • Action Data Providers – Provides light weight, low-level access and high-level Object Relationship Management (ORM) support to several common databases and data formats such as SQLite, JSON, XML, SPON and CloudKit.
  • Action SQL Parser – Provides the ability to parse text containing one or more SQL commands into an Action Data SQL Document Object Model (DOM) and is used to provide SQL support for data sources that don’t support SQL natively (such as CloudKit and JSON).

Action Codable

Action Codable controls provide support for several common databases and data formats such as SQLite, JSON, XML and CloudKit using Swift 4’s new Codable, Encodable and Decodable protocols to move information between your data models and our portable ADRecord and ADRecordSet formats.

With Action Codable and Action Data Providers, build your data model objects as simple struct or class objects and inherit from ADDataTable, then use Action Controlsto quickly create, insert, update, delete and maintain the tables and records in the underlying data source. For example:

<span class="token keyword">import</span> <span class="token builtin">Foundation</span>
<span class="token keyword">import</span> <span class="token builtin">ActionUtilities</span>
<span class="token keyword">import</span> <span class="token builtin">ActionData</span>

<span class="token keyword">class</span> <span class="token class-name">Category</span><span class="token punctuation">:</span> <span class="token builtin">ADDataTable</span> <span class="token punctuation">{</span>
    
    <span class="token keyword">enum</span> <span class="token builtin">CategoryType</span><span class="token punctuation">:</span> <span class="token builtin">String</span><span class="token punctuation">,</span> <span class="token builtin">Codable</span> <span class="token punctuation">{</span>
        <span class="token keyword">case</span> local
        <span class="token keyword">case</span> web
    <span class="token punctuation">}</span>
    
    <span class="token keyword">static</span> <span class="token keyword">var</span> tableName <span class="token operator">=</span> <span class="token string">"Categories"</span>
    <span class="token keyword">static</span> <span class="token keyword">var</span> primaryKey <span class="token operator">=</span> <span class="token string">"id"</span>
    <span class="token keyword">static</span> <span class="token keyword">var</span> primaryKeyType<span class="token punctuation">:</span> <span class="token builtin">ADDataTableKeyType</span> <span class="token operator">=</span> <span class="token punctuation">.</span>computedInt
    
    <span class="token keyword">var</span> id <span class="token operator">=</span> <span class="token number">0</span>
    <span class="token keyword">var</span> added <span class="token operator">=</span> <span class="token function">Date</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token keyword">var</span> name <span class="token operator">=</span> <span class="token string">""</span>
    <span class="token keyword">var</span> description <span class="token operator">=</span> <span class="token string">""</span>
    <span class="token keyword">var</span> enabled <span class="token operator">=</span> <span class="token boolean">true</span>
    <span class="token keyword">var</span> highlightColor <span class="token operator">=</span> <span class="token builtin">UIColor</span><span class="token punctuation">.</span>white<span class="token punctuation">.</span><span class="token function">toHex</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token keyword">var</span> type<span class="token punctuation">:</span> <span class="token builtin">CategoryType</span> <span class="token operator">=</span> <span class="token punctuation">.</span>local
    <span class="token keyword">var</span> icon<span class="token punctuation">:</span> <span class="token builtin">Data</span> <span class="token operator">=</span> <span class="token function">UIImage</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toData</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    
    <span class="token keyword">required</span> <span class="token keyword">init</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

This includes support for complex tables with nested objects, arrays and dictionaries and complex relationships such as one-to-one, one-to-many and many-to-many. For example:

<span class="token keyword">import</span> <span class="token builtin">Foundation</span>
<span class="token keyword">import</span> <span class="token builtin">ActionUtilities</span>
<span class="token keyword">import</span> <span class="token builtin">ActionData</span>

<span class="token keyword">struct</span> <span class="token builtin">Address</span><span class="token punctuation">:</span> <span class="token builtin">Codable</span> <span class="token punctuation">{</span>
    <span class="token keyword">var</span> addr1 <span class="token operator">=</span> <span class="token string">""</span>
    <span class="token keyword">var</span> addr2 <span class="token operator">=</span> <span class="token string">""</span>
    <span class="token keyword">var</span> city <span class="token operator">=</span> <span class="token string">""</span>
    <span class="token keyword">var</span> state <span class="token operator">=</span> <span class="token string">""</span>
    <span class="token keyword">var</span> zip <span class="token operator">=</span> <span class="token string">""</span>
<span class="token punctuation">}</span>

<span class="token keyword">class</span> <span class="token class-name">Person</span><span class="token punctuation">:</span> <span class="token builtin">ADDataTable</span> <span class="token punctuation">{</span>
    
    <span class="token keyword">static</span> <span class="token keyword">var</span> tableName <span class="token operator">=</span> <span class="token string">"People"</span>
    <span class="token keyword">static</span> <span class="token keyword">var</span> primaryKey <span class="token operator">=</span> <span class="token string">"id"</span>
    <span class="token keyword">static</span> <span class="token keyword">var</span> primaryKeyType <span class="token operator">=</span> <span class="token builtin">ADDataTableKeyType</span><span class="token punctuation">.</span>autoUUIDString
    
    <span class="token keyword">var</span> id <span class="token operator">=</span> <span class="token function">UUID</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span>uuidString
    <span class="token keyword">var</span> firstName <span class="token operator">=</span> <span class="token string">""</span>
    <span class="token keyword">var</span> lastName <span class="token operator">=</span> <span class="token string">""</span>
    <span class="token keyword">var</span> addresses<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token builtin">String</span><span class="token punctuation">:</span><span class="token builtin">Address</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token punctuation">]</span>
    
    <span class="token keyword">required</span> <span class="token keyword">init</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        
    <span class="token punctuation">}</span>
    
    <span class="token keyword">init</span><span class="token punctuation">(</span>firstName<span class="token punctuation">:</span> <span class="token builtin">String</span><span class="token punctuation">,</span> lastName<span class="token punctuation">:</span><span class="token builtin">String</span><span class="token punctuation">,</span> addresses<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token builtin">String</span><span class="token punctuation">:</span><span class="token builtin">Address</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">self</span><span class="token punctuation">.</span>firstName <span class="token operator">=</span> firstName
        <span class="token keyword">self</span><span class="token punctuation">.</span>lastName <span class="token operator">=</span> lastName
        <span class="token keyword">self</span><span class="token punctuation">.</span>addresses <span class="token operator">=</span> addresses
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token keyword">class</span> <span class="token class-name">Group</span><span class="token punctuation">:</span> <span class="token builtin">ADDataTable</span> <span class="token punctuation">{</span>
    
    <span class="token keyword">static</span> <span class="token keyword">var</span> tableName <span class="token operator">=</span> <span class="token string">"Groups"</span>
    <span class="token keyword">static</span> <span class="token keyword">var</span> primaryKey <span class="token operator">=</span> <span class="token string">"id"</span>
    <span class="token keyword">static</span> <span class="token keyword">var</span> primaryKeyType <span class="token operator">=</span> <span class="token builtin">ADDataTableKeyType</span><span class="token punctuation">.</span>autoUUIDString
    
    <span class="token keyword">var</span> id <span class="token operator">=</span> <span class="token function">UUID</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span>uuidString
    <span class="token keyword">var</span> name <span class="token operator">=</span> <span class="token string">""</span>
    <span class="token keyword">var</span> people <span class="token operator">=</span> <span class="token builtin">ADCrossReference</span><span class="token operator"><</span><span class="token builtin">Person</span><span class="token operator">></span><span class="token punctuation">(</span>name<span class="token punctuation">:</span> <span class="token string">"PeopleInGroup"</span><span class="token punctuation">,</span> leftKeyName<span class="token punctuation">:</span> <span class="token string">"groupID"</span><span class="token punctuation">,</span> rightKeyName<span class="token punctuation">:</span> <span class="token string">"personID"</span><span class="token punctuation">)</span>
    
    <span class="token keyword">required</span> <span class="token keyword">init</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        
    <span class="token punctuation">}</span>
    
    <span class="token keyword">init</span><span class="token punctuation">(</span>name<span class="token punctuation">:</span> <span class="token builtin">String</span><span class="token punctuation">,</span> people<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token builtin">Person</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">self</span><span class="token punctuation">.</span>name <span class="token operator">=</span> name
        <span class="token keyword">self</span><span class="token punctuation">.</span>people<span class="token punctuation">.</span>storage <span class="token operator">=</span> people
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

Swift Portable Object Notation

Action Codable also introduces support for the new Swift Portable Object Notation (SPON) data format that allows complex data models to be encoded in a portable text string that encodes not only property keys and data, but also includes type information about the encoded data. For example, using the Address struct above:

@obj<span class="token punctuation">:</span><span class="token builtin">Address</span><span class="token operator"><</span>state$<span class="token operator">=</span>`<span class="token constant">TX</span>` city$<span class="token operator">=</span>`<span class="token builtin">Seabrook</span>` addr1$<span class="token operator">=</span>`<span class="token number">25</span> <span class="token builtin">Nasa</span> <span class="token builtin">Rd</span> <span class="token number">1</span>` zip$<span class="token operator">=</span>`<span class="token number">77586</span>` addr2$<span class="token operator">=</span>`<span class="token builtin">Apt</span> #<span class="token number">123</span>`<span class="token operator">></span>

The portable, human-readable string format encodes values with a single character type designator as follows:

  • % – Bool
  • ! – Int
  • $ – String
  • ^ – Float
  • & – Double
  • * – Embedded NSData or Data value

Additionally, embedded arrays will be in the @array[...] format and embedded dictionaries in the @obj:type<...> format.

Action Data Providers

Action Data Providers provide light weight, low-level access to several common databases and data formats such as SQLite, JSON, XML, SPON and CloudKit. Results are returned as a key/value dictionary (ADRecord) or as an array of key/value dictionaries (ADRecordSet). For example:

<span class="token keyword">let</span> provider <span class="token operator">=</span> <span class="token builtin">ADSQLiteProvider</span><span class="token punctuation">.</span>shared
<span class="token keyword">let</span> record <span class="token operator">=</span> <span class="token keyword">try</span> provider<span class="token punctuation">.</span><span class="token function">query</span><span class="token punctuation">(</span><span class="token string">"SELECT * FROM Categories WHERE id = ?"</span><span class="token punctuation">,</span> withParameters<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
<span class="token function">print</span><span class="token punctuation">(</span>record<span class="token punctuation">[</span><span class="token string">"name"</span><span class="token punctuation">]</span><span class="token punctuation">)</span>

Additionally, Action Data Providers provide high-level Object Relationship Management(ORM) functionality using Action Codable controls and data models conforming to the ADDataTable protocol. For example, using the Address, Person and Group data models presented above:

<span class="token keyword">let</span> addr1 <span class="token operator">=</span> <span class="token function">Address</span><span class="token punctuation">(</span>addr1<span class="token punctuation">:</span> <span class="token string">"PO Box 1234"</span><span class="token punctuation">,</span> addr2<span class="token punctuation">:</span> <span class="token string">""</span><span class="token punctuation">,</span> city<span class="token punctuation">:</span> <span class="token string">"Houston"</span><span class="token punctuation">,</span> state<span class="token punctuation">:</span> <span class="token string">"TX"</span><span class="token punctuation">,</span> zip<span class="token punctuation">:</span> <span class="token string">"77012"</span><span class="token punctuation">)</span>
<span class="token keyword">let</span> addr2 <span class="token operator">=</span> <span class="token function">Address</span><span class="token punctuation">(</span>addr1<span class="token punctuation">:</span> <span class="token string">"25 Nasa Rd 1"</span><span class="token punctuation">,</span> addr2<span class="token punctuation">:</span> <span class="token string">"Apt #123"</span><span class="token punctuation">,</span> city<span class="token punctuation">:</span> <span class="token string">"Seabrook"</span><span class="token punctuation">,</span> state<span class="token punctuation">:</span> <span class="token string">"TX"</span><span class="token punctuation">,</span> zip<span class="token punctuation">:</span> <span class="token string">"77586"</span><span class="token punctuation">)</span>
    
<span class="token keyword">let</span> p1 <span class="token operator">=</span> <span class="token function">Person</span><span class="token punctuation">(</span>firstName<span class="token punctuation">:</span> <span class="token string">"John"</span><span class="token punctuation">,</span> lastName<span class="token punctuation">:</span> <span class="token string">"Doe"</span><span class="token punctuation">,</span> addresses<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token string">"home"</span><span class="token punctuation">:</span>addr1<span class="token punctuation">,</span> <span class="token string">"work"</span><span class="token punctuation">:</span>addr2<span class="token punctuation">]</span><span class="token punctuation">)</span>
<span class="token keyword">let</span> p2 <span class="token operator">=</span> <span class="token function">Person</span><span class="token punctuation">(</span>firstName<span class="token punctuation">:</span> <span class="token string">"Sue"</span><span class="token punctuation">,</span> lastName<span class="token punctuation">:</span> <span class="token string">"Smith"</span><span class="token punctuation">,</span> addresses<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token string">"home"</span><span class="token punctuation">:</span>addr1<span class="token punctuation">,</span> <span class="token string">"work"</span><span class="token punctuation">:</span>addr2<span class="token punctuation">]</span><span class="token punctuation">)</span>
    
<span class="token keyword">let</span> group <span class="token operator">=</span> <span class="token function">Group</span><span class="token punctuation">(</span>name<span class="token punctuation">:</span> <span class="token string">"Employees"</span><span class="token punctuation">,</span> people<span class="token punctuation">:</span> <span class="token punctuation">[</span>p1<span class="token punctuation">,</span> p2<span class="token punctuation">]</span><span class="token punctuation">)</span>
<span class="token keyword">try</span> provider<span class="token punctuation">.</span><span class="token function">save</span><span class="token punctuation">(</span>group<span class="token punctuation">)</span>

Creates the People, Group and PeopleInGroups SQLite database tables (if required) and inserts the new record instances, with relationships, into the database. For example:

To retrieve the Group from the database, use the following:

<span class="token keyword">let</span> group <span class="token operator">=</span> <span class="token keyword">try</span> provider<span class="token punctuation">.</span><span class="token function">getRow</span><span class="token punctuation">(</span>ofType<span class="token punctuation">:</span> <span class="token builtin">Group</span><span class="token punctuation">.</span><span class="token keyword">self</span><span class="token punctuation">,</span> forPrimaryKeyValue<span class="token punctuation">:</span> <span class="token string">"F6DEC3CD-DA62-4A08-A2B6-272E62A7F6E3"</span><span class="token punctuation">)</span>

The Action Data Providers are designed to be interchangeable, so you can start developing locally using a SQLite database and a ADSQLiteProvider, then later switch to CloudKit and a ADCloudKitProvider without have to change any of your other code.

Additionally, Action Data Providers can be used to move data from one source to another. For example, download data from the web in JSON using a ADJSONProvider and save it to a local SQLite database using a ADSQLiteProvider, all with a minimal of code.

Several of our Action Controls are designed to take an Action Data Provider as input (such as ActionTable), making it easy to work with complex data and common display and input methodologies that would typically require tons of repetitive, boilerplate code.

Action SQL Parser

The ADSQLParser provides the ability to parse text containing one or more SQL commands into an Action Data SQL Document Object Model (DOM) and is used to provide SQL support for data sources that don’t support SQL natively (such as CloudKit and JSON).

The ADSQLParser uses SQLite’s SQL syntax and currently support a subset of the full SQL language. For example:

<span class="token keyword">let</span> sql <span class="token operator">=</span> <span class="token string">""</span>"
<span class="token constant">CREATE</span> <span class="token constant">TABLE</span> <span class="token constant">IF</span> <span class="token constant">NOT</span> <span class="token constant">EXISTS</span> parts
<span class="token punctuation">(</span>
    part_id           <span class="token constant">INTEGER</span>   <span class="token constant">PRIMARY</span> <span class="token constant">KEY</span><span class="token punctuation">,</span>
    stock             <span class="token constant">INTEGER</span>   <span class="token constant">DEFAULT</span> <span class="token number">0</span>   <span class="token constant">NOT</span> <span class="token constant">NULL</span><span class="token punctuation">,</span>
    description       <span class="token constant">TEXT</span>      <span class="token function">CHECK</span><span class="token punctuation">(</span> description <span class="token operator">!=</span> <span class="token string">''</span> <span class="token punctuation">)</span>    <span class="token operator">--</span> empty strings not allowed
<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token string">""</span>"

<span class="token keyword">let</span> instructions <span class="token operator">=</span> <span class="token keyword">try</span> <span class="token builtin">ADSQLParser</span><span class="token punctuation">.</span><span class="token function">parse</span><span class="token punctuation">(</span>sql<span class="token punctuation">)</span>
<span class="token function">print</span><span class="token punctuation">(</span>instructions<span class="token punctuation">)</span>

API Documentation

Each tool in the Action Data suite has a fully documented API, with comments for every element included. Check out our API documentation to discover every feature that Action Data has to offer: