Avatar of marc

by marc

iOS 7 and OS X Mavericks

June 17, 2013 in Cocoa, iOS, Mac, Oxygene, ROFX, WWDC, Xcode

As you have probably heard by now, last week Apple announced iOS 7 and OS X Mavericks, new major versions of both its flag-ship operating systems. I had the privilege of being on site in San Francisco and attending WWDC in person, but the keynote with the core announcements is available for public viewing by anyone, and the remaining ~100 sessions of the conference are also available for free to all registered developers (major kudos to Apple for that, and more importantly, for making these videos available so fast, in most cases on the same day as the actual presentations!).

iOS 7 is a major new release and – most observers agree – a game changer. It’s a whole new UI paradigm for the OS, and will be a very exciting release for both users and developers; there are a whole bunch of new technologies that will let you create even better iOS apps, and will make the whole iOS experience even better for the user — in the core OS or with your apps.

Due to the massive UI overhaul, most iOS apps will need a serious rethinking for iOS 7 to stay relevant – which means extra work for developers, but also extra opportunities. From what i can tell (and am allowed to tell), switching an application over to the core iOS 7 “look” will be simple, but really making an app feel at home on iOS7 will require a lot of thought — no way around it.

I have already started moving two of our (internal) apps to iOS 7 while on site in San Francisco, simply because after (foolhardily) upgrading my main phone to the new OS, i could no longer stand looking at the old UI ;). One app is “done” and was relatively straight-forward – mainly a matter of rebuilding with the iOS 7 SDK, and making a few adjustments here and there to better embrace the new style; the other will be more work.

OS X Mavericks (if you don’t like the name, you are not alone. Virtually everybody i talked to or heard talk about it found it “weird”) is a smaller upgrade, by comparison, but also a significant release with a ton of exciting technologies for developers – two that were highlighted in the keynote include the new Maps API and cool new energy-saving APIs and technologies. (And if you’re not excited by being able to make your apps more power-efficient, then you have no business developing Mac apps! ;).)

Of course the big question you’re all asking is how Oxygene for Cocoa is working with the new iOS 7 and OS X Mavericks. The good (and slightly unexciting, because expected) news is: it works just fine. We’ve long had an article on the Wiki that discusses the (simple) steps for hooking up Oxygene with new beta SDKs, and Oxygene is working fine with iOS 7 and with Mavericks (although i do recommend grabbing the latest beta drop of Oxygene, as we already made some tweaks and improvements there).

All the new APIs (IIRC Apple mentioned a number of 1500 new APIs being available) will work with Oxygene out of the box – no need to wait for anyone to create any wrappers or headers for you, and re-building your Oxygene apps with the iOS 7 SDK will give you the new iOS 7 look right away (but not save you from re-examining how to really embrace iOS 7 best with your app, of course).

There are also a few new non-API features that we’ll be embracing with Oxygene as well, but unfortunately those are (afaict) all under NDA, so i cannot talk about them yet. But suffice to say over the next few months we will of course be doing a lot of testing with Oxygene and the new APIs and SDKs to keep Oxygene up to date with the SDKs and the Xcode 5 tool chain.

Of course we’ll also be testing Data Abstract and RemObjects SDK for Cocoa with the new SDKs, and (where applicable) expanding them with support for new APIs. In my testing so far, they work great (both the apps i mentioned above are DA-based, and run fine on iOS 7, for example).

Support

Talking about new iOS and OS X SDKs is always a tightrope walk, as there’s a lot of information that’s under NDA (but available to all registered Apple developers – so do make sure you check out the beta builds and all the videos from WWDC). But Oxygene, as well as RO/DA for Cocoa, are already working great with the new operating systems, and we’ll be working hard to expand those parts that do need explicit support and work to fully embrace the new OSs.

If you have any specific questions regarding support for or issues with the new SDKs, there’s two places to get help: for one, we’ll be monitoring and participating in Apple’s beta forums, so you can post questions about Oxygene there (maybe add “(Oxygene)” to the subject so we can find them easier). And you can also always directly email support.

We cannot discuss the iOS 7 or OS X Mavericks Beta SDKs on Connect; you could be violating your NDA by posting details there, and we’d be doing the same by answering. So be careful.

Summary

I’m very excited about both iOS 7 and Mavericks (and i assume i’ll eventually get over the name, too), and so should you. I’m looking forward to seeing what you’ll build on the new OSs with Oxygene and Data Abstract.

Data Abstract Sample for Oxygene for Cocoa

June 17, 2013 in Uncategorized

Hi guys,

Recently I’ve spotted a question about Nougat samples in the support thread. Unfortunately, we didn’t offer any sample applications at that time, so I’ve tried to quickly compose one.

We’ve already proposed some New Project templates for Data Abstract for Cocoa though:

Nougat Templates

