FMX XE4 Update 1 – Form Event onActivate Problem unofficial fix

After installing XE4 Update 1 a small problem added on the Firemonkey Form Event onActivate. The Event onActivate is not fired correctly anymore. See also my QC Report and also a other QC Report on the Embarcadero Website. After analyzing the changes in the FMX Sources i found the problem and i fixed it. Patching FMX.Forms.pas works now fine with Update 1 procedure TCommonCustomForm.Show; var ScreenService: IFMXScreenService; begin if not (csDesigning in ComponentState) and TPlatformServices.Current.SupportsPlatformService(IFMXScreenService, IInterface(ScreenService)) then begin case FPosition of TFormPosition.poScreenCenter: SetBounds(System.Round((ScreenService.GetScreenSize.X - Width) / 2), System.Round((ScreenService.GetScreenSize.Y - Height) / 2), Width, Height); end; end; if FFullScreen then begin SetFullScreen(True); FFullScreen := False; end ;  FVisible := True; // Add line as in XE4 before Update 1 FWinService.ShowWindow(Self); // FVisible := True; remove this line DoShow; end; Now onActivate works fine
Read More

FireDAC Update 2 available

Embarcadero released a new Version of FireDac for XE4 users direct download Link to Files you find here: LINK Change Log: ============================================================ v (28.05.13) + added: ADDataSet: EmptyView method to delete all filtered records – fixed: ADDataSet: AV when dataset serialization failed at stream creating – fixed: ADDataSet: TField.Required may be True for a …
Read More

Read More

Read More

Give in to the ARC side

I thought I’d take a few moments (or more) to answer some questions regarding the just introduced Automatic Reference Counting (ARC) mechanism to Delphi on mobile platforms (namely iOS in XE4, and Android in a future release). Among some sectors of our customer base there seems to be some long-running discussions […] … Read More

Read More

If you are an EDN Mobile user, you should upgrade

I have been porting many of my DataSnap REST services from using dbExpress for its database access, to take advantage of the FireDAC data access framework. As a side-effect of this, I’ve had to make a change to the EDN Mobile application to handle a slight difference in datatype in some of the datasets it remotes to clients. In particular, the My Member Services and My duplicate accounts functionality may no longer work as intended with EDN Mobile versions 1.1.4 and prior once I upgrade the REST server. I intend to upgrade the REST service that EDN Mobile consumes one month from today, so you should have plenty of time to upgrade to the latest version of EDN Mobile (currently 1.1.5). The new version should consume the existing  REST service with no issues. This upgrade also fixes a bug with the way auto login authentication details were stored, so if you are encountering issues in this area, this upgrade will be beneficial to you. Share This | Email this page to a friend
Read More

Full Text Search Functionality in Delphi Applications – Implementation Idea

Ah … real world problems require some proof-of-concept almost-finished implementation solutions. This time I’m into figuring out what would be the best way to introduce full text search in one of my Delphi applications. “Setup” There’s a Delphi application operating on files. Files are located in various sub-folders and, with 99% certainty, files will not […] … Read More

Read More

Macs compatible with OS X Mavericks

Apple just announced OS X Mavericks and it brings some cool new features. Now come the question “Is my Mac compatible with OS X Mavericks”, below a list of Macs that will be able to run the new OS: iMac (Mid-2007 or later) MacBook (13-inch Aluminum, Late 2008), (13-inch, Early 2009 or later) MacBook Pro (13-inch, Mid-2009 or later), (15-inch, Mid/Late 2007 or later), (17-inch, Late 2007 or later) MacBook Air (Late 2008 or later) Mac Mini (Early 2009 or later) Mac Pro (Early 2008 or later) Xserve (Early 2009) Also, the computer needs to be running Mac OS X 10.6.7 Snow Leopard or higher, with 8GB of free disk space for installation. Essentially, that’s the exact same computer and specification requirements as Mountain Lion required—so if you installed that, you can be confident that Mavericks will run on your machine. — Apple Insider Andreano Lanusse | Technology and Software Development Follow me on Twitter: @andreanolanusse Related posts: iPad the new Apple Tablet AKA (Big IPHONE) :) Software Development, technologies and other matters #3
Read More

10 Tips For Delphi Users

Working on some Delphi projects with some clients over recent weeks has thrown up a number of tips that have been well-received so I thought I’d write them up for a more global audience.

1) Running apps from network shares

Sometimes people like to put executables on network drives and run them from there – it allows potentially many users to launch a single executable. However if the program is running and the network connection breaks there is a more than reasonable chance that the program will crash is a quite ghastly manner, understandably enough.

Given users are at liberty to launch there apps like this it may be an idea to make habit a simple step that alleviates the aforementioned crash scenario. You can have the Delphi linker set a special bit in a 32-bit Windows executable header to instruct Windows that in the event of being launched off a network drive the executable should first be copied to the local paging file and then be launched from there. This flag was introduced in Windows NT 4.0 and described in this old MSJ article by Matt Pietrek from 1996.

This is quite straightforward. You can do this with a compiler directive in the project file or you can change the linker setting (at least in recent versions of Delphi).

To change the project file, you must make sure that Windows (or Winapi.Windows, if you prefer) is in the uses clause and then add in this compiler directive after the uses clause:


To set the linker option directly, open the project options dialog (Ctrl+Shift+F11), go to the Linking options, ensure you are looking at options for a 32-bit build configuration and then give a value of 2048 to the Set extra PE Header flags option. This is passed along to the compiler as the --peflags:2048 command-line switch and does the same thing.

