Today

The Beauties of Objective C

 

 

 

High resolution image loading in iPhone4/4S is easy in native SDK, so that is why we wanted to support that simplicity in MobiAccess. However, we ran into some problems implementing that simple solution.


The @2x image loading in the iOS SDK is supported only if we load the image with the [UIImage imageNamed:fileName] method.

But in MobiAccess, creating images can only be done from NSInputStream, for example:


Image.FromStream(Resources.GetResourceAsStream(fileName)).


This actually creates an NSInputStream and passes it as a parameter to the Image Constructor, which reads it and creates the image with [UIImage imageWithData:data]. The problem with that at this point is that we do not have a clue as to where that NSInputStream points to. Without knowing the filename, we cannot use the native support for @2x image loading.


The MobiAccess virtual machine has a complex and strict class hierarchy, so it is not easy to make modifications in the VM itself without implementing the modification on all platforms.

In this case, we needed to attach an NSString (the filename) to the NSInputStream, without adding a new field or subclassing it.

We wanted to solve this in a very clean way and objective C's associative references popped into my head. I read about it in a book called iOS5 Programming: Pushing the Limits by Rob Napier and Mugunth Kumar. Altogether it is a very informative and intriguing book.

According to the book, associative references are used to attach key-value data to any NSObject.

 

In order to use associative references, we need to import objc runtime:

 

#import <objc/runtime.h>

 

 

This is how we associate the input stream with the filename using key pathKey:

 

/*

     Attaching the fileName to the stream with association. This is required because we need the filename in Image.FromStream in order to load the @2x images for iphone4 properly

     more info: http://developer.apple.com/library/IOs/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocAssociativeReferences.html

     */

    objc_setAssociatedObject(is, &pathKey, fileName, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

 

And this is how we get back the associated filename:

 /*

     We associated the filename with the inputstream in Resources.GetResourceAsStream(), in order to be able to load the @2x images for iphone4 here.

        [UIImage imageNamed:fileName] automatically loads the highres version of the image if available.

     */

    

    NSString* fileName = objc_getAssociatedObject(is, &pathKey);

 

You can see OBJC_ASSOCIATION_RETAIN_NONATOMIC enum is used as third parameter in the setter. Associations have proper memory management, and they are freed when the object is being freed so you do not have to worry about it.

 

Written by PS

iPhone4/4S High Resolution Image Loading in MobiAccess

 

 

 

If you have been developing native iOS applications, you are probably already familiar with the @2x trick for high resolution image loading.

 

Basically, when you are positioning elements on the  iPhone's screen, you are not positioning to pixels, but to points. Thus, every iOS window has a scale factor. This factor is 2x for iPhone4/4S and 1x for iPhone 3G/3GS.

 

Although this is an amazing idea, if you look closely at a 320x480 image on the iPhone4, you will see it's pixellated. This is because iPhone4 has a resoultion of 640x960. To solve this problem you need to load a higher resolution image on the iPhone4/4S. This can be done without a single line of code.

 

If, for example, you have ’mobiaccess.png’ in your project and you are displaying the image in a PictureBox, you can include This e-mail address is being protected from spambots. You need JavaScript enabled to view it in the project and it will automatically get loaded on iPhone4/4S, an almost effortless solution for the issue.

 

Written by PS

How to use custom font size in MobiAccess

 

 

 

 

The Code:

class : Form

{

    private function Init() : Void;

    public CI()

    {

        super();

        this.Init();

    }

    Init

    {

        var label  : Label = Label.CI();

        this.AddControl(label);

        label.SetText("hello");       

        var fontSize : Object = 50;

        label.SetFont(Font.CI(EFontFace.DEFAULT, [EFontSize]fontSize, false, false, false));

        label.SetPosition(LTWHPos.CI(0.0,300.0, 200.0,100.0));

        return;

    }   

}



Explanation:

Instead of using one of the values of the enum EfontSize (MEDIUM, LARGE, SMALL), we can use a little trick to create our own font size object with, let us say, a font size of 50:

var fontSize : Object = 50;

then with this parameter we call the SetFont method, cast on the appropriate type:


label.SetFont(Font.CI(EFontFace.DEFAULT, [EFontSize]fontSize, false, false, false));

The FontSize object has to be drawn into a variable, because the [EFontSize][Object]fontSize casting trick does not work (I also tried it that way first :) )


Anyone finds out about this, I wasn’t the one who told you. :)

 

Warning: The trick above only works on Android platform

Written by SJ

Hashtable Point of Interest

 

 

 

 

While working on the development of a relatively simple navigation/tab control I have come accross the following issue:

Navigation control contains buttons on the navigation bar, and by clicking on them the appropriate panel appears.
 

I wanted to save which panel appears by clicking a certain button in hashtable.
 

The button was supposed to be the hashtable’s key, while the panel its value.
 

Although my solution worked perfectly in the MobiAccess emulator, on Android phones a "java.lang.NullPointerException - null" error message appeared when I tried to add the button-panel pair to the hashtable: hashtable.Add(button, panel);

AnalytiX - How to easily execute a drill operation on an OLAP cube with data pre-filtering

 

Recently I have come accross the following issue: I had to solve a drill operation in the easiest possible way in the case of a mobile application that uses WebService and MDX calls to communicate with an MSSQL Analysis Service operating an OLAP cube.

 

In itself, the drill function can be solved with relatively simple commands during the MDX call with the help of the DESCENDANTS method call. The only issue in this case is that the call returns all the members (data) found on the given hierarchy-level along the chosen dimension. What caused most of the deliberation was how to use the DESCENDANTS method in a way that it returns the values in summary at the given hierarchy level for a defined set of data. The easiest possible solution for this issue was CREATE SUBCUBE.