Using these templates, and after going through several steps in the wizard, we can get an almost complete data-aware application (we just need to review and adjust the code in several places marked with a #warning directive).

So I’ve started with this New Project wizard and created a client for the PCTrade sample domain exposed by Relatvitiy server.

In this sample, I want to show several things:

  • Working with Relativity server.
  • Downloading data at the client side in an asynchronous way.
  • Using Cocoa NotificationCenter.
  • Master-Detail navigation in the data.
  • Using Calculated fields for the DADataTable.
  • Conditional formatting of the table view cells.
  • The application should be universal and support both iPhone and iPad.

At the same time, I’ve tried to keep things as simple as possible to make it easy to understand common ideas.

So let’s start:

Working with Relativity domains

Almost all implementation required for connecting to the Relativity server, including autentication at the Relativity side, is done by the template and new project wizard. Most important places in the code are highlighted with the #warning directive. For example, in the DataAccess.pas file you can see the following place:

    {$WARNING  Define your server address and Relativity domain name, below.}
    const SERVER_URL  =                    'http://192.168.0.22:7099/bin';
    const SERVICE_NAME =                   'DataService';
    const RELATIVITY_DOMAIN  =             'PCTrade Sample';
    const DOMAIN_SCHEMA  =                 'PCTrade';

Here you can adjust the URL of your Relativity server (my server uses http://192.168.0.22:7099/bin).
These constants will also be used for configuring the RemoteDataAdapter instance.

Another place that requires our attention is in the AppDelegate.pas and holds the passwords to log in to the Relativity domain:

method AppDelegate.needLogin(var aLogin: String) password(var aPassword: String): Boolean;
begin
  // The DataAccess automatically takes care of storing login information in Settings and Key Chain
  // and retrieving it as necessary. This method is only called when no login is stored (i.e. on first
  // run) or if the retrieved login was rejected by the server.
  // Typically, you would implement this method to bring up the UI that asks the user for his credentials.
 
  // By default, new Relativity Server domains will use "Data"/"Relativity" as login, unless
  // the login provider setup has been changed by the administrator.
  aLogin := 'Data';
  aPassword := 'Relativity';
 
  result := true; // return YES if the user provided login details, or NO if the user canceled
end;

Of course, in the real application, you can implement a popup window here with to enter login and password, or even get credentials from the application preferences, but I’m trying to keep it simple here.

Downloading data

Again, like in the point above, almost all implementation for downloading data from the server was generated automatically by the new project wizard.

You may notice that all the tables we selected in one of the last wizard step, were created with the appropriate properties in DataAccess.pas and code has been generated to fill them.

method DataAccess.downloadData;
begin
  // ToDo: Add code to download data from server
  // You will need to define fields and, if necessary, properties for your tables.
 
  var tableNames := new NSMutableArray<String>;
  tableNames.addObject('Clients');
  tableNames.addObject('OrderDetails');
  tableNames.addObject('Orders');
 
  var tables := fRDA.getDataTables(tableNames);
 
  Clients := tables['Clients'];
  OrderDetails := tables['OrderDetails'];
  Orders := tables['Orders'];
end;

It is important to note here that the given downloadData method is called asynchronously (in a separate thread), so we get a responsive and non-frozen UI.

method DataAccess.loadInitialData;
begin
  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), method begin
      ...
      downloadData();
      ...
      dispatch_async(dispatch_get_main_queue(), -> triggerDataReady);

Using notifications

Since we are downloading data in a separate thread, we need to notify our main UI thread with the results.
And here the Cocoa Notification Center comes in to help us.
In the code above you may have notice that after downloading the data, we perform a triggerDataReady call at the main thread. This method just posts a notification to the Notification Center that the job is done.

method DataAccess.triggerDataReady;
begin
  dataReady := true;
  NSNotificationCenter.defaultCenter.postNotificationName(NOTIFICATION_DATA_READY) object(self);
  NSLog('data is ready.');
 
  // ToDo: Add any processing you want to do once the data is fully ready
end;

Thus, if our controller needs to be informed about loading data results, we need to subscribe it to this notification. You can find the code in the ClientsViewController.pas file.

 
method ClientsViewController.viewDidLoad;
begin
  inherited viewDidLoad;
  // Do any additional setup after loading the view, typically from a nib
  ...
  NSNotificationCenter.defaultCenter.addObserver(self) 
                                     &selector(selector(dataReady:)) 
                                     name(DataAccess.NOTIFICATION_DATA_READY) 
                                     object(DataAccess.sharedInstance);
  ...
end;
 
method ClientsViewController.dataReady(notification: NSNotification);
begin
  tableView.reloadData();
end;

That means that when our ClientsViewController receives the DataReady notification, the dataReady: method must be invoked, which then refreshes the content of the table view.

Master-Detail navigation

This feature is part of the New Project template. By default, it generates already configured Master and Detail view controllers and the corresponding storyboards files with proper transitions between views inside.

Concrete implementation depends on device type.
For iPhone/iPod devices with their relatively small screens, when user selects a certain cell, the proper transition will be invoked and we can hook on it and set the info for the detail controller.

method ClientsViewController.prepareForSegue(segue: UIStoryboardSegue) sender(sender: id);
begin
  if segue.identifier.isEqualToString('showOrders') then begin
    var ip := tableView.indexPathForCell(sender);
    var tableRow := self.dataTable.rowAtIndex(ip.row);
    segue.destinationViewController.setDetailItem(tableRow);
  end;
end;

For the iPad device, the master and detail view are visible at the same time – no transition required. So we can just hook at the didSelectRow event and provide the details data for the detail controller as shown below:

method ClientsViewController.tableView(tableView: UITableView) didSelectRowAtIndexPath(indexPath: NSIndexPath);
begin
  if UIDevice.currentDevice.userInterfaceIdiom = UIUserInterfaceIdiom.UIUserInterfaceIdiomPad then begin
    var tableRow := self.dataTable.rowAtIndex(indexPath.row);
    OrdersViewController.detailItem := tableRow;
  end;
end;

About the details data: Since all necessary data is already present at the client-side, we are performing just a local data filtering using NSPredicates:

method DataAccess.OrdersByClient(client: String): NSArray;
begin
  var filterPredicate := NSPredicate.predicateWithFormat('Client == %@', client);
  result := self.Orders.rowsFilteredUsingPredicate(filterPredicate);
end;

Using Calculated fields for the DADataTable

As you might know, we can easily extend any existing DADataTable with our custom lookup and calculated fields which could help us get various related information. For this sample I need to know the amount of orders for each of our clients and also want to know the total for each client order (which can be calculated by summing the OrderDetails rows).

There is the special setupData method in the DataAccess class. It will be called while loading the initial data, so I can be sure that my tables will be extended in a proper way.

Declaring calculated fields is easy, we just need to specify the field name, its type and the target and selector for the method that will be used for calculation.

method DataAccess.setupData;
begin
  // Use this method to implement any setup that is needed on your data tables, such as
  // creating lookup or calculated fields, etc.
  self.Clients.addCalculatedFieldName('OrdersCnt') 
                            dataType(__enum_DADataType.datInteger) 
                              target(self) 
                           &selector(selector(calculateOrdersCntForClientRow:)); 
 
  self.Orders.addCalculatedFieldName('OrderSum') 
                             dataType(__enum_DADataType.datCurrency) 
                               target(self) 
                            &selector(selector(calculateSumForOrderRow:)); 
end;

As a rule, calculation methods take a row instance as the parameter and return an object (id) as the result of the calculation. So here is the sample of our calculation method:

method DataAccess.calculateSumForOrderRow(row: DADataTableRow): id;
begin
  // Get the Order ID value from the row 
  var orderID: Integer := row.valueForKey('OrderId').integerValue;
  // Prepare filter to obtain details on given order
  var condition: NSPredicate := NSPredicate.predicateWithFormat('Order == %d', orderID);
  // Get the order total
  var orderSum: Double := self.OrderDetails.rowsFilteredUsingPredicate(condition).valueForKeyPath('@sum.Total').doubleValue();
 
  // Wrap it into an id object and return
  exit NSNumber.numberWithDouble(orderSum);
end;

Conditional cell formatting

It has become common practice to give a slightly different design to each cell depending on the data it represents. For example, the developer can play with font, size, color, etc. All this makes the data more obvious and easy to perceive.

We will use a similar approach for our application. We already have the method tableView() cellForRowAtIndexPath(): UITableViewCell which composes the cell for any table row we want to show.

method ClientsViewController.tableView(tableView: UITableView)
                 cellForRowAtIndexPath(indexPath: NSIndexPath): UITableViewCell;
begin
  var CellIdentifier := "Cell";
  // Try to obtain cached cell
  result := tableView.dequeueReusableCellWithIdentifier(CellIdentifier);
 
  // This is required only if you are targetting iOS 5.1 or lower
  if not assigned(result) then
    // If there is no such cell cached, then just create a new one
    result := new UITableViewCell withStyle(UITableViewCellStyle.UITableViewCellStyleValue1) 
                                  reuseIdentifier(CellIdentifier);  
  
  // Note that we used UITableViewCellStyleValue1 as the UITableViewCellStyle
  // which makes the cell with the value aligned to the left side and the detail value aligned to the right side of the cell
  var tableRow := self.dataTable.rowAtIndex(indexPath.row);
  result.textLabel.text := tableRow['ClientName'];
 
  // Get the count of orders (as you remember, OrdersCnt is the calculated field)
  var ordersCnt: Integer := tableRow['OrdersCnt']:integerValue();
 
  // And depending on the orders count we can use different colors and different icons for the given cells
  case ordersCnt of
    0: begin 
        result.detailTextLabel.textColor :=  UIColor.blueColor();
        result.imageView.image := UIImage.imageNamed('1');
        result.detailTextLabel.text := 'No orders'; 
    end;
    1: begin
      result.detailTextLabel.textColor := UIColor.orangeColor();
      result.imageView.image := UIImage.imageNamed('2');
      result.detailTextLabel.text := NSString.stringWithFormat('%d order', ordersCnt);
    end;
    2: begin
      result.detailTextLabel.textColor := UIColor.magentaColor();
      result.imageView.image := UIImage.imageNamed('3');
      result.detailTextLabel.text := NSString.stringWithFormat('%d orders', ordersCnt);
    end;
    else begin
       result.detailTextLabel.textColor :=  UIColor.redColor();
       result.imageView.image := UIImage.imageNamed('4');
       result.detailTextLabel.text := NSString.stringWithFormat('%d orders', ordersCnt);
    end;
  end;
  
end;

As a result of our efforts above, we now have the following application:

Nougat DA for iOS application

And finally, as a small bonus, this is how it looks in iOS7 ;)