You could work out the value to pass along yourself by looking in Winapi.Windows.pas and seeing that IMAGE_FILE_NET_RUN_FROM_SWAP has a value of $800, which in decimal in 2048.

Update: Just to clarify some points that have come up in comments, this linker setting does not affect operation of the program in terms of how .ini files shipped alongside the .exe get loaded or what the value is returned by Application.ExeName.

2) Inspecting an item in a TList

The old TList class is still a useful beast, even if in many cases we should be using the newer generic TList<T>. TList is useful when the list will potentially contain objects of different types, with suitable backup code that knows to check the type and cast appropriately.

In the debugger, if you want to inspect an item in a TList things can be a bit of a challenge. When you inspect your TList variable (Alt+F5) you get a debug inspector that hints at the items contained therein in its FList field.

If you right-click on FList and choose Descend (or Ctrl+D, to make this inspector inspect that field) or Inspect (or Ctrl+I, to launch a new inspector showing that field) you’ll see the addresses of the items in the list.

These aren’t much use though; being as this is the type-unsafe general TList these values are just pointers. Indeed if you look in the definition of TList you’ll see this FList field is a TPointerList – an array of pointers.

So what do we do to inspect the item underlying a pointer variable? Well, we cast the pointer to the right type and inspect that. To work out what type that is, add a watch that casts the address shown in the inspector to a TObject and call its ClassName method – don’t forget to ensure the watch is set to allow side effects and function calls when adding it.

This tells you the type. Now you can bring up an inspector for the currently unhelpful point by selecting it in the inspector and pressing Ctrl+I, or maybe just double-clicking it.

Then you can apply the typecast by right-clicking and choosing Type Cast… or pressing Ctrl+T, and entering the target type of TFoo (in this example’s case). And then you have what you sought:

For bonus points you can identify the target type in the CPU window’s memory pane rather than the watch window. Invoke the CPU window with Ctrl+Alt+C and pay attention just to the memory pane at the bottom left. In recent IDEs you can also just invoke a solitary memory pane using View, Debug Windows, CPU Windows, Memory 1 (Ctrl+Alt+E) or Memory 2 (Ctrl+Alt+2) or Memory 3 (Ctrl+Alt+3) or Memory 4 (Ctrl+Alt+4).

In the memory pane, firstly have the memory displayed in 8 byte chunks of data by right-clicking and choosing Display As, DWords.

Now right-click again and choose Go to address… (Ctrl+G) and enter a suitable expression based on the pointer value. In the case above the first pointer in the list had the value $27E2C20. This is an object reference – the address of an object’s instance data. So if we de-reference the pointer we’ll be at the start of the instance data. But the address of the class name string is a little way into the instance data, a distance given by the constant vmtClassName, so the required expression will be:


As mentioned, we’re now looking at the address of the class name, which is stored as a short string. To follow (de-reference) this address, right-click on it and choose Follow, Offset to Data or press Ctrl+D. This takes us to the information we seek: TFoo.

If you wish you can change the display back to bytes (right click, Display As, Bytes) and then the short string is more obvious – you can see the length prefix byte for the 4 character string is indeed 4.

3) Loop failure iteration detection

You’ve doubtless encountered this scenario while debugging. There’s an issue in a loop. The loop executes *loads* of times but you need to look into the problem so you need to know how many times round the loop the problem occurs. Stepping through the loop, or using a breakpoint and pressing F9 or clicking on the last line of the loop and pressing F4, counting in your head – all such options are mind-numbing and hugely prone to losing count or messing up in some regard, so how about letting the system work it out for you?

Place a breakpoint at the end of the loop with a massive pass count – say 1000000. Now run the app and make the problem occur. Now look in the breakpoints window and check the current pass count – it will tell you how many times the breakpoint has been passed without actually breaking.

Once you know how many iterations it has been through, modify the properties of the breakpoint and set the pass count to that value. Restart the program and the when the breakpoint triggers the error will occur on the next iteration of the loop. Nice!

4) Breakpoint logging

Breakpoints had their advanced properties added many, many versions ago. You can use advanced breakpoint properties for a variety of cunning debugging scenarios, but a simple usage is to enable cheap logging without writing additional code statements.

Wherever you want to log some information, add a breakpoint and bring up the breakpoint properties. Press the Advanced button, set the breakpoint to not actually break and then specify the log message. For bonus points you can also choose to have an expression evaluated and (optionally) logged at the same time.

This log information will be added to the Event Log window during your debug session in the same way that OutputDebugString messages are, but with the benefit of not having written any code. If you have the IDE set to save your project desktop then the breakpoints will be saved when you close the project and reappear next time you open it.

5) Leaving RTL assembler code

When stepping through code with Debug DCUs enabled you often inadvertently end up in RTL assembly code. In most instances Shift+F8 (Run, Run Until Return) will run the rest of the code through and take you back to where you were so you can try F7 again.

Shift+F8 doesn’t always work. For example if you use F7 on a call to a dynamic method you end up in the System unit’s _CallDynaInst routine. This doesn’t exit in the normal manner, but by jumping off to the located method address stored in the ESI register.

The best way forward here is to click on the JMP ESI line, press F4 to run up to that point and then press F7 – that will take you into the dynamic method that was called.

6) Find declaration while debugging

Seasoned Delphi developers know that you can locate the definition of a symbol by right-clicking it in the editor and choosing Find Declaration. Rather annoyingly there is no shortcut listed next to it, but it is commonly known that if you hold down Ctrl and wave your mouse around the editor, anything that the IDE thinks it can locate the definition/declaration of turns into a hyperlink – this Ctrl+click hyperlink feature is Code Browsing and links to the Code Browsing History keystrokes of Alt+← and Alt+→ that allow you to go back and forth though the links you’ve clicked.

