When XE4 came out and the full extent of the bait and switch perpetrated by Embarcadero became clear, I decided that my money was better spent with RemObjects and their Oxygene product. But it has only been this past weekend that I finally found some “quality time” to spend with it.
I have had a number of false starts with Oxygene since my purchase months ago. These have not been the fault of Oxygene, simply the result of the amount of stuff on my plate, first with a big (5 week!) trip to Ukraine and the UK to organise and then embark upon, and then the aftermath (3,500+ photos to develop in Lightroom – since I shoot RAW, to use a technical term!). 3 months later I am still only about 1/2 way through those photos!
I should stress again that every one of the false starts came to an end not because of any difficulty experienced with Oxygene. Far from it. Installation, upgrades and configuration (what little there is that is required) has been smooth and friction free at every step of the way. It hasn’t been a question of “this is taking longer than I expected” but rather more simply “I don’t have as much time as I thought I did“.
For the same reason – for example – I haven’t even got as far as installing Delphi XE4 yet.
But this weekend I was determined to finally get some code generated by Oxygene and running on an actual iOS device. Consistent with my – limited – experience with Oxygene thus far, this all went very smoothly.
Even the upgrade of the CrossBox component – the Oxygene counterpart to Delphi’s PA Server – was all but automatic. After installing the latest update to Oxygene, the CrossBox icon on the VisualStudio toolbar (running in my Windows VM) notified me that an update to CrossBox on the OS X host machine was necessary. After confirming that I did indeed wish to update CrossBox, Oxygene took care of stopping the OS X CrossBox process, updating it, then restarting it.
The only complication was the fact that I had chosen an unfortunate time to finally get the necessary assets in place in Xcode, with various Apple Developer Services still unavailable when I started. That was finally resolved overnight, incidentally – all Apple Developer Services are now back up and running. Worth mentioning of course is that these particular difficulties would have affected all developers for Apple devices, whether using Oxygene, Delphi or Xcode.
So then I set about crafting my first application, which I created by selecting one of the many template projects offered by Oxygene.
I chose a “Tabbed Application”.
This immediately exposed me to the concept of Storyboards in iOS development. Storyboards initially seemed attractive, but after doing a little research I decided I wanted to start with a more basic approach: an UI built entirely in code (for reasons that aren’t relevant to this post).
And this is what brings me to the point (finally!) of this post.
My biggest concern with the FireMonkey approach taken in Delphi is the constraints this imposes in terms of being able to learn from any community or examples. FireMonkey is – by any measure – a niche platform and if (and when) a FireMonkey developer runs into any question about how to achieve something on an iOS device there are likely to be precious few examples for them to apply directly in their code. Most help for a FireMonkey developer can only come from other FireMonkey developers.
Oxygene likely has even fewer users than FireMonkey, so how would I get on ?
Well, I immediately had 2 questions:
1) How do I remove storyboards from an iOS storyboard application ?
2) How do I create an application with a 100% programmatically created UI ?
In both cases, the answer came not from Oxygene, RemObject or VisualStudio sources, but directly from the iOS community at large (in the form of online articles, references, examples etc).
I should mention at this point that in Xcode you have the option of creating your project without Storyboards right at the start, avoiding the first problem entirely. This is not an option in Oxygene currently (it would be a nice addition I think, but not a hugely important one, as we shall see).
An iOS storyboard is itself simply an XML file. This is edited – visually – using Xcode, but in VisualStudio the storyboard file is simply presented within the Solution Explorer. In fact, it is interesting to compare that solution with the equivalent Tabbed App project in Xcode (created from the equivalent Xcode template):
The contents of the two projects are remarkably similar although Oxygene I think organises the contents of the project more helpfully. And, of course, being ObjectPascal, in Oxygene we don’t have to contend with “.m” and “.h” file pairs for our code!
We can easily see that both projects contain the “storyboard” file.
Worth noting is that if you do wish to work with Storyboards then as long as you keep your project source in a location accessible by both the Windows VM and the OS X host, you can simply switch to OS X and double-click the storyboard file in Finder to edit the file visually in Xcode.
But back to my simple, first project.
I didn’t want storyboards, so I removed them from my solution and indicated that I also wanted them to be deleted. This resulted in complaints at runtime from my application, that a required Storyboard could not be found.
At first I feared that Oxygene was imposing the use of Storyboards on me, but I needn’t have worried. A few seconds on Google revealed that the info.plist file contained configuration information for my iOS project, including any initial storyboard:
Again, there is a directly equivalent plist file in the Xcode project, though it has to be said that in this instance Xcode presents the contents of this file in a more user-friendly fashion:
The point being that the lesson learned from the Xcode/Objective-C community was directly applicable to me as an Oxygene-Nougat developer: To remove storyboards from your iOS application, the application info.plist file is the key.
Objective accomplished – I now had a storyboard-free iOS application. Now how to create the UI programmatically ?
Creating an iOS UI Programmatically
And this is the crux of the matter for me.
Again, a few seconds with Google led me to a very helpful article on exactly this subject.
Obviously I did not, and could not, just copy and paste the code from this article. Not least, I first wanted to understand it. But let’s look at the final Objective-C example that the article builds up to:
And now let’s look at the equivalent in Oxygene:
Even though I was expecting something like this, the similarity is striking.
This has further strengthened my confidence in having chosen Oxygene for this endeavour.
As I continue my journey and learn more about iOS development, I expect to be able to learn directly from the entire iOS Xcode/Objective-C development community (and books!). I can even ask questions of that community in terms that are relevant to them and obtain answers that are immediately useful to me, with only simple syntax conversions required to-and-from.
Having said that, one thing did immediately catch my eye that has the potential to cause problems for the unwary. It is easily addressed however, and I shall have to reveal and discuss that in my next post because unfortunately I’ve run out of my available time for this ! Again ! 🙁