Nougat DA for iOS application iOS7

You can get sources of the sample download here

Thanks for your attention! ;)

Avatar of marc

by marc

“After which no more maintenance releases are planned”. Not.

June 7, 2013 in non-tech, Oxygene, Prism

Our good friends and trusted long-time partners at Embarcadero have recently sent out announcements to make sure that all of our shared Prism/Oxygene customers are fully aware of their future path for continuing using the Oxygene language, coverage of Oxygene updates for the full period of Software Assurance this customers have paid for, and are assured that their technological investment in Prism/Oxygene are savely going forward.

I thought it might make sense to post this message here, to make sure noone misses it.

Dear Embarcadero Customer,

Embarcadero Technologies is pleased to announce the release of Embarcadero Prism XE3.2.

Embarcadero Prism is no longer an included product within RAD Studio as of the XE4 release. Maintenance updates will continue to be provided through August 2013, after which no more maintenance releases are planned.

We wish you success in using this latest Embarcadero Technologies product.

Regards,

Embarcadero Product Management

We want to thank our friends and partners at Embarcadero once again for getting the word out on this, and for letting our shared customers know where to obtain Oxygene going forward, especially beyond August. It goes without saying that we (RemObjects Software) will honor all active SA contracts, on our dime, beyond August. Please contact us if you have any questions.

Data Abstract for Cocoa: New methods for adding rows

June 5, 2013 in iOS, Mac

In the last release we have introduced two new methods in the DADataTable which allows adding new row with data in one go

The first one is public -addNewRowWithDataFromDictionary:inEditMode:

It returns new row with values from specified dictionary which contains key-value pairs with field name as the key and value – as value for given field.

NSDictionary *data = @{
  @"WorkerBirthDate" : date,
  @"WorkerLastName"  : @"Doe",
  @"WorkerPosition"  : @"Boss",
  @"WorkerFirstName" : @"John"
};
 
DADataTableRow *row = [table addNewRowWithDataFromDictionary:data inEditMode:NO];

Since it takes a dictionary, and we know to what field given value belongs, then there is no matter in what order you will put the data – it can differs from order of fields in the table.

This method also perform some basic validation. If you will specify value for field which does not belongs to the table then it throws an exception saying that given field does not exists in the table.

I also need to say few words about adding rows for tables with autoincrement fields. As you might know, when you insert new row to the table with autoincrement key, Data Abstract, at the client side, will provide temporary key value. It is an negative integer value in order not to interfere with existing positive values.

-addNewRowWithDataFromDictionary:inEditMode: method does not allow you to specify custom value for such autoincrement key. Though it does not firbid to change temporary key value before sending an updateData request.

To avoid ambiguity, if you include value for autoinc field to the dictionary then adding new row will throw an exception saying that you cannot specify custom value for autoincrement field.

