In the case you need an app that displays dynamic content and when the team “reviews” the “views” you generated on your iOS app fetching the approved content for the app, using the agreed template and the right data, and then “the picture is …”, “the text looks …”, “is not where it is supposed to …”. Well i wish everyone could arrange it the right way, so we don’t have to reship the hole project after every review but a crash course of “Storyboard” and “Xcode” wont do any good, so i went and built an easy to use interface where we all could create the views using pictures and text boxes, and then i could make it look exactly how it looked. So i went on and made it, here is a bit of my thoughts and code.
I needed to create custom views for an iOS app and serve them as dynamic content to be displayed. So what we need to accomplish here is some sort of logic to create the view and it’s components, an easy to use interface to create them and some way to render all that data on the iOS app. We will go trough all of those steps in a series of posts(not sure how long they will take). I will try to be concise, cause i have a tendency to loose interest on huge blog posts (they sometimes are needed and have a point Design Patterns in Swift there is a good example).
I double quoted solution because i don’t feel this like being the ultimate path for attacking this predicament. I will simply present my approach and i hope to get some feedback to improve it :).
Lets begin with a checklist of all the things i’m looking to accomplish in order to build an easy to use webapp for creating views for an iOS device, and of course actually displaying the views on the device.
- Create the logic behind the rails app, to model the problem.
- Create an easy to use tool to visually create the views.
- Export the data in a simple format to display it on the device.
- Sit back and watch the happy faces when we can actually make the content view how it looked.
Defining some stuffs
Let’s begin to “objectify” the problem. Since the objective of this post is to build the actual thing to create the views and send them to the device for further rendering, i’ll go ahead and expose my approach and i’ll be glad to review it later with anyone kind enough to comment :). The views are a collection of sections they will be the base of the hierarchy a simple container of sections, the only relevant thing for me here is that a digital publication, can and almost always will have more than a single view, therefore the only attribute on the views could be the view index, meaning the order where the view will be displayed. So the sections are the base of a more complex hierarchy, because like that i can extract common attributes, as the section axis, height, width etc…, plus i can add more section types later(pretty much object oriented programming all the way), such as hyperlinks and hidden sections. So i have the head of my hierarchy on a “view” object, this object haves sections, and each section haves a type, something like this:
Each one of the sections will have then his own type, such as an Image Section, or a Text Section or whatever section needs to be defined.
So the sections are like an encapsulation of the actual thing to render, and depending of the type of the section an actual useful object to render will be defined and will live persisted on the database.
Now the good part!!. We can create the rails project now, the full code can be found here, there you will find all the necessary migrations, and of course(this is my curse) some tests to add in the mix, i have change my tests methodology since i read dhh’s article, i will go through the process right now.
First thing first, the migrations:
- All we need on the views table is actually the view_index attribute.
- On the sections table we need all the common attributes to the sections, the order of creation of all the sections inside the views and of course the necessary reference to the parent view.
- The ImageSections will of course have the reference to its section and since i am using carrier-wave for file uploading i am gonna need two fields, one for carrier-wave named image and other for the iOS App to load the image named image_name
- The TextSections table will hold the font, the font-size, the content, the alignment will be an integer according to the text alignment property of text-boxes and labels on iOS.
So the migration looks like this:
So now that all the definitions are on the right place, usually i begin realizing that all the validations and tests are missing i go test first on the models definitions not so much when i think about the system itself i go from feature, to better feature to test and make it even better. There is nothing special to it, just some plain old tests, i will go through the suit of tests.
First of all i wanna point out that i am musing mini_test and fixtures right from the rails stack. I will go through the reasoning of my test suite and the models definitions, i will add some code samples, but the complete code is on the github project.
With the views the need was simple i just needed to access the view’s sections and make sure that the index of the section is a positive number. The fixture is simpler, just add a random positive number. To satisfy this tests the model will reflect a has_many relationship with the sections models and will validate numerically that the view_index field must be greater than or equal to 0.
On the sections, to make sure that the data was sanitized, tests for the presence of mandatory attributes are present, and for the minimum values of axis, width, height and the other numeric values. And of course access to the sections real underlying object definition, in the case of an image_section an object on the image_sections table pointing at his section parent, so it can be retrieved with the has_one relation on the section model definition. Since a section is pointless without a minion object the fixtures reflects it:
On the tests all the validations are tested and also the relations:
The ImageSection model only needs the string field for carrierwave, the name of the image for the iOS and the reference for the parent object. The tests are for the presence of this fields. The TextSection model haves a few more validations, since there are more fields to look after, for example the max and min values of the three fields for the rgb colors red, green and blue, also the text-alignment and the font-size and no duplication on the parent section object. Also a high number of times the default font color remains the same also the size and the alignment so an init method was added on the model for easy creation:
That is pretty much it on the models. The models holds simple but complete definitions for the problem intended to solve.
Doing something else
Now the interface part is left, on the fronted side of the application the heavy-lifting will be done so it will be left for the second part of this series, where an easy to use interface to create the views will be made, yeah of course, easy to use but not that easy to implement. Well the easiest thing for us to draw around and update things on a webpage is of course a canvas, so the trick will be to simulate an iOS device screen and on the canvas draw the items, but remains the not so easy task of saving the canvas state, drawing the images and texts and the line changing text(OUCH!!). Hope this posts clarifies the problem, more on this on following articles. Keep coding strong.