The problem with Ctrl+click is that it doesn’t work in a debug session. Many times it would be handy to find the definition of a symbol in a debug session but Ctrl+click just doesn’t cut it. Fortunately, however, Alt+↑ *does* work in a debug session (yay!)… (or at least should do – it generally does for me). Why Alt+↑ isn’t listed in the editor context menu against Find Declaration baffles me. It’s a very little-known but useful shortcut.

7) Non-destructively locally disable a compiler option

Often-times a build configuration has range-checking enabled to ensure problems show up when they occur as tangible issues rather than vague Access Violations through memory overwrites way down the line during an execution. That said, it can still be important to selectively turn off range-checking for specific small sections of code that are valid, but will flag up range-check errors thanks to, say, the pointer types involved.

Clearly you can turn range-checking (or overflow-checking or whatever) off and on using local compiler directives, as in:

//code that requires range-checking off

but what about if you then build the code with a build configuration that has range-checking globally disabled? This use of compiler directives means the file in question will have range-checking *enabled* from that point onwards, despite the intent being to have it disabled throughout the project.

This is where this tip comes in. You can selectively change a compiler option using code like this, where this example disables range-checking if it was enabled, and then ensures it gets enabled again if appropriate:

//code that requires range-checking to be disabled

Here we define a conditional symbol if we toggle range-checking off, and we use that symbol’s existence to decide whether to enable range-checking later.

8) Building a Delphi project at the command-line

For quite a few versions now, Delphi has used the MSBuild format for its project files and project group files. This means you can use MSBuild to build your projects and project groups, using appropriate MSBuild command-lines to pass in options or specify build targets (the targets include clean, make and build). So if you have a project Foo.dproj and you want to clean up the previously produced binaries (compiled units and executable output) and then build it in Release and Debug configurations for Win32 and Win64 you could run these commands in a RAD Studio Command Prompt:

msbuild -t:clean -p:Config=Debug -p:Platform=Win32 Foo.dproj
msbuild -t:build -p:Config=Debug -p:Platform=Win32 Foo.dproj
msbuild -t:clean -p:Config=Release -p:Platform=Win32 Foo.dproj
msbuild -t:build -p:Config=Release -p:Platform=Win32 Foo.dproj
msbuild -t:clean -p:Config=Debug -p:Platform=Win64 Foo.dproj
msbuild -t:build -p:Config=Debug -p:Platform=Win64 Foo.dproj
msbuild -t:clean -p:Config=Release -p:Platform=Win64 Foo.dproj
msbuild -t:build -p:Config=Release -p:Platform=Win64 Foo.dproj

9) Formatting entire projects

Recent versions of Delphi have offered pretty printing, as it used to be called, or source formatting as the process is now described. It’s invoked by Edit, Format Source (or Ctrl+D) and can be fully customised in the Tools, Options dialog. Your custom settings can be saved into formatter profile files.

It’s less well known that the formatter is also available through a command-line tool. You can use this to run it across all files in a project directory tree.

Assuming you’ve saved your custom IDE formatter options in a formatter profile called Formatter_MyProfile.config then you start by running up a RAD Studio Command Prompt. Now issue some commands along these lines and it’s all done for you:

set CONFIG="Formatter_MyProfile.config"
set LOG=Format.log
del %LOG%
formatter -delphi -config %CONFIG% -r –d . > %LOG%

10) Case toggle

If you are not a touch typist and occasionally type a whole bunch of code in with CAPS LOCK on you should become familiar with the keystroke that toggles the case of a marked block: Ctrl+O, U.

11) Bonus tip: disable Error Insight to lower blood pressure

I’ve said this before in talks and in writing. I’m very happy to say it again. Please, *please*, don’t suffer the shame of Error Insight and its hopeless and hapless efforts in working out what might compile and what might not. Yes, it gets the simple ones right. But any vaguely interesting project that you work within is pretty much guaranteed to be besmirched with lots of red squiggles over perfectly good code and perfectly locatable units in the uses clause all within a fully compilable code base. The fact that Error Insight continues to be enabled by default, despite the growing problem of its inaccurate problem detection is really rather surprising. I urge you to disable Error Insight by going to Tools, Options… and then locating the Code Insight options within the Editor Options.

Yes, yes, there are reasons why it gets it wrong – it’s not using the exact same code as the compiler does and doesn’t know all the things that the compiler does. But this has been the case for years, and it still offends my eyes with its tenacity of squiggling over code that has just compiled cleanly.

Ease your annoyance at Error Insight by turning it off. Then pick any of the plethora of Error Insight bugs logged on QC and vote for it/them.

Seriously though, on very large projects, disabling anything that executes and isn’t useful/productive is a benefit. When working with clients’ large projects I disable Error Insight, Tooltip Help Insight and automatic Code Completion.

Read More

Read More

‘Dynamic’ Delphi/C++ samples on SourceForge via Subversion

