Interesting Tech Projects
Mac OS X
Creating Package Installers for MonoMac
Sep 25th
When developing applications with Mono/MonoMac it is very useful to create an installer that bundles Mono with your application. MonoMac includes a utility for creating an installer but unfortunately it is bug ridden and limited. Here are the steps that work for me.
Note: make sure you have Xcode installed.
- Delete any existing bundle. For example MyApplication.app. This is important because if the bundle already exists when you try to create it MonoMac will give you the cryptic error message “Unhandled error in packaging”
- In MonoDevelop go to Project -> Create Mac Installer… and choose to only create a bundle
This should create a bundle with a name like MyApplication.app - Start PackageMaker by going to Spotlight and searching for it. It can also be found in /Developer/Applications/Utilities.
- Drag your bundle MyApplication.app to the left hand side of PackageMaker.
- Select the package, click on “Components” and uncheck “Allow Relocation”
- Build and run the installer
You may or may not want to uncheck the option to allow relocation. On your development Mac if you don’t uncheck this then the installer will find a version of your application inside your MonoDevelop solution and overwrite it rather than putting it into /Applications. This makes it appear as if the installer didn’t work. On non-development Macs this option allows the application to be overwritten even if the user has moved it after installing an older version.
Global Objects With MonoMac
Sep 24th
When developing for C# and using Windows Forms creating and using global objects is trivial:
public static class Program { public static Foo MyFoo = new Foo(); static void main() { Main = new MainForm(MyFoo); } }
The same can’t be said for MonoMac. The mistake is to equate the static MainClass class as being the same as the WinForms Program class in the example shown.
The solution is to put the global class instantiation inside the NSApplication delegate. MonoMac creates this automatically and calls it AppDelegate. The above example becomes:
public partial class AppDelegate : NSApplicationDelegate { MainWindowController mainWindowController; public Foo MyFoo = new Foo(); public AppDelegate () { } public override void FinishedLaunching (NSObject notification) { mainWindowController = new MainWindowController(MyFoo); mainWindowController.Window.MakeKeyAndOrderFront(this); } }