RealmExplorer – a piece of sample code for Realm DB

realmexplorer_01_smallFirst things first, look at the RealmExplorer github repo for the project.

Preface: CoreData

I have some history in using databases. From using Oracle, Frontbase, mySQL, PostgreSQL, sqlite etc. the last time I used a database was for a postcard app using CoreData. But I found CoreData to be a lot of overhead and boilerplate code to write.

Especially migrations are kind of not very intuitive to understand and if something goes wrong you are basically lost. While Xcode for a while had an Entity modelling tool (which had it’s roots in the WebObjects EOModeler), most of the time this tool did not work very well for me and had lots of bugs. In each Xcode version different bugs!

Also many people report running into issues when using CoreData with lots of objects, because it is easy to loose track of memory consumption with CoreData and if you do not actively check and work against that, you end up with a whole model graph being in memory. Not cool! So I wanted to try something different.

Realm

I found Realm by Realm.io to be interesting enough to tinker with. So I started working with their sample code projects. But none of those projects came even close to some real world example. So I just started prototyping something I will need for a different project anyway.

Starting with a custom viewcontroller for adding & editing entities I recognized that this would soon become rather painful to provide e.g. inputfields for text and numbers and dates. So I grabbed FXForms to give it a try after I had already completed a viewcontroller to manage DBCaptain entities a bit.

Migrations

Right from the start I wanted to know how migrations work. Because usually those are the weakest spot in every db operation taking place. With a live product you always „pray“ that nothing will go wrong during migrations on the customers device. And keeping track of changes to the db schema is very important to have a stable app.

So I built the sample around the process to „simulate“ an app in development. You can now iterate through different development steps (5 different app states & their migrations) and their needed migrations. This way I figured out how I can safely manage my migrations (i.e. always keeping a backup of the old schema). In the project the
DatabaseFactory.m class manages all that. It detects existing schemas using a precise naming scheme for each Realm-db created.

During app launch any necessary migrations are executed if necessary. Also, any errors happening while the app launches and gets into trouble activating the database, are nicely displayed.

Create/Insert/Edit/Delete

I started with one entity DBCaptain which is basically a user entity. I just wanted to create user objects and populate them with different properties. I tested insertion with one and with many users on the main thread and on the background thread. I also took advantage of notifications coming from Realm as soon as an operation finished updating the db.

Deletion of objects came next. As always having the UI keeping track of all those changes is the more difficult task. So expect some „ugly“ code, because this was only me tinkering around. When i wanted to edit existing objects I recognized that I do not want to create all those textfields manually.

FXForms

That was when FXForms came to the rescue. I started to recreate the already half done viewcontroller and created another based on FXForms. I needed some time to wrap my head around FXForms, because basically this is a quite sophisticated hack of providing compact descriptions of UITableViewCells and their content.

You describe what kind of structure your form should have and what kind of value types it should use. FXForms crafts the UITableView which makes all those inputfields come true. Things start to become a bit tricky if you want to control those UITableViewCells more directly. E.g. I needed a way to exclude certain properties of being edited at all. So I simply extended the FXForms protocol to allow for a denial of userInteractionEnabled on certain cells by adding the FXFormFieldEditable key. This is used on the CaptainFormViewController to exclude the information about the database schema and the encryption status to not be editable.

Evaluation

My first impression of Realm DB is quite positive. It is fast, it provides helpful error-messages and it is easy to setup and comprehensive in what it does and how it works. I never in my life had migrations up and running that quickly. Very, very helpful was the Mac app RealmBrowser to open a realm DB file directly. I used that while checking my migrations and the results of operations which added arbitrary data (e.g. image files).

What is actually really great is that encryption is supported for the db by just providing a 128 bit key. That is really helpful to protect user data and increase safety of the realm db file even if it gets backed up into some cloud somewhere else.

What’s next?

I think I missed something related to the KVO-thingy going on by Realm. But I had no time until now to figure that out. I suppose they actually track entities and changes via KVO. But I am not yet sure how exactly this works and how I can detect if an object has pending changes. That is why I added a hasPendingChanges BOOL-flag to both ViewControllers for editing entities. So help is welcome here!!