So general recomendation here will be – If your table has an autoincrement key field then just omit passing its value. It will be generated automatically.

And finally you don’t need to pass values for ALL fields. You can specify only ones you need. It also can be handy for setting defaults.

The second method -addNewRowWithDataFromArray:inEditMode: is less safe. It just takes an array of values for new row. Thus, orders of values here plays the very important role. There is no special validation and checkings of the passed arrays. So you must be sure what you are passing there.

For these reasons, we make this method as internal. You can use it when import proper header file like shown in code snippet below.

The benefit in using this method is in its simplicity and conciseness.

#import <DataAbstract/Internal.h>
...
NSArray *data = @[
   [NSNull null],
   @"Bond",
   @"James",
   date,
   [NSNull null],
   @"Spy"];
 
DADataTableRow *row = [table addNewRowWithDataFromArray:data inEditMode:NO];

As I’ve said, order of values here is important so when I want to skip value for certain field then I need to pass a null object there.

DA SQL Browser is getting better

June 5, 2013 in Uncategorized

Today I want to tell you about a recent change in the DA SQL Browser.
As you might know, it is a tool that comes with our Data Abstract product and allows you to create SQL statements and query your DataAbstract-powered servers by using a DA SQL feature. You can consider it as an SQL development studio, but instead of a database, a server supports DA SQL.

On start, the DA SQL Browser will prompt you to connect to the server with the following dialog:
DA-SQL-Browser-Server-Connection
You can see that several fields are already filled with default values, which will work with a DA Sample Server.
Unfortunately, the login dialog of the DA SQL Browser is not that easy to use when connecting to Relativity Server (after all, the DA SQL Browser was created much earlier than the Relativity project). You have to provide somewhat cryptic “additional login parameters” like Domain=PCTrade Sample;Schema=PCTrade.

Considering this, a new option was introduced, so you can see a checkbox Relativity Server on the bottom of the form.
DA-SQL-Browser-Server-Connection-expanded
When you click it, it gives another drop-down lists to pick a Domain Name and a Schema Name. Note that you can still fill these names manually, but as long as the dialog’s Server URL to the Relativity Server is valid, these lists will have all the domains and schemas you need.

Now, you can connect to the Relativity Server and try some queries and (maybe later) include them in your client application. And I hope the DA SQL Browser will help you with your projects.
DA-SQL-Browser-with-Relativity

Oxygene 6 now includes Oxygene for Cocoa

May 31, 2013 in Guest Post, Java, Oxygene, Prism

Ah, it’s been released… The May 2013 release of Oxygene, released on 27th May 2013, brings us Oxygene 6.0, and Oxygene 6.0 brings us the official release of Oxygene for Cocoa.

The Oxygene language now gives ways of coding for all the currently interesting platforms using the three available editions of Oxygene:

  • Oxygene for .NET (formerly also known as Delphi Prism) – targets the .NET platform, allowing you to build Windows applications, Windows phone applications, Silverlight applications and so on, using the relevant .NET frameworks. Also targets the Mono platform, allowing applications to go to the many places where Mono goes, such as Mac and Linux and also Android and iPhone/iPad using Xamarin.Android (aka Mono for Android) and Xamarin.iOS (aka MonoTouch) using those frameworks.
  • Oxygene for Java – targets the Java runtime, allowing you to build Java apps, Java servlets, Java applets and also, perhaps most interestingly, Android apps. Java apps will use your chosen Java frameworks and Android apps use the Android SDK framework.
  • Oxygene for Cocoa – targets iOS and OS X allowing native ARM applications to be built for iPhone and iPad as well as 64-bit native OS X applications. Applications are built against the native OS X Cocoa and iOS CocoaTouch frameworks.

Oxygene is hosted in Visual Studio 2012 (support for Visual Studio 2010 has now been phased out in Oxygene 6.0). If you don;t have a copy of Visual Studio 2012 the Oxygene installer can set up the Visual Studio 2012 shell first.

For existing users of Oxygene for .NET and/or Oxygene for Java there are some new features added to Oxygene 6.0, including a spate of new conditional defines to help distinguish which compiler built your code or which platform you are targeting:

Oxygene 6.0 edition Edition define Platform define GC/ARC define
.NET ECHOES DOTNET GC
Java COOPER JAVA GC
Cocoa NOUGAT COCOA ARC

However the main thrust of the release is Oxygene for Cocoa, which works in conjunction (if you want) with Apple’s UI designer to support visual UI design via nib (.xib) files or storyboard files. It also understands and fully supports multi-part method names so that it fits in directly with the Objective-C naming system and can represent and refer to any existing methods. It support the iOS Simulator, supports debugging there and on-device and offers all the options needed to sign and provision your apps. It supports ARC (automatic reference counting), understands bridging and uses an LLVM back-end to generate good ARM and 64-bit Intel code.

It ships with all the standard frameworks imported and has a tool that allows you to import any additional libraries you need to work with. Because Oxygene always uses the frameworks that natively exist on the target platforms, there is not an awful lot to learn specific to Oxygene when building Mac or iOS apps. Anything you learn on the Internet about how to build aspects of Mac/iOS apps applies directly – it’s just a case of expressing the various local API calls in the Oxygene syntax, which is a very familiar Object Pascal based syntax.

During pre-release development Oxygene for Cocoa was called Project “Nougat” and I worked with it a lot to keep tabs on how it progressed. I’ve built a whole bundle of test apps to keep on top of (mostly) iOS application development techniques by simply following various online Objective-C tutorials, and just entering the code in Pascal instead of in Objective-C.

I’m delighted Oxygene for Cocoa is now released as I’ve been productive with the tool for quite a long time now. I’ve wanted to make blog posts about how I do thing with it, but given it’s just a syntax shift there hasn’t really been much of a need for it. I guess maybe I’ll do one at some point to show the basics of building up an iOS app in the Visual Studio IDE and getting it launching in iOS Simulator, but after that it’s just writing code in the same way any other iOS developer does; just in Pascal.

On June 17th I’ll be demonstrating the product with a talk at a Developers Group meeting in Maidenhead, UK.