Many of you will have already bumped into this information, but I’m posting it for the benefit of those who haven’t come across it. In much the same way as how the static RAD Studio online documentation is complemented by updatable and updated web-based documentation at, the sample applications supplied with RAD Studio are also updated over time and available via an online Subversion repository hosted at SourceForge. The RAD Studio Demo Code Web Site is at and the SourceForge project page is To pull down the demos you can use your favourite Subversion client and use the checkout functionality. With regard to Subversion clients I like using TortoiseSVN from within Windows Explorer, although there is also a TortoiseSVN plug-in for the RAD Studio IDE. Of course if you use Delphi XE or later you can perhaps more sensibly just use the built-in RAD Studio IDE Subversion support. Suitable Subversion repository URLs for the RAD Studio demo projects include: for the main demo trunk, although this misses out a bunch of XE4 demos, so maybe a specific branch (see rest of this list) might be more appropriate – RAD Studio XE demos – RAD Studio XE2 demos – RAD Studio XE3 demos – RAD Studio XE3 demos, including 64-bit C++ – RAD Studio XE4 demos, including iOS demos – RAD Studio XE5 demos, including iOS and Android demos From time to time you can again use your Subversion client to update the demos to take advantage of any changes made in the online repository. It’s good to be kept up to date! Above I touched on the online up-to-date documentation. For completeness I should mention that the docwiki is available from Delphi’s Help menu (RAD Studio Docwiki) and I should also offer up this list of entry pages to the online help systems: RAD Studio 2010 main page RAD Studio XE main page RAD Studio XE2 main page RAD Studio XE3 main page RAD Studio XE4 main page RAD Studio XE5 main page Finally, it’s always nice to get a refresher on what’s been added in recent product releases, so do stop by the What Was New In Past Releases page on the docwiki.
Read More

Delphi for iOS – some notes