I did not have time to do some real hardcore performance testing, i.e. adding thousands of entities and relationships in a short time and crafting a rather complex model with complex relationships which define ownership and cascading deletions etc. Also doing sophisticated db queries is on my list to do next.

But having a prototype now to tinker with helps already a lot. Since I learn best from sample code, and I think I am not the only one learning new things this way, I hope it helps others to jumpstart with Realm, too.

Why do I blog this? I just wanted to give a bit of background info on the sample code I put on github. Have fun tinkering & I am really in need of getting more info on how I can detect changes to an object so I know WHEN to save changes to the db. Maybe someone who already grabbed the concept better can help me here?? Leave a comment or contact me via github.

Open Night of Code

ONOC_logo

Die erste ONOC wird am 21. November 2014 stattfinden. Die Türen der E0 im MZH werden ab 17 Uhr offen stehen, ab 18 Uhr (bis Open End) ist offizieller Beginn. Dann werden wir kurz die Projekte und Aufgaben vorstellen und ab ca. 19 Uhr heißt es dann: Happy Hacking!

Ein Open Night of Code Event das an der Uni Bremen im November stattfindet. Leider ist mein November schon ziemlich vollgepackt mit anderen Terminen. Aber mal gucken…

Why do I blog this? Vielleicht schau ich selber mal vorbei. Nur eine Note-2-self.

Using UIImage-PDF category for @#x resolution independence coping with ever increasing Apple iDevice Size Fragmentation

Since iOS 8 revealed YADS (Yet another device size), things start to become too fragmented and way to complicated to optimize the display of your app on all those devices down to the pixel. I mean there never was a pixel, only a point and subpixel antialiasing, but up until @2x we were able to optimize for pixel perfect alignments with a little bit of extra effort in Photoshop (or other good tools like Pixelmator).

The Post-@2x-era

Since @3x this time is over. If you have a universal app which needs to work on iPad, iPhone and iPod and on @1x, @2x and @3x, your matrix looks something like this:

  iPhone/iPod iPad
@1x Picture.png PicturePad.png
@2x Picture@2x.png PicturePad@2x.png
@3x Picture@3x.png Who knows what`s next?

If your app goes the extra mile on perfect UXP with the display of your image assets you will also take portrait and landscape orientation into account. This means the following:

  iPhone/iPod iPad
Portrait@1x Picture.png PicturePad.png
Landscape@1x PictureLandscape.png PicturePadLandscape.png
Portrait@2x Picture@2x.png PicturePad@2x.png
Landscape@2x PictureLandscape@2x.png PicturePadLandscape@2x.png
Portrait@3x Picture@3x.png Who knows what`s next?
Landscape@3x PictureLandscape@3x.png Even in Landscpe?

If you have 9 image assets you want to display (say some simple icons), this will amount to 9 x 10 = 90 image assets to add. Repeat my words, that is ninety assets you need to provide.

The power of 10

This was way too much for me. Since I am independent developer, I simply cannot afford ill-sized amount of workload. So why not go back to 9 image assets from the 90 assets you usually need to craft?

And that is what I did. I just vectorized all those image icons which were very important for the main screen in my app. That took some time, but from now on I simply do not care anymore about Apple’s next plans to release the oversized iPhone Plus Plus or the iPhone Super Plus or the iPad Air Hyper Retina or the iPod Hexagonal. Even iOS 9 with frosted glass effect for text and vibrancy effect for the device home button… I DON’T CARE.

I just use mindbrix UIImage-PDF, a category which enables to create UIImages from PDF-files containing scalable vector content (Kudos to cocoanetics). This category allows you to switch your assets from .png to .pdf in no time and saves you megabytes in your binary bundle.

Results of using PDF