You can find more information about Oxygene for Cocoa at these links:

Buying Oxygene is reasonably pocket-friendly. If you’re new to it then $699 gets you all three versions. Otherwise there is a $499 renewal price for existing Oxygene for Java or Prism customers, a $599 cross-grade price for any users of Embarcadero Delphi or of older Embarcadero Prism versions (XE2 and below) and also a $99 academic price.

If you want to see how you get on with Oxygene 6.0 without committing you can always pull down a trial version first.

Avatar of marc

by marc

Announcing Oxygene 6 and the new Oxygene for Cocoa

May 28, 2013 in .NET, Android, Cocoa, iOS, Java, Mac, Oxygene, Prism, Visual Studio

Hello everyone.

We are more than pleased to announce the release of Oxygene 6, the next major milestone of our Oxygene language. This new version includes a significant update to the existing “Oxygene for .NET” and “Oxygene for Java” editions, but – most excitingly – it also marks the first release version of our all-new Oxygene for Cocoa.

Oxygene for Cocoa is a brand-new edition of our Oxygene language, and it targets native Mac and iOS development with the Cocoa frameworks, using the same great language you already know and love from .NET and Java. We are very excited about Oxygene for Cocoa, and we think it will be a game-changer for how you create apps for Mac and iOS.

Oxygene for Cocoa is a very unique product, in that it is the only language (next to Apple’s own Objective-C) to truly natively target the Cocoa platform and the Objective-C runtime. It gives you access to all the great frameworks and libraries provided by the platform, lets you use all the native UI controls, and generates executables that are lean, mean and blazingly fast – and compiled directly for Intel x64 (Mac) or ARMv7 and ARMv7s (iOS).

Get Oxygene now

Support for all three platforms is available in the new Oxygene 6 package, which is a free update for all active subscribers who bought Oxygene form us since last August. It is available for new users at only $699 (again including all three platforms!), and individual platform support is also included in our Suite Subscriptions for .NET, Cocoa and Java, respectively.

Special renewal pricing is available for existing Oxygene for Java or Prism customers $499, as well as a special $599 cross-grade offer for any users of Embarcadero Delphi or of older Embarcadero Prism versions (XE2 and below).

We’re also for the first time ever introducing a new academic pricing for students, teachers and non-profit researchers, at an amazingly low $99.

And of course, as always, theres a free fully-functional 30-day trial version available, as well.

This is only the beginning

But we’re just getting started with this release and have many further exciting things planned for this year and beyond, including two minor updates for June and July, a significant “6.1” release in Fall, as well as several related products and technologies that will extend the Oxygene ecosystem that we’re not quite ready to talk about yet.

In the meantime, we hope you will enjoy the first release of Oxygene 6.0 and Oxygene for Cocoa – and we’re looking forward to hearing what Apps you will be building with it!

You can learn more about Oxygene at remobjects.com/oxygene and wiki.oxygenelanguage.com.

 

Yours,

marc hoffman
Chief Architect,
RemObjects Software

RemObjects SDK Beginners Guide

May 22, 2013 in .NET, ROFX

Intro

RemObjects SDK is an awesome framework. Not only because its development feeds me and my 10 cats ;) but also because it allows to efficiently create applications on literally a dozen different platforms (to name them: Win32 (a.k.a. Delphi apps), desktop .NET framework, Windows Phone, Silverlight, Mono, Android, Android via MonoAndroid, iOS, iOS via MonoTouch, native MacOS X apps, Java and JavaScript). Unfortunately, it takes a bit of time to get started with developing, you can’t just jump right in. I myself (and most of the software developers I know) usually want to try their new, just downloaded toy without reading a ton of documentation pages.

So this article will try to be a kind of “crash course”. It won’t go very deep (there are Wiki articles on just about anything, if you want to delve in deeper, and our support team will help you with any questions), it will just try to give you some ‘feeling’ for the tech, a foothold to conquer the new framework.

This article covers the .NET version of the RemObjects SDK, however, the main approach will remain the same for all platforms (.NET, Xcode, Delphi, Java, JavaScript), so you won’t waste your time with this article, even if you don’t use .NET in your development work.

My colleagues will provide similar articles devoted to the other supported platforms later this month.

Note: This article covers the ‘Client Calls The Server’ scenario and doesn’t touch the ‘Server Pings The Client’ one. At this moment it is enough to know that the latter scenario is possible as well and its implementation won’t affect the former one.

The Core

The very heart of the RemObjects SDK is based on ChannelsMessagesEnvelopes and Services. Two more components used under the hood are Interfaces and Invokers. Don’t be afraid of these words, things are actually simpler than they look.

Let’s take a look at the ‘Client calls the server method’ scenario:

var methodCallResult = sampleService.DoSomething();

Looks simple, doesn’t it?

Here’s what happens from the RemObjects SDK’s point of view:

The client code calls the Foo method of some object serverService. Here, sampleService is an instance of the auto-generated proxy class, so calling the sampleService.DoSomething() method actually means the following:

1. Sending out a request
The Interface class serializes the request to the server using the configured Message. The Message is then wrapped by the attached Envelopes, if any are set up (f.e. data is encrypted somehow). Then the resulting data package is sent over the wire by the Client Channel.

2. Processing the request on the server side
The Server Channel retrieves the data package and pushes it to the Message component. Message unwraps it using the attached Envelopes, if needed. The resulting data package is provided to the Invoker, which reads the requested service, method names and method parameters from it.

Then the Service method is invoked, which does the actual job.

After the service method has finished, its result (or any exceptions occurred) are serialized, wrapped, and sent back over the wire using the Server Channel (yes, the processing pipeline is similar to step 1).

3. Retrieving the response
The Client Channel retrieves the data package, unwraps it and provides the serialized data package to the Interface‘s method that initiated the remote service call. This method then deserializes the provided data package and provides the method result back to the user code.

RemObjects SDK Overview

The magic is that the entire process is transparent for the user code on both ends of the wire and doesn’t require much attention from the developer. While the service method call pipeline might seem complicated (or even over-complicated), its performance overhead is negligible (especially for the binary serialization-based Message), making the actual network speed the main issue to care about, not the inner RemObjects SDK processes.