The typical current requirements of the customers I work with, so they tell me, are to stick with Windows + VCL thanks to the long-term projects they have ongoing. Because of this I’ve not really spent too much time getting to know FireMonkey in excruciating detail since it was introduced. However, given that the quintessence of the XE4 release has been iOS support and this typically† revolves around using FireMonkey, I figured maybe it was about time to roll the sleeves up and get stuck in. This post is a summary run-though of the things I bumped into, how I got on, what I figured out, what problems I encountered and how I achieved a few things whilst checking out the latest platform-targeting in the Delphi product line. Environment setup First things typically come first, so top of the agenda was setting up the development environment to work on iOS projects. This was straightforward enough. The online documentation (to be honest I don’t install the help – I just use Embo’s docwiki site) covers the setup quite thoroughly. There’s a general run-through and then also in the iOS tutorials page there are links to detailed setup for the Mac and setup for Windows. To develop apps for Mac (OS X) or for iDevices (iOS) requires the use of a Mac – Apple make this a requirement as they supply some necessary tools for parts of the job (such as signing the app or simulating an iDevice) and those come with Apple’s Xcode and only run on a Mac. There’s no real need to dash out and buy a hugely over-priced MacBook Pro unless you have spare cash at your disposal; a Mac Mini is more than adequate and much more sensibly priced. Delphi or RAD Studio will run on a Windows machine, and a helper app called PAServer (the Platform Assistant) runs on the Mac to: liaise with any Mac tools that are required automate the iPhone/iPad Simulator when running iOS apps against the simulator act as a remote debugger when debugging a Mac or iOS application (either on a device or in the simulator) My first attempt at iOS development had my development environment (Delphi XE4) on a Windows laptop, talking across my network to the Mac Mini. This actually worked just fine, though the deployment step took about 10-20 seconds each time, sending the app files and the debug symbols across the network. Hardly a long time, but it got annoying when I kept needing to make small changes and see their effect. I ended up settling on a Windows virtual machine running on the Mac Mini via VMWare Fusion and installed Delphi XE4 in that. This made the deployment step joyfully rapid. I also then had the luxury of working directly with the Mac Mini, or working remotely on my laptop using VNC. I can have one session connected to the Windows virtual machine (VMWare Fusion acts can have each virtual machine optionally act as a VNC server) and another session talking to the Mac itself to see apps running in the simulator. I should point out I don’t have any iDevices – all my apps are just tested in the simulator and that’s that for the time being. To build iOS apps for the device and the simulator the IDE makes use of two of the five Delphi compilers shipped in RAD Studio XE4 (or Delphi XE4 with the mobile add-on), which are the latter two in this compiler list: dcc32 – Embarcadero Delphi for Win32 compiler version 25.0 – your regular Win32 Delphi, the latest version updated over many versions since Delphi 2 dcc64 – Embarcadero Delphi for Win64 compiler version 25.0 – the 64-bit Windows targeting compiler dccosx – Embarcadero Delphi for Mac OS X compiler version 25.0 – the Delphi compiler that generates 32-bit OS X apps dccios32 – Embarcadero Delphi Next Generation for iPhone Simulator compiler version 25.0 – the NextGen Delphi compiler that builds Intel executables that run in the iOS simulator dcciosarm - Embarcadero Delphi Next Generation for iPhone compiler version 25.0 – the NextGen Delphi compiler that builds ARM executables that run on iOS devices Simple FireMonkey apps To check that FireMonkey behaves basically the same as VCL I created a FireMonkey mobile application and threw some code on the form. It did as expected, and I noted the pervasive StyleLookup property that lets you customise all the controls. For example with a button there are pre-defined styles to make the button look like the various buttons that commonly crop up in iOS applications. This style system helps you put together a UI that will fit in with other apps in the world of iOS. This is an important issue. When you build an iOS app you’ll be creating a UI specifically for the mobile devices – laid out to look appropriate on an iPhone and/or iPad. Apple are very specific about how UIs on their OSs should look and have comprehensive User Experience guidelines both for OS X and for iOS. You should digest these guidelines and take note of how existing applications look to ensure your app doesn’t stick out like a sore thumb. The UI should be carefully designed for the target platform. <soapbox>Consequently, the repeated platitude we hear from the bods at Embo about building an app once and recompiling it for different platforms should be taken for what it is: marketing fluff. Sure, back-end code could follow that ideal, but anything tightly related to the UI will doubtless need to be re-implemented for each target platform. You owe it to your users to respect them enough to do the right thing with your app’s UI.</soapbox> All that notwithstanding, it was a breeze to build a simple iPhone app and have it run in the simulator. Seemed very much akin to building a VCL application at the basic level I was working at, which was quite encouraging. Compiler changes If you’re looking to share a bunch of existing code with an iOS Delphi application you should remember that the iOS compiler is a next generation Delphi compiler, with a few language changes in. I gave a list of the changes (including proposed changes currently represented by warnings) in the compiler in a previous blog post here. The removal of some of the string types and some of the other obvious changes in it might make it more difficult than you expect to pull in a lot of old code, but obviously your mileage will vary on this one. If you want to write new code that will be shared across platforms, the fact that the next-gen compiler employs ARC for all Delphi objects (not just strings, dynamic arrays and interfaces) means that the shared code will need to call Free, which is a no-op on iOS. iOS-only code can forget all about calling Free, which is nice. Certainly what I hear from clients I work with is that their primary goal for the iOS compiler is to build some small standalone applications that will, via some connectivity option or other, perhaps connection to a web service or DataSnap server, present some representation of a portion of an existing desktop application to users, or provide reports and stats from an existing system to management types. That seems like a very achievable and sensible plan to me. New dependency keyword A new keyword that slipped in under the radar in the NextGen ARM compiler is dependency. This is really a convenience that precludes the need to tweak the options to get certain apps to work. Specifically this keyword lets you tell the linker of additional libraries to link in when declaring an external library function. So, for example, the MIDAS static link library midas.a has a dependency on the Standard C++ library libstdc++.dylib. A dylib on a Mac can be dynamically loaded at runtime or statically linked. Apple decrees that iOS apps cannot use any custom dynamic libraries, so any library code must be statically linked into the app. This means that any app that uses the MIDAS library must statically link the Standard C++ library in as well. Without the dependency keyword this would involve modifying the ARM linker options. This could be done by going into the project options (Ctrl+Shift+F11) and doing either of these: selecting Delphi Compiler, Compiling in the options tree, then selecting Other options, Additional options to pass to the compiler and entering a suitable portion of a dcciosarm.exe comand-line like: --linker-option:"-L $(BDSLIB)\$(Platform)\$(Config) -lstdc++" selecting Delphi Compiler, Linking in the options tree, then selecting Options passed to the LD linker and entering: -L $(BDSLIB)\$(Platform)\$(Config) -lstdc++ However, dependency means you can forget all that and write your import declaration like this one, from DataSnap.DSIntf.pas: {$IF DEFINED(IOS) and DEFINED(CPUARM)}function DllGetDataSnapClassObject(const [REF] CLSID,  [REF] IID: TGUID; var Obj): HResult; cdecl;  external 'libmidas.a' name 'DllGetDataSnapClassObject'  dependency 'stdc++';{$ENDIF IOS and CPUARM} This approach is used more widely for the InterBase DBExpress client code in Data.DbxInterbase.pas. Here we find a variety of imported functions coming from libsqlib.a, which have a dependency on both Standard C++ and also libibtogo.dylib. So there are a whole bunch of declarations like: function DBXBase_Close(  Handle: TDBXCommonHandle): TDBXErrorCode; cdecl;  external 'libsqlib.a' name 'DBXBase_Close'  dependency 'ibtogo', 'stdc++'; FireMonkey versus CocoaTouch If you spend some time browsing through the FireMonkey and iOS-specific RTL source you’ll become familiar (at one level or another) with the relationship between FireMonkey and the iOS Objective-C API. Very similar to how the VCL presents nice components, but those components are built on the Windows UI infrastructure of windows and window handles and how VCL applications operate by participating in the regular Windows message processing behaviour, FireMonkey iOS applications also immerse themselves in the regular iOS infrastructure. What this means is that a FireMonkey form is based on an Objective-C UIView or, more specifically, a GLKView in the case of a GPU-backed form. The application start-up is done through a call to UIApplicationMain and there is an application delegate (UIApplicationDelegate protocol implementation) used to deal with when the app starts, goes to the background, comes back to the foreground and terminates. Here and there you might find it useful to call upon some iOS APIs, which requires a heads-up on some basics. The following sections endeavour to give you such a heads-up. Working with NSStrings Objective-C uses NSString objects where Delphi uses strings. If you need to pass a string to an iOS API that expects an NSString you can use the NSStr function in iOSapi.Foundation.pas to translate it over. You can also do the reverse by borrowing (ok, copying) the NSStrToStr function that is (inexplicably) tucked away in the implementation section of FMX.MediaLibrary.iOS.pas. [Update: Note that this function turns the NSString to UTF8 before turning it back to a Delphi string. This is a bit of a round trip, and any characters outside UTF8-space get rather mangled. You might benefit from looking at Chris Rolliston’s approach to the same problem.] Additionally, any time you are presented with a UTF8 string from an Objective-C method (which would be represented as type _PAnsiChr), such as the UTF8String method of NSString or the systemVersion method of a UIDevice, you can turn it into a Delphi string with UTF8ToString. Delphi’s representation of Objective-C objects Much as Delphi's classes all stem from TObject, Objective-C classes all have a common ancestor of NSObject. The large number of classes in the full tree are split into branches of classes called frameworks. For example UIKit is the framework containing all the basic UI-related stuff and MapKit wraps up all the mapping stuff. Delphi represents these Objective-C classes by interfaces. For example, NSObject is declared in iOSapi.CocoaTypes.pas and contains declarations of the instance methods of an Objective-C object of type NSObject. Where Delphi has an interface for an Objective-C class's instance methods there is also another interface for all the class methods. In the case of NSObject it's called NSObjectClass. In order to make use of these interfaces a helper class is defined alongside the instance interface and class interface for the Objective-C type. The helper class is a generic class that inherits from TOCGenericImport<C,T> and wraps up the process of importing the Objective-C class into Delphi. For NSObject the helper class is TNSObject and gives you a means to create an Objective-C object of type NSObject and also wrap up an object id for such an Objective-C object into an NSObject interface reference. That sets out the pattern of types used to represent imported Objective-C objects. In Objective-C constructing an object is a two stage process. The memory is allocated by a call to the class alloc method and then the returned object is initialised through a call to a class initialiser, such as the default init or maybe a custom one. Various classes have custom initialisers, for example controls have one called initWithFrame. We may be more familiar with the one-stop construction achieved by calling a Delphi class constructor, such as Create, but of course behind the scenes the same two steps have to occur - the memory for the instance is allocated and then the body of Create initialises that instance. Let's take an example of creating an alert view - basically an iOS message box. Clearly in a FireMonkey project you would just use ShowMessage or MessageDlg, which will work out how to do all this on iOS platform, but for the sake of example let's follow it through. The alert view is represented in iOS by UIAlertView, so iOSapi.UIKit.pas defines interfaces UIAlertView and UIAlertViewClass as well as class TUIAlertView. If you want to construct an instance of UIAlertView using alloc and the default init initialiser then a call to TUIAlertView.Create will do the job and return an interface reference to a UIAlertView. You can then tailor the alert view by calling its setTitle, setMessage and addButtonWithTitle methods and display it by calling show. Something like this: var  alertView: UIAlertView;...  alertView := TUIAlertView.Create;  alertView.setTitle(NSStr('Delphi for CocoaTouch'));  alertView.setMessage(NSStr('Hello world'));  alertView.setCancelButtonIndex(    alertView.addButtonWithTitle(NSStr('OK')));;  alertView.release; However if you want to use a custom initialiser you can allocate an uninitialised instance by calling the helper class's Alloc method and then call the custom intialiser on that. However the custom intialiser will return an actual Objective-C object (as opposed to an interface that represents it), which is represented as a raw pointer. This pointer can be considered the Objective-C object id. To turn this object id back into a usable Delphi interface reference you feed it into the helper class's Wrap method (just be careful with Wrap as it does not check for nil being passed in and so will happily crash if given the chance - see QC 115791). So we could rewrite the above like this: var  alertView: UIAlertView;...  alertView := TUIAlertView.Alloc;  alertView := TUIAlertView.Wrap(alertView.initWithTitle(    NSStr('Delphi for CocoaTouch'), //title    NSStr('Hello world'), //message    nil, //delegate    NSStr('OK'), //cancel button caption    nil)); //other button captions;  alertView.release; So that shows how to create a new instance of an existing Objective-C class and call instance methods. To call class methods you use the OCClass property. The UIDevice iOS class has a currentDevice read-only property that is documented to return a UIDevice instance that represents the current device. Similarly UIScreen has a mainScreen read-only property that returns a UIScreen instance that represents the main screen (i.e. not an external screen). var  currentDevice: UIDevice;  mainScreen: UIScreen;  iOSversionStr, screenDimensionsStr: string;...  currentDevice := TUIDevice.Wrap(    TUIDevice.OCClass.currentDevice);  iOSversionStr := UTF8ToString(    currentDevice.systemVersion.UTF8String);  mainScreen := TUIScreen.Wrap(TUIScreen.OCClass.mainScreen);  screenDimensionsStr := Format('%d x %d',    [Round(mainScreen.bounds.size.width),     Round(mainScreen.bounds.size.height)]); From a given interface reference to an Objective-C object, obj, you can access its object id (the pointer to the actual Objective-C object) using this: (obj as ILocalObject).GetObjectID Objective-C properties Objective-C objects offer various properties just like Delphi objects do. These are implemented with getter and setter functions as you'd expect. However if building a Delphi iOS app you should know that all the Delphi interfaces representing Objective-C classes don't have these properties brought through. Instead you'll need to call the setter procedure (e.g. setFrame() for a UIView object's frame property or setStatusBarHidden() for the UIApplication class statusBarHidden property) or getter function (e.g. frame() for the frame property or isStatusBarHidden() for the statusBarHidden property. Yeah, as you may notice there the property getter either has the same name as the property or uses an is prefix... You can read the formal documentation on property accessor naming on Apple's site here. Objective-C method names As explained in various places on the Arpanet (or Internet as we now call it), such as this method naming post from Ry's Objective-C tutorial, Objective-C has an interesting approach to method naming. The parameter names become part of the method name to aid self-description and to minimise opportunities for ambiguity. Let's have a look at some example methods defined in the UIApplicationDelegate protocol. Firstly the method that triggers after the application has started up: (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions This is a function method that returns a Boolean and takes two arguments, a reference to a UIApplication and a reference to an NSDictionary. To the person implementing the method the arguments are called application and launchOptions but the arguments are described in the full method name, which is formed from all items that have colon suffixes. The Objective-C method name is application:didFinishLaunchingWithOptions: and this differentiates it from other methods in the same protocol, such as application:shouldSaveApplicationState: and application:willChangeStatusBarFrame:. Problems start cropping up over on the Delphi side when you try to translate these methods to a Delphi representation. Here are a selection of methods from this protocol that we might wish to translate: (BOOL)application:(UIApplication *)application  didFinishLaunchingWithOptions:(NSDictionary *)launchOptions(BOOL)application:(UIApplication *)application  shouldSaveApplicationState:(NSCoder *)coder(void)application:(UIApplication *)application  willChangeStatusBarFrame:(CGRect)newStatusBarFrame Now here is the best we can do in Delphi to translate them over accurately: function application(application: UIApplication;  didFinishLaunchingWithOptions:NSDictionary): Boolean; overload;function application(application: UIApplication;  shouldSaveApplicationState: NSCoder): Boolean; overload;procedure application(application: UIApplication;  willChangeStatusBarFrame: CGRect); overload; You'll notice each method has the same name and so requires overloading. But we're okay so far as each overload has a unique signature. Let's add in some more methods: (BOOL)application:(UIApplication *)application  shouldRestoreApplicationState:(NSCoder *)coder(void)application:(UIApplication *)application  didChangeStatusBarFrame:(CGRect)oldStatusBarFrame You can probably see the problem rearing its head now. When we translate these into additional methods in a Delphi UIApplicationDelegate interface the compiler won't accept the overloads as we have the same signatures as already defined: function application(application: UIApplication;  shouldRestoreApplicationState: NSCoder): Boolean; overload;procedure application(application: UIApplication;  didChangeStatusBarFrame: CGRect); overload; So this leads to the realisation that the general case is that we cannot adequately represent any given Objective-C class or protocol by using a Delphi interface. You can do some of it, but as soon as matching signatures come along this approach falls down. If you hunt out the UIApplicationDelegate interface in iOSapi.UIKit.pas you'll see a number of the methods commented out for this exact reason. This puts a bit of a downer on the whole affair until you find out that given enough desire you can work around this limitation of Delphi's method representations and set things up manually. In fact that's exactly what FireMonkey does in order to set up an application delegate on iOS application start-up. It uses low-level Objective-C Runtime routines to set up Delphi routines to implement given Objective-C methods. If you look in FMX.Platform.iOS.pas and locate TPlatformCocoaTouch.Create you can see this being done. It's a bit of a faff, but does allow Delphi to work with any Objective-C objects. I've used the approach myself in a couple of test applications and can confirm that it's workable, but really it's not entirely productive to do so. I plan to write more on the subject at a later point, but for now I'll leave the FireMonkey source as an adequate reference. [Update: apparently I’d rather overlooked the fact that this issue had already been acknowledged by the Embo devs and a neat workaround exists – ah well, you live and learn. Indeed this neat workaround is used to work around the problem in the RTL, for example in the CLLocationManagerDelegate interface. This is achieved using the handy [MethodName()] attribute through which you can map an arbitrarily named Delphi method to a specifically named Objective-C method. Thanks to Embo’s Darren Kosinski for pointing me to this] ARC and Delphi and Objective-C When Delphi first arrived it supported the string type. A string is really a pointer to a data structure that is automatically memory-managed for you. This memory management includes reference counting to cater for when strings are passed into subroutine calls and assigned to variables. When nothing references a string any longer the code generated by the compiler ensures all the memory occupied by the string data structure is freed. When interfaces were added to Delphi 3 we again enjoyed reference counted memory management. The compiler worked out when to call the _AddRef and _Release methods on interface references based on assignments, parameter passing and scope and if _Release caused the internal reference count to reach 0 the object destroyed itself. With the NextGen Delphi compiler the programmer is afforded the luxury of automatic reference counting (ARC) for all objects, as detailed in this Dr Dobbs article by Embo's JT and Marco Cantù. The compiler will identify where to make calls to TObject's __ObjAddRef and __ObjRelease for you. Again, when the internal reference count gets to 0 the object destroys itself. Hence there is no longer a need to worry about calling Free and wrapping construction and destruction code up in a pair inside a try/finally statement. That said, it doesn't matter if you do call Free as in the NextGen compiler TObject.Free simply sets the object reference to nil, hastening the decrement of the object reference. When you program iOS apps in Objective-C you are also blessed with ARC. Just as with Delphi it's a compiler thing - the compiler works out where it's appropriate to make calls to retain and release to ensure the internal reference counts will drop to 0 when a given object is no longer used by anything. So the Delphi (NextGen) compiler does ARC against all Delphi objects and the Objective-C compiler does ARC against all Objective-C objects, but what about Objective-C objects in a Delphi program? Unfortunately there is no ARC for the iOS objects represented by the import wrapper class and the interfaces discussed above. When dealing with iOS objects manually you will need to call retain and release yourself at the correct points. Allocating an iOS object starts the reference count off at 1; calling release will drop it to 0 and have the object destroy itself. Apple’s Instruments app A really useful tool supplied as part of Xcode (or possibly just shipped a part of OS X, I’m not positive) is Instruments. If you read up on Instruments you’ll see that this can help identify memory leaks in your OS X or iOS apps. I've been using it to check on iOS object leaks in FireMonkey applications and also in apps written in Delphi that use no FireMonkey business at all. It's been quite illuminating as I've happened upon a couple of simple shortcomings in the FireMonkey code. The principle I've used is to have all the code that does stuff I want to leak-check in secondary forms launched from a main form. In the case of FireMonkey I'm just using regular forms and launching them with ShowModal. I launch the app in the iOS simulator and then launch Instruments and choose the Leaks mode. Next I use the Choose Target dropdown and from the Attach to Process submenu I select my app process from the System list. Pressing the Record button then starts tracking object and memory allocations. For any given iOS object type you can see how many instances still exist, look at a list of them all and for any instance see the allocation and all the retain/release calls. Going through this process with a simple FireMonkey app that launched a secondary form showed that a UIView and various other helper objects were being allocated each time the form was displayed but not freed when it was closed. Tracking the problem eventually yielded some fixes to the FireMonkey source that resolve the problem, as documented in QC 115914. In short you need to: copy FMX.Platform.iOS.pas from $(BDS)\source\fmx change TPlatformCocoaTouch.DestroyWindow to be:procedure TPlatformCocoaTouch.DestroyWindow(  const AForm: TCommonCustomForm);begin  if Assigned(AForm.Handle) then  begin    WindowHandleToPlatform(AForm.Handle).View.      removeFromSuperview;    WindowHandleToPlatform(AForm.Handle).View.release;  end;end; in TPlatformCocoaTouch.ShowWindowModal change the finally part of the try/finally statement to:finally  BackView.removeFromSuperview;  BackView.release;end; Further experimentation showed that the iOS implementation of the message box routines (ShowMessage, MessageDlg and InputQuery) were also leaking objects; in this case UIAlertView references. QC 115966 contains the report and a proposed source fix. As above you change a local copy of FMX.Platform.iOS.pas. This time you change TPlatformCocoaTouch.MessageDialog. At the end of it add this statement: AlertView.release; Now in TPlatformCocoaTouch.InputQuery, imediately after the assignment: Result := Delegate.Result = mrOk add in the statement: AlertView.release; Accessing the Objective-C shared application object iOS apps often need access to the Objective-C shared application object (a singleton UIApplication object that represents the running application). One example would be when using a TWebBrowser object you can indicate to the user that network activity is taking place as the web page is brought down by using a property of the application object to control the iDevice's network activity icon on the status bar. The browser object's OnDidStartLoad event marks the start if the page download and OnDidFinishLoad or OnDidFailLoadWithError tell you when it's over. The application object has a networkActivityIndicatorVisible property that controls the status bar icon. In iOS you retrieve the shared application object by using the sharedApplication class function of the UIApplication class. Here is how you could build a helper function to expose the shared Objective-C application object. Note that a function just like this is implemented in (although not exposed from) both these iOS FireMonkey units: FMX.MediaLibrary.iOS.pas and FMS.Pickers.iOS. uses  iOSapi.UIKit;function GetSharedApplication: UIApplication;begin  Result := TUIApplication.Wrap(    TUIApplication.OCClass.sharedApplication);end; Given this function you could write event handlers for a web browser component like this: procedure TBrowserForm.WebBrowserDidStartLoad(ASender: TObject);begin  GetSharedApplication.setNetworkActivityIndicatorVisible(True);end;procedure TBrowserForm.WebBrowserDidFinishLoad(  ASender: TObject);begin  GetSharedApplication.setNetworkActivityIndicatorVisible(    False);end;procedure TBrowserForm.WebBrowserDidFailLoadWithError(  ASender: TObject);begin  GetSharedApplication.setNetworkActivityIndicatorVisible(True);  ShowMessage('Web page failed to load for an unknown reason');end; In this case the failure event handler cannot tell the user what the failure is as the NSError object given the equivalent iOS event handler is not surfaced to FireMonkey, even in some abstract manner. I've reported this to Quality Central as QC 115652. Logging to the OS X Console app It is common in iOS apps to emit logging statements that are picked up by OS X’s Console application using the NSLog API. This is a global function, not a method, and takes an NSString, but because it is outside the scope of the Delphi helper objects and interfaces it expects a PNSString (a pointer to an NSString) - an Objective-C object id for the string in question. To make it easy to turn a Delphi string into a PNSString you can build a helper function like this: uses  iOSapi.Foundation, Macapi.ObjectiveC;...function PNSStr(const AStr: String): PNSString;begin  Result := (NSStr(AStr) as ILocalObject).GetObjectIDend; While you are at it you could build a more usable Log function: procedure Log(const AStr: String); overload;procedure Log(const AStr: String; const Args: array of const); overload;...procedure Log(const AStr: String);begin{$IFDEF IOS}  NSLog(PNSStr(AStr));{$ELSE}  {$MESSAGE WARN 'Only currently implemented for iOS'}{$ENDIF}end;procedure Log(const AStr: String; const Args: array of const);begin  Log(Format(AStr, Args))end; Numeric type definitions For the most part you'll not bump into this being an issue, but the initial release of XE4 has NSInteger and NSUInteger both incorrectly defined in iOSapi.CocoaTypes.pas. NSInteger is defined to be Integer and NSUInteger to be LongWord, which are both always 32-bits regardless of the underlying platform. The Apple documentation for NSInteger and NSUInteger clearly states that on 32-bit platforms the types are 32 bits and on 64-bit platforms they are 64 bits. It would be rare to find these wrong definitions a problem, but I did bump into it as an issue when implementing a C calling convention (cdecl) routine that was called by Objective-C and returned an NSInteger. When the stack was cleared up by the Objective-C side the differing size of the return value meant the function's return address was in "the wrong place" and so the app immediately crashed. I sorted this in the project by defining local versions of the types that were correct. This has been reported as QC 115789. Debug source stepping The keener among us Delphi users like to step through the RTL and VCL or FMX source. With iOS apps the installation neglects to add one of the key iOS RTL directories to the browsing path in the initial XE4 release. This results in various iOS units not being found when trying to step through the source. The issue has been reported on QC, and I submitted a duplicate report before learning of that initial post. To fix the problem go to Tools, Options..., Delphi Options, Library. Now add $(BDS)\source\rtl\ios to the Browsing path † the reason for the use of typically is that you can actually build a regular CocoaTouch application using Delphi for iOS if you really want to. I've done this myself with a few little apps, working through a variety of technical stumbling blocks along the way. I'm in the process of writing up my findings on the subject, so I'll hopefully blog about an article on the subject in the near future.
Read More