I have an app on the AppStore called Sea Weather Pro which actually needs 9 icons and uses them to create a nice rendered main screen menu with large tap targets and some kind of „plates“ which have a light gradient and some nearly invisible borders. These plates need to be rendered differently in different sizes and with different icon sizes and for different screen scales on each and every device in portrait and landscape.

The Portrait screen looks like this now (click to see full size):

The Landscape screen looks like this now (click to see full size):

I was able to adjust the landscape size of the icons on these plates to be a little bit smaller, so when the iPhone/iPod is rotated to the landscape orientation the overall visual impression is lighter than before. This was only possible due to the use of PDF-assets.

The used resources (png vs. pdf)

The assets I used were completely different. It was bitmap versus vector data and the vector won by far. The additional flexibility you gain for having every size you want at any time with no more tool involved than UIImage, combined with the time saved editing and slicing bitmap assets is mindblowing.

BUT and this is a real issue, I was at first not able to use a PDF file which actually supports alpha blending or transparency. This is a well known issue because PDF never was meant to be used for something other than printing on paper (which is white/opaque background by default). So we need to jump through the following loop, if your exported PDF file does not yet kill the white box usually found in such files when exported.

Where I used this before:
PNG Resource

I now use this:
PDF Resource

The process in 11 steps (using InkScape in X11 & XQuartz FTW!)

I was a Photoshop heavy user in the Ante-@3x-era, so all my resources are still in PSD-files. My vectorization of icons was done in PS. When I started saving the vectorized content as PDF-files I recognized that the PDF files contained always a white box on which the shape was drawn. There was no transparency or alpha blending whatsoever. I tried really every single configuration and colorspace to make this box disappear. It was not possible! So I tried using InkScape to fix my problem. Which actually worked.

process_inkscape_01

Step 1
Import EPS file you exported from Photoshop. Be careful to clip to the objects bounds/frame. This ensures you keep the aspect ratio and spacing in the document.
process_inkscape_02

Step 2
Now you see your icon, but you also have a white background, which should be transparent (alpha = 0).
process_inkscape_03

Step 3
Add a layer to the image, below the existing layer containing your whole shape.
process_inkscape_04

Step 4
Draw a color filled rectangle on that new layer behind the vector shape you imported.
process_inkscape_05

Step 5
Change to the layer of the vector shape. Choose the selection tool and select the shape. Now choose ungroup from the menu.
process_inkscape_06

Step 6
Now select the white background box. And press the delete button…
process_inkscape_07

Step 7
After the deletion you now have the single shape without a white box. Select the layer containing the colored rectangle…
process_inkscape_08

Step 8
…delete/remove this layer.
process_inkscape_09

Step 9
Now go to file menu and choose print
process_inkscape_10

Step 10
Choose „Print as File“ and give a meaningful name to it.
process_inkscape_11

Step 11
You now have a pdf image that is way smaller than the EPS file or PDF file Photoshop spit out. And this one is able to be rendered with transparency/alpha blending.

Why do I blog this? Because I am fed up with Apple’s neckbreaking pace of dropping new iOS releases and iDevice sizes. I need to come up with solutions Apple did not provide to make all those transitions cost efficient.

There is no other way to provide app updates than reducing the amount of work on this hell of fragmentation which now was introduced by iOS 8. Even the category class I linked to above is not yet fully ready to be used in iOS 8. Check out my forked one which fixes several issues with caching and the correct scale values.

I hope I can help other independent developers. And I dare Apple to slow down their amount of OS iterations dropped on developers and instead spend a whole year in just improving and cleaning up the mess they left behind after this power play on fragmentation and design changes. Apple please start thinking about usefulness and simplicity again and CONSOLIDATE. And please show some empathy towards developers (aka your ecosystem), or you will soon have messy, ugly and buggy apps all over the place or even worse are left with only OpenGL non-UIKit-using apps like games. You will end up with a GameStore instead of an AppStore if you continue going down this road. It’s the developers in the first place which take care of bugfree and perfectly working apps and not your review team. You simply cannot replace developers with reviewers. And the next time something isn’t yet ready to ship – like iOS 8.0? Don’t ship it! It’s that simple.