Sample Server

Let’s create a sample server and client app in a step-by-step guide and see how the ChannelsMessagesEnvelopesInterfacesInvokers and Services entities are implemented in a real RemObjects SDK-based application.

Prerequisites

For this tutorial you’ll need Visual Studio and either the RemObjects SDK for .NET or the Data Abstract for .NET frameworks installed. Also, a minimal knowledge of C# is required, but the same concepts would apply to Visual Basic for .NET, Oxygene or any other .NET language.

Server Application

As mentioned above, the server application should contain the Server ChannelMessageEnvelope (if needed) and Invoker, as well as the Service itself.

1. Create a new Class Library project named BusinessLogic and add a single class to it:

using System;

namespace BusinessLogic
{
    public class StringProcessor
    {
        public Int32 Process (String value)
        {
            if (String.IsNullOrEmpty(value))
                return -1;

            return (value + @"Secret Salt").GetHashCode();
        }
    }
}

This project imitates an already existing implemetation of a real-world business logic method that should be exposed to remote client applications. While it is not necessary to put the business logic into a separate project, it was done here to emphasize that the business logic layer is fully separated from the to-be-implemented communication layer.

2. Add a new Windows Forms project to the solution and name it SampleServer. Of course, a real-world server application should be running as a Windows Service (and RemObjects SDK provides the needed application template), but for this “crash course” it will be easier to use the simple Windows Forms project.

3. Add the following references to the SampleServer project, as they provide the needed classes:

  • RemObjects.InternetPack.dll
  • RemObjects.SDK.dll
  • RemObjects.SDK.Server.dll
  • RemObjects.SDK.ZLib.dll

Also add a reference to the previously created BusinessLogic project, as we will expose its methods in the server.

4. Now we need to define the Server Surface Area, i.e. the service name, its methods, their parameters and return values, etc. This step is needed to allow the RemObjects SDK to generate strongly-typed Interface and Invoker classes.

Add a new ‘RemObjects SDK Service Definition’ item to the project.

Adding New Item

A new file named NewLibrary1.RODL will be added to the project and the Service Builder app will be started automatically. The RODL is an XML file containing the service definition written in the ‘RemObjects Definition Language’ (or RODL), and the Service Builder provides the GUI to edit .RODL files without diving into the definition language syntax. Please note that the RemObjects SDK exposes the object model that allows to load, parse and generate .RODL files (and even to generate code based on these files), but this topic is outside the scope of this article.

Service Builder

As you can see, the file is almost empty. Select the single topic in the tree on the left side of the app’s window. The edit boxes that will appear will allow you to change the library name, set its namespace or even write its definition. Set the Library name to BusinessLogicLibrary.

Library contains all the entities in the given RODL file. Consider it as a root of a service definition tree.

The next step is to define the Service. Press the ‘Service’ button (or right-click the Library name in the tree and issue the ‘Service’ context menu command) and rename the just added Service to BusinessLogicService

Now we can define this service’s methods. Press the ‘Add Operation’ button (the one with the green “+” glyph). A new method named ‘NewMethod’ will be added. Double-click its definition and change the method’s name to Process.

The last step is to define this method’s parameters and set its return type. Press the ‘Add Parameter’ button and change the parameter’s name to ‘value’. Change the parameter’s type to Utf8String (the ‘Data Type’ editor allows to select a type name from a combo box, so there is no need to enter it manually).

Set the Result type to Integer (the type name can be selected from the combo box as well).

If everything was done right, the Service Builder window should now look like this:

Service Definition

Close the Service Builder.

Set the ‘Build Action’ of the just added RODL file to ‘Embedded Resource’, so it will be embedded into the compiled application. You will find out why this is needed below.

5. As you can see, once you closed the Service Builder, three new code file were added to your project: BusinessLogicLibrary_Intf.csBusinessLogicLibrary_Invk.cs and BusinessLogicService_Impl.cs.
BusinessLogicLibrary_Intf.cs contains the Interface classes, BusinessLogicLibrary_Invk.cs contains the set of Invoker classes and BusinessLogicService_Impl.cs is a blank Service implementation class.
There is no need (and it is NOT recommended) to edit the code in the first two files.

In case you change the RODL file (for example add one more method to the service definition), the *_Intf and *_Invk files will be regenerated automatically to reflect the RODL changes. At the same time the _Impl file will stay untouched to prevent any code loss. Since the service implementation class contained in the _Impl file implements the service interface contained in the _Intf file, the service project won’t be able to build until the Service implementation class will match the Service definition.

For example: If you add a method to a service definition, the interface representing this service in the _Intf file will contain the new method definition as well. And because the Service implementation class has to implement this interface, the developer will have to add the corresponding method implementation to the service definition class.

6. Open the Service Implementation file (i.e. BusinessLogicService_Impl.cs) and find the Process method implementation. It is empty, so change it to

public virtual int Process(string value)
{
    return (new BusinessLogic.StringProcessor()).Process(value);
}

At this time, we have defined and implemented a Service (and it probably took more time for you to read the text above than to actually execute the steps in Visual Studio). Now we need to make the service available remotely.

7. Below, we will manually implement the network connectivity layer using the RemObjects SDK components. This is done to demonstrate the ins and outs of the framework as the RemObjects SDK provides the application templates and (starting from the May 2013 release) the pre-implemented NetworkServer class that allows to implement the connectivity layer in literally 3 lines of code.

Open the main form in designer mode (remember that our server app is intentionally primitive, so no properly layered architecture or ‘Run As Windows Service’ support here):
* Add the IpHttpServerChannel and BinMessage components to the main form (note that a licenses.licx file was automatically added to the server app project. Please do not delete this file).
* Open the properties of the IpHttpServerChannel component and open the custom editor for the Dispatchers property.
* Press the ‘Add’ button and select the previously added BinMessage instance as a value for the Message property.

Channel Properties

* Press OK to close the dialog and save the property’s value.

That’s it. The server message processing pipeline (i.e. the Server Channel and Server Message) is set up.

8. Open the code-behind file of the main form and add this code line to the very end of the main form class constructor:

this.ipHttpServerChannel1.Open();

This code line will ‘open’ the server channel so it will start to accept the incoming connections.

Now you can start the server app. Open a web browser and go to the page http://localhost:8099/rodl. The server app will show the contents of the embedded RODL file at this address. Note that you can always set the the ’Embedded Resource’ property to None for the RODL file and the server will not advertise its methods.

Client Application

Even the most advanced server application is useless if there is no client application for it. So… let’s create one!

If you remember, a client application needs the following components implemented: ChannelMessage, (possibly) Envelope and Interface. This may look scary again, but it will be much easier than it sounds.

1. Create a new Console Application (for simplicity reasons).

2. Add references to the assemblies

  • RemObjects.InternetPack.dll
  • RemObjects.SDK.dll
  • RemObjects.SDK.ZLib.dll

These assemblies provide the client connectivity classes (as you can see, there is no need to reference the RemObjects.SDK.Server.dll assembly).

3. Now issue the ‘Add’ -> ‘Existing Item’ command (available via the context menu for the client application project entry in the Solution Explorer).

4. Select the BusinessLogicLibrary_Intf.cs file (it can be found in the server’s project folder) and add it as a link.

Adding the _Intf file as a link has a little but important advantage over simply adding an existing file to the client app project: when the server RODL is changed, the _Intf file is automatically regenerated. If this file is added as a link, there will be no need to update the _Intf file copy contained in the client app project.

This step adds the Interface part of the client app.

4. Add the following code to the Program.cs:

using System;

namespace SampleConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.Write("Enter string: ");
            String value = Console.ReadLine();
            Console.WriteLine();
            Console.WriteLine("Processing...");

            // Communicating with the server
            SampleServer.IBusinessLogicService service = new SampleServer.BusinessLogicService_Proxy(@"http://localhost:8099/bin");

            Int32 hash = service.Process(value);

            Console.WriteLine();
            Console.WriteLine("String entered: {0}", value);
            Console.WriteLine("String hash: {0}", hash);
            Console.WriteLine("Press ENTER to continue...");
            Console.ReadLine();
        }
    }
}

The Console.WriteLine and Console.ReadLine calls here are pretty usual for any console application. Let’s take a closer look at these code lines:

// Communicating with the server
SampleServer.IBusinessLogicService service = new SampleServer.BusinessLogicService_Proxy(@"http://localhost:8099/bin");
Int32 hash = service.Process(value);

Here, a proxy for a server app service is created and then a service method is called (the Channel and Message components are automatically created behind the scenes to make this possible).

The IBusinessLogicService interface lists all methods exposed by the remote service, while the CoBusinessLogicService.Create static method creates a proxy class that implements this interface. This makes it possible to perform calls to a remote server transparently for the client app’s code.

5. There are probably some explanations needed regarding where the “http://localhost:8099/bin” URL came from. Let’s take a closer look on each part of the URL:

  • http – Protocol used by the server channel. In this sample, we use a simple HTTP channel. The RemObjects SDK supports several other communication protocols as well (f.e. TCP-based ones).
  • localhost – Name or IP address of the server’s host.
  • 8099 – Port the Server Channel is listening to. 8099 is the default port for the IpHttpServerChannel used in our server application.
  • bin – So-called dispatcher name. This is the name of the Message on the server side that processes the incoming data package. bin is the default name for the BinMessage.

6. Build and start both the server and client applications. Enter any string into the client application window and see the result returned by the server app:

Client Application

Conclusion

At this point you should have a basic understanding of how the RemObjecs SDK-based communications can be implemented. As an exercise, try to add one more method to the Service and call it.

This article doesn’t cover many (or even most) of the RemObjecs SDK features. Server Events, Envelopes, client authentication processing and SSL support were not covered for simplicity reasons. Search our Wiki for the questions you are interested in. If for some reason you can’t find the info you need, don’t hesitate to call on our support via RemObjects Connect or email to support@remobjects.com.

Avatar of marc

by marc

…then i might as well learn Java?

April 23, 2013 in .NET, Cocoa, Delphi, iOS, Java, Oxygene, Windows

One of the most frequent comments i hear when people dismiss or decide against considering Oxygene as their development tool of choice goes along the lines of the title of this blog post:

“With Oxygene i need to learn all the new platform APIs. If that’s the case, i might as well learn C# [or Java or Objective-C].”

That’s certainly true. When moving to and learning a new platform, there’s a vast number of things to learn — new classes, new APIs, new concepts, new ways of doing things. Learning a new language, especially if it’s one from the same broader family of languages you already know (i.e. Object Oriented languages) is only a small and insignificant part of that.

But, i think it is missing the point of Oxygene, to think its whole reason d’être is to save you from learning a new language. Quite the contrary.

Oxygene is based on Object Pascal, and is, at its root, very close to the “Delphi” language (which basically represents the state-of-the-art of Object Pascal ca. 2003). The main reason for that is not that Delphi developers (which the creators of Oxygene were too, at the time) do not have to learn a new language. The reason for that is that Pascal — as much as it has gone out of fashion over the past 20 or so years — is a freaking amazing base point for a programming language. It’s clean, well structured, easy to learn, and — very importantly — easy to read.

Many developers underestimate this, but they spend a lot more time re-eading their (and other’s) code than they originally spent writing it — so having a language that makes code easy to parse and understand by the human brain is a very important and undervalued feature of a language. One that Oxygene shines at like no other.

So that’s the why Oxygene is what it is, but is that enough reason to choose it over C#, Java or even Objective-C? No, of course not.

The biggest selling point for Oxygene in my opinion is not that it’s Pascal based, and is not that is allows you to natively compile for today’s three major platforms (.NET, Java and Cocoa) with the same code base, and it most certainly not that it saves you from doing anything (be it learning a new language, or be it spending more money on a more expensive development tool).

The biggest selling point of Oxygene is — quite frankly — that it is an amazing modern language, with features that developers using the other mainstream languages don’t even begin to dream about.

Going into details on all the features that make Oxygene unique and powerful, the features that will change your life as a developer, would require several posts on its own. But the scope ranges from Class Contracts to language-integrated parallelism, from nullable types to the amazing Future types, from small but powerful things like the colon operator and double boolean comparisons to “for” loop expressions (not to be confused with regular “for” loops), and from duck typing to language-native tuples.

The list could keep going on.

So when you’re looking at Oxygene (and i know you are), don’t just look at it from the perspective that it will let you keep coding in Pascal without having to learn a new language. Sure, that’s a big factor too. If you’re a Delphi developer, you probably love Pascal (like we do), and have been using it for the past 10, 20 or even more years. And being Pascal certainly is one thing that makes Oxygene attractive to you.

But don’t stop there; you’re doing Oxygene and yourself an injustice, if you look at that as the main benefit.

Instead, think of using Oxygene as switching to the most powerful and modern object oriented language out there, today. That it’s Pascal-based is just the icing on an already very delicious cake.

Avatar of marc

by marc

Prism XE4, Where Art Thou?

April 17, 2013 in Oxygene, Prism, Uncategorized

Update: (May 26, 2013) We have an official FAQ for the migration of Prism licenses to Oxygene available now at remobjects.com/oxygene/prism.

Ok, so the cat is out of the bag, if a few days ahead of schedule: starting with the upcoming release of XE4, Embarcadero Prism will no longer be part of the RAD Studio SKU, and there will be no “XE4″ branded edition of Prism.

But worry not. As you all know, Prism has been nothing more than a re-branded version of our Oxygene for .NET product — and Oxygene will keep going on, stronger than ever.

In fact, Oxygene has long outgrown its Prism-branded edition, first when we introduced full native support for Java and Android to the language over 18 months ago, and of course with our upcoming support for truly native iOS and Mac apps, shipping next month.

So “Embarcadero Prism” as a product is going away, but the Oxygene language you have come to love and depend on will continue to shine and evolve, as it always has.

What exactly does all of this mean?

We believe that in the end, this change will be a net positive for Oxygene.

When we first started working with Embarcadero in 2008 to bring Oxygene 3.0 into RAD Studio, Embarcadero had a gap left in their lineup with the discontinuation of their ill-fated Delphi for .NET product. Both companies shared a vision of Delphi and Oxygene — then getting branded Delphi Prism — becoming two sides of the same coin: two languages evolving together and influencing each other to push Pascal forward both for CPU-native Windows development and for managed targets.

Over the years, it turned out that this was not happening, and as Embarcadero was shifting their focus to “(CPU-)native, native über alles” and onto FireMonkey, Prism (and with it Oxygene, as i’m going to start referring to it from now on exclusively) became the odd man out — the product that was there, as part of RAD Studio, but no-one liked to talk about, because it did not really fit the vision of the company.

This became clearer as Oxygene evolved.

We added support for Java and (more importably) Android, but Embarcadero had their own (very long term ;) vision of how they wanted to pursue the platform that conflicted with what Oxygene had to offer. As a result, Oxygene was forced into a split personality — with Oxygene for .NET remaining under the Prism umbrella, and Oxygene for Java becoming a separate product (for a while).

At the same time, Embarcadero became less and less interested in actually marketing and promoting the product, and it was being relegated to a “filler” to pad up RAD Studio as a worthwhile product suite.

Things got even more complicated when we started working on “Nougat”, our vision for really and properly bringing Object Pascal and Oxygene onto the (misleadingly named) Objective-C runtime that is the engine behind iOS and Mac. Once again, Embarcadero had different plans for the platform, and what is more, they — understandably — raised the concern that Oxygene for Cocoa would be too direct a competitor to their efforts on iOS (albeit once again our two companies were following two very different visions).

To wrap things up short and sweet, as of right now, Oxygene is finally standing on its own two feet again.

During the five years of partnership, RemObjects Software has always been the sole technical contributor to the core Oxygene product, and having Oxygene “back to ourselves” really just means one thing: that we can, more aggressively and consistently, continue to drive the product on all three target platforms, according to the vision we have for it. And trust me, we have some amazing things planned for 2013 and 2014, with “Nougat”, our Mac and iOS support, only being the tip of the iceberg.

What does this mean for existing customers?

Worry not. We have every eventuality covered.

First of all, if you already bought Oxygene directly from us or one of our reseller (i.e. without an Embarcadero serial number), none of this will affect you at all, you’re already set.

If you’re an Oxygene user from the Embarcadero side of the fence, now more than ever, make sure you register your XE2.x or X3.x serial number with us. This way, we know about you and can take care of you moving forward.

Once you have registered your serial, you can take advantage of our special renewal price for Prism customers and renew to a full Oxygene package licensed directly from RemObjects Software, for only $349. Remember, this not only renews you for future updates to Oxygene for .NET (the product you have now), but it also gives you the Java/Android and Mac/iOS targets, as well!

If you have active software assurance (SA) with Embarcadero that covers Oxygene, that will of course be honored. Up until August (i.e. one year from when XE3 shipped), you will continue to receive the latest updates to Oxygene for .NET from Embarcadero. This will (assuming your SA is still active at the time) include the upcoming major 6.0 release, next month.

Once your current SA expires, renewing it will not include renewed access to Oxygene, but you can use the link above at any time to renew to the full Oxygene package from us. (Note that the current renewal price of $349 is a special offer and will increase slightly once “Nougat” ships next month.)

It’s probably unlikely that you’re buying RAD Studio XE4 “fresh” without already being an existing RAD Studio user, but if you do, i’m afraid you will not receive “Prism XE4″ as part of it. You (and every other Delphi user) can use our special cross-grade offer to purchase a full Oxygene package from us, at $399 (this is also a special offer, and the price will increase slightly once we ship 6.0 next month).

In Summary

As the old saying goes, The King is dead, long live the King! Embarcadero Prism is no more, starting next week, but Oxygene is going stronger than ever.

We, and i personally, are incredibly excited about Oxygene, and about the things we have planned thru-out the rest of the year and beyond. We can’t wait to walk down the road ahead with you.

yours,
marc hoffman
Chief Architect & Oxygene Team Lead
RemObjects Software