Tuesday, December 29, 2009

Grails Gotcha #1

Whenever you work in Grails and wonder why something like this is not working:



Check the types of objects you're trying to compare. Most likely, one of the following gotchas is keeping you busy.

1. Trying to check for containment of Strings. In case you're using Groovy's support for embedding variables in a string (using "foo $bar" notation), the resulting object is of type GString not String.

2. Trying to check for containment of byte-code-modified objects. Especially when working in Hibernate-environments, objects might not really be what you think they are. They are probably of a type like "MyClass__javaassited_36" where the objects in your list are of type "MyClass".

You might be able to change your statement to use the convenient "any { it -> // code }" method included in the Groovy JDK (Object class).

Hope it saves you from some of the headaches it's been giving me!

Remote Desktop on Mac

Did you know that Mac OS X comes with a fully integrated VNC server and client for quick and easy remote desktop access? I came across the need to use remote desktop connection with my iMac at home once I was away for the holiday season. It was pretty easy to set things up on Mac OS X so here's a quick run down of what you have to do in order to get full remote desktop access to your home Mac:
  1. Optional: Install the fantastic DynDNS client, enter your credentials and domain information. Your Mac can now be accessed using the domain registered at DynDNS even in case you only have a dynamic IP address.
  2. In case you're behind a router, make sure you enable port forwarding to your Mac on port 5900, the default VNC port.
  3. Open your Mac's system settings and open the Sharing settings.
  4. Enable Screen sharing and specify which user should be allowed to login remotely.
  5. You're now ready to go! Get another Mac and open the Finder. Choose "Connect with server" from the "Go to" menu and enter "vnc://".
  6. In case things are working properly, the login form will be displayed. The user credentials are the same that you use when working with your Mac directly (ie. without a remote connection).
Obviously, you should make sure that no user accounts with empty passwords are allowed to login remotely. Enjoy!

Tuesday, December 22, 2009

NEXT Munich

We have finally created a web presence for our new iPhone / iPod touch and Android development studio. You can find our site (German only for now) at the following location:

http://www.next-munich.com

I will start to move most of the tech-related topics to my new tech blog AppTech which is hosted on our website. I'll keep posting in English so that no reader is left behind! The first post on the new blog just presents a small piece of code which can help in case you're having flicker-issues on launch of your cocos2d-enabled application.

Hope to see you on the new site!

Saturday, December 12, 2009

Background Music & SFX on iPhone

I'm so glad that many people are sharing their findings and how they are getting things done in iPhone:

First of all, there is a super-convenient set of classes in the cocos2d package that can be used for playing background music and sound FX. The only thing I have to figure out is how I can tweak these guys to stop iPod music in case the user explicitly wants to enable in-game sound. But that's probably a piece of cake, too!

The next help comes from Tinker Blog which lists suitable file formats and conversion commands. Essentially, iPhone allows you to play one compressed file (like MP3) and several uncompressed files in parallel. Since there's only a single hardware decoder for compressed files available, not more than a single compressed file can play at the same time, though. The idea is to take your most expoensive sound and use it as an MP3 within your application (eg background music) and convert the smaller sounds (typically sound effects) to a format like "IMA4" packed inside of a "CAF" file.

Friday, December 11, 2009

Shear Transformations in cocos2d

To properly map a 2d texture onto a cube, I needed a shear transformation to properly transform the texture. Cocos2d does not support shears out of the box but this piece of code suggested by codem01 does the trick very nicely.

Keep in mind that the default shear values should be 0.0 (= no shear) and values used can be both, positive and negative and are restricted in magnitude only by your application.

You can find some more background on shear transformations on Wolfram MathWorld and on Wikipedia.

Thursday, December 10, 2009

Stupid Objective-C Mistake #1

While laying out my screen, I keep objects handy in a couple of NSArrays. Typically, I start out coding all the layouting code and retouch it once I see what's rendered on screen. Many times, objects that I try to add to my layout just do not appear - because I failed to initialize my arrays!

Since in Objective-C, a message to a nil-variable just returns nil and moves on, you dont't have any indication that something might not go according to plan. Therefore this little note to self:

First thing to do if things do not appear on screen, check your arrays initializations, stupid!

Thursday, December 3, 2009

Leak Hunting in iPhone Code

Eventually, when you're closing in on the release candidate of the software you're working on, you're probably going to check your app for memory and performance issues.

Same for me. On my current iPhone project, we're getting closer to our first beta and I felt I had neglected checking my memory usage and whether there are any apparent memory leaks in my app. Firing up Instruments, Apple's tool for analyzing Mac and iPhone software in many different ways (Memory, Disk Access, Open GL, Leaks, Core Data to name just a few), I was pretty happy with what I saw: the Leak-Detection tool did only find a couple of minor places in the code where I was leaking memory.

The output of Instruments, though not very intuitive at first, helped me identify the places in my code where I was allocating and / or retaining objects which I never released when it was time for them to be released. After patching those holes only a couple of leaking places were left that did not trace back into application code but into system APIs. Good job, I thought.

Coming from a Java background where I never had to spent a lot of thoughts to memory management (unless, of course, the occasional image = null; System.gc(); calls), switching to a reference-counted environment on the iPhone seemed to easy to be true. And sure enough I was going to find out that things are slightly more involved than checking the Leak tool in Instruments!

My colleague discovered the issue when he kept playing the game for longer than I had ever done. At some point in time, loading one of the included mini games, the application just crashed. Memory was his first thought and I also felt like it was some problem with running out of memory. Fortunately I was able to reproduce the bug and could see memory usage increase in Instruments while navigating the game.

After some time of digging for an answer I discovered an issue that was not detected by the Leak tool: cyclical references. Here I retained an object representing my scene for it to render properly while active. Within that object I created another object, however, which was retaining the scene. Once the scene was removed from screen, deallocation did not take place since the retain count of the scene did not reach 0.

How did I catch that one? A good indicator is ever increasing memory usage within your application. Monitor that while running on the phone itself to get a more accurate picture of your memory's distribution between Open GL ES memory and "regular" memory. I tried to explicitly free all my textures by calling cocos2d's [[TextureMgr sharedTextureMgr] removeAllTextures] method. Since this did not free any Open GL memory at all, something was going on. Finally, I carefully tracked memory usage using the Memory instrument when taking well-defined steps within the app. Once I had discovered a point where memory did not go back to where it was supposed to be (in case all of the memory had been free'd), I added some logging to see whether the object's I wanted to be dealloc'ed really were disposed of. That step let to the discovery of the the leak - maybe this will help you find some in your code, too!

Here's some sample implementation code to highlight what was happening:



This code kind of looks ok at first but soon you'll notice, that MyScene is never going to be dealloc'ed unless you explicitly call its' release selector twice somewhere outside of this code (which is going to lead to other problems - so don't do this!).

Assume the following code to understand why this is happening:



As you will probably know from Apple's documentation, whenever you're using alloc / init to create an instance of a class, you've implicitly retained the object. You have to explicitly release the object to properly dispose of the object. Now pay attention to the object's retain count:

1. The call to [[MyScene alloc] init] gives you an implicit retain count of 1.
2. Additionally, MyObject retains the allocated scene thus increasing its' retain count to 2.
3. Once [scene release] is called, the retain count is reduced to 1.

As you can see, the retain count is not going down to 0 as it should because of the retain by MyObject. Since MyObject only releases its' reference to MyScene in dealloc, this is not going to happen unless you explicitly send the MyObject instance the release selector.

The easy fix: if MyObject only lives as long as the scene is living, just don't retain the scene. It's going to be alive as long as MyObject is alive so there is not going to be a problem.

If you think this is happening to you, too, make sure you log the retain count of the object in question at appropriate times (whenever you think this object should be dealloc'ed but isn't). You can do this with a single line of code:



Hope this helps you find the pesky cyclical memory leaks. When is there going to be an app for that, too?

Did you find any other common patterns of leaks that are not detected by Instruments? Share your findings in the comments! I'm surely going to be thankful but so are probably all the other readers / Google users.

Friday, November 27, 2009

TextField update

There was a small bug inside the TextField code with regards to accessing the latest strings in textFieldUpdated method. The protocol has been adapted to reflect this.

Updates are available here.

Enjoy!

Wednesday, November 25, 2009

The Quest to implement a custom Text Field

To match the UI of the App I'm working on right now, I needed a text field with a custom look and feel that would nicely integrate with cocos2d.

I thought there must've been someone out there who has already accomplished / implemented something like this but after a while of google'ing and browing the cocos2d forums, I figured that there seems to be no final, working source code of something like this available.

With some help from this post by Jack and David (and some other stuff I don't seem to be able to remember), I eventually managed to code something myself which combines the rendering abilities of cocos2d (Sprites and BitmapFontAtlas) with the input capabilities of UITextField. This sure feels like a hack as I'm using an "invisible" (read: very tiny) UITextField to handle the text input while rendering the intercepted text using BitmapFontAtlas and some other Sprites but - hey - it works just fine.

I'll check with the people at cocos2d whether it would be worthwhile to include such a class in the main distribution. In the meantime, the files are available here.

Here's how you'd use the TextField class in your own projects:



Hope this gets you going much quicker than me! Now enjoy the code and let me know what you think!

Monday, November 23, 2009

Line-break code for BitmapFontAtlas available

I finally got around to submitting my cocos2d enhancement for BitmapFontAtlas to the cocos2d for iPhone issue tracker. The respective issue #637 contains the modified source code and is up for grabs if you can't wait to give this thing a try.

Here's a quick snippet of sample code for you to better understand how to use the added features:



Let me know in case you're having problems with the code or in case something's unclear. Enjoy!

Thursday, November 12, 2009

Code Snippets in Blogger posts

Finally got around to installing the awesome syntax highlighter on my blog thanks to the post by Carter Cole. I had to go hunt around for the Objective-C brush which you can copy and paste to a JS file on this page (the download link on the list of brushes did appear to point to a brush for Lua).

And this is what it looks like - pretty neat, huh?

Growl-based Hudson notifier

Since the Java-based notifier wasn't working properly for me, I quickly played around with a Cocoa-based notifier for Hudson. The result is a small piece of code that is neither properly refactored nor very clean.

It does its job, though, and that's why I felt like open source'ing it. Maybe somebody would like to help me flesh out the tool? The source code is hosted at Google Code:

http://code.google.com/p/hudson-on-cocoa/

Enhanced Fonts in cocos2d

One thing I came across in cocos2d was an issue with the font rendering. Since the fonts produced by Hiero bitmap font editor are very tightly packed on their containing images, rendering artefacts can appear when cocos2d displays the characters on screen.

Several people have reported these issues but I did not find a solution that fixes the problem in all cases. For that reason I have slightly amended the Hiero bitmap font editor: the modified editor outputs the fonts with more space between individual characters and amending the characters rectangles in the font definition files. This works very well and fixes the issue for me. I'll try to get in touch with Hiero's maintainer (who seems to be this guy) and will check whether there is any chance of having this feature integrated into the official version of the editor.

Another thing relating to fonts is the calculation of a string's width and, based on these calculations, a proper algorithm for line and page breaking. As I did not find such a facility within cocos2d source code, I enhanced the BitmapFontAtlas class to provide all of these. Basically, before calling [label setString:@""] to set the text for a label, you can assign a size to the label using

label.size = CGSizeMake(width, height);

If such a size has been assigned, a call to

[label setString:@"A very long string with reeeeeaaaaalllllllyyyyyyyyyyyyyyyyyyy long words and\nforced line breaks."];

will split the string according to the given size. The string will first be divided into lines (obeying the maximum width assigned earlier), then into pages (additionally obeying the maximum height). The first page will then be used as the string displayed by the label.

To choose a different page and figure out the amount of pages available within the label, you can then use the properties label.currentPage and label.pages respectively. If you assume that you want to switch to page 1 and this is within the amount of pages available, you can just assign label.page = 1 and be done.

If you don't assign a size before your call to [label setString:@""], the text is going to be rendered as with the unmodified version of BitmapFontAtlas. The only added benefit is that forced line-breaks using @"\n" are supported.

For this change, too, I'll try to contribute back to the cocos2d project. I will keep you updated!

Friday, November 6, 2009

Databases: Reserved Keywords

With technologies like Hibernate, deployment of database-driven application should've become a no-brainer: change the driver, change the DataSource's configuration in some XML file and off you go!

Reality is slightly different: a Grails-based web-application we're working on right now is configured for three different databases - depending on the system we're deploying to. During development, it's configured to use an in-memory HSQLDB. When working in development mode, things just work - there has not been a single reserver-keyword hickup so far.

For production, we have two different databases that we can test on: MS SQL Server 2005 and MySQL. For MS SQL Server 2005, first-time deployment has been a pain. During schema generation only the first error is that occurs is reported in the logs and thus we had to perform a couple of deploy -> bugfix -> deploy -> ... cycles as a couple of issues with reserved keywords popped up.

In MySQL, things have been going pretty well with no need to change mapping because of keywords. Just yesterday, however, I added a new field to one of our domain classes and ran into the first keyword issue on MySQL, too.

Now here's the list of keywords you need to avoid while working on the different databases. I'll try to keep this up-to-date as I encounter more such issues.

MS SQL Server 2005
  • "user" - Won't be accepted as table name in schema generation
  • "rule" - Won't be accepted as table name in schema generation
MySQL 5.1
  • "key" - Even though this keyword can be used as a column name in schema creation, adding to the table with an "insert into" will lead to an unhelpful 'you have a syntax error near ...' SQLGrammarException to be thrown

Which brings me to another question? Why does the Hibernate database dialect not automatically prevent these keywords to be used in mappings and provide replacement values? The dialect could, for example, prefix every known reserved keyword with a "_" character - deployment problem solved.

Sunday, November 1, 2009

My first barcamp

Yesterday I participated in my first barcamp. To be honest, I broke one of the most important rules about barcamps but more on that later.

The mobile devcamp Munich 2009 - or #mdc09 for short - took place at the Intel offices in Feldkirchen on Saturday. As I didn't know anything about barcamps until that day, here's a brief run down of what happened for anybody interested in visiting a barcamp one of these days.

Basically a barcamp is this event where loads of people show up, quickly introduce themselves (by the ritual, everyone's allowed to only give their name and three keywords or tags) and self-organize a day full of sessions on a broad range of topics. Whoever is ready to give a session enters the stage, briefly describes what they are going to talk about and asks for a show of hands indicating people's interest in the topic. In #mdc09's case, about 15 - 20 people gave a session and rooms were allocated based on the interest of the general public in these sessions. The sessions themselves are very casual and are not at all like the classic speeches that you'll know from conferences. Participation in the session is hugely encouraged - which leads to very fruitful discussions!

Besides all the sessions, the people who show up at a barcamp are really great! Everybody has a story and a lot of insights to share. People are very approachable and open to meet and greet.

Maybe I was a very lucky first-timer at a barcamp and things just went especially well. Still, if the next barcamp is only half as interesting it's going to be a big win! So in case you're interested, go visit a barcamp whenever you get the chance. You won't regret it!

Regarding the broken rule: there are a couple of rules encouraging participation in a barcamp. Amongst others, first-timers are supposed to give a session themselves during the first barcamp they visit. So ... I did not make it this far but am very much prepared to do so at the next barcamp I'll attend. To learn more about the other rules of barcamps, go visit @flobby's blog (German). For upcoming barcamps in your area, have a look at the official barcamp wiki.

Now, go, enjoy your first barcamp!

Friday, October 30, 2009

Running Actions in cocos2d during onEnter

I just discovered a requirement in the onEnter method when you try to run a duration-based Action in cocos2d. Whenever you're trying to do something like this within the onEnter method of a subclass of Layer:

[node runAction:[FadeIn actionWithDuration:1]];

make sure you call the super class' onEnter method. Otherwise the action will not perform what you try to achieve. Working code looks like this:



Hope this helps someone and saves some time!

Thursday, October 29, 2009

Note to Self on Void Pointers and CallFuncND

This is no news to anyone except for people who have never been exposed to void pointers (void*) before. Coming from a Java-background, I never had the opportunity (or dare I say hassle) to deal with pointers, obtaining memory addresses and de-referencing those. Whenever I was confronted with C / C++, I tried my best not to dive too deep into that matter.

Now in Objective C, I finally wanted to get rid of a compiler warning I was getting because I was dealing with void* as a data type. Basically, void* is a pointer to some data in memory of which the type is unknown to the compiler. Therefore, any address to some data in memory can be stuffed into a variable of type void*. Both of the following is valid:

void* data;
int i = 5;
float f = 6.5;

data = &i; // first assignment: works
data = &f; // second assignment: works, too

Now to get back to the data you stuffed inside, you cannot just de-reference it just like that. You need to cast it to the proper pointer type of the data that is stored at the particular address you're pointing to. In other words, you'd have to do the following (continuing the code above):

int* iPtr = (int*) data; // if data contains &i
float* fPtr = (float*) data; // if data contains &f

Since cocos2d uses void* as the data type to piggy-back any kind of user data within a CallFuncND action, I at least had to get that straight!

Sunday, October 18, 2009

Mac OS X auto-starting Tomcat

To complete my dive into continuous integration with Hudson I wanted to have Tomcat (the Servlet Container of choice) auto-run in the background on my Mac box.

First of all, download the latest Tomcat distribution from the project's homepage. Now change the script files in its "bin" directory so that they can be executed using "chmod +x *.sh". This is all you have to do to get a working copy of Tomcat on your system. Give it a spin by executing the startup shell script and navigating to "http://localhost:8080/". You will already notice that the startup will cause an icon to appear in your dock that you might rather not want to see (first of all it's ugly and clutters the dock and secondly, it doesn't provide much functionality anyways). We'll get rid of that icon a little later.

Now to have Tomcat startup automatically on system start, you have to create an entry in "/Library/StartupItems". By default, the directory is protected and you're not allowed to copy anything here. Use the Finder to change the permissions of the directory and grant yourself rights to read and write the directory. Now create a new directory "Tomcat" and place the following two files inside.

File "Tomcat":
#!/bin/sh

. /etc/rc.common

export CATALINA_HOME=/Applications/apache-tomcat-6.0.20
export JAVA_OPTS=-Djava.awt.headless=true

StartService ()
{
ConsoleMessage "Starte Tomcat Server"
su -c $CATALINA_HOME/bin/startup.sh
}
StopService ()
{
ConsoleMessage "Stoppe Tomcat Server"
su -c $CATALINA_HOME/bin/shutdown.sh
}
RestartService ()
{
ConsoleMessage "Starte Tomcat Server erneut"
su -c $CATALINA_HOME/bin/shutdown.sh
su -c $CATALINA_HOME/bin/startup.sh
}
RunService "$1"
where you substitute "" for the user account that should be used for building your iPhone app (the name of your home directory should work). This setting is crucial as Xcode will not build your project unless your running build as the user whose key chain contains the iPhone developer certificate. If you're trying to build using a different account you will get error messages saying that a suitable provisioning profile could not be found.

File "StartupParameters.plist":


These files will allow Tomcat to automatically launch when the system starts. To make this work, give execution rights to the file "Tomcat" using "chmod +x Tomcat" in directory "/Library/StartupItems/Tomcat". Now change the ownership of the files and their folder using the command "chmod -R -v 0:0 Tomcat" in directory"/Library/StartupItems". This will give ownership of the files and the directory to root - a requirement by the service launcher.

You can now test whether things went smoothly by executing the command "sudo SystemStarter start Tomcat". If things go well you will notice that no icon appears in your dock on launch. This is due to the Java parameter "-Djava.awt.headless=true" that we specified in the script "Tomcat" above. If you would like to keep the icon, just comment the line using a "#".

If things do not go well it's most likely due to some missing permissions. Check the logs in the utility application "Console" that you can find in "/Applications/Utiltities".

This post followed the German description by Kai Surendorf and adjusted things where appropriate. The "java.awt.headless" tweak was found on Hardy Ferentschik's blog.

Now I'm off to write a small Hudson/Growl integration app since the Java-based notifier available on Hudson's site didn't seem to properly invoke Growl on my machine. Maybe the recent Growl update or Snow Leopard broke the tool.

Stay tuned!

Follow-up on Versioning

While working with Hudson today and trying to get a CI server up for automated iPhone builds, I came across an article by Dave Murdock regarding versioning of iPhone apps. Turns out I did things slightly different to what is the - apparently - recommended behaviour:
  1. Use "CFBundleVersion" for your build number
  2. Use "CFBundleShortVersionString" for a version number like "0.1"
  3. Concatenate those strings within your application
This approach seems to be the standard behaviour in Mac OS X applications.

For integration with Hudson it also became apparent that updating the version number on Hudson builds using Apple's agvtool from within the Hudson build script was very straight forward and did not require additional files. So I'm basically using the Hudson build script as outlined by Michael with the versioning setup explained by Dave. Sweet!

iPhone and Unit Tests

Finally, following a series of posts on Luis de la Rosa's blog, I have Google Toolbox for Mac up and running my Unit Tests for iPhone.

Here's a quick note in case you choose to download the latest code from SVN instead of downloading the pre-packaged v1.5.1 from Luis' page: in addition to the files he copies to the sample project, you need to copy two additional files, "GTMObjC2Runtime.h" and "GTMObjC2Runtime.m", into your "UnitTestFramework" group within Xcode. With these files included, your build of the UnitTest target will work successfully.

Now having a look at the continuous integration suggestions by Michael Nachbaur. Let's see whether I can get a Hudson instance running and packaging both, my test targets and the final application.

Thursday, October 15, 2009

Automatic version numbering in Xcode

Here's a nice piece on automatic version numbering from within Xcode. The article details almost all the work you have to perform to get automatic versioning up and running.

Here are the missing pieces:
  1. Place the Xcode config file in the root of your project.
  2. In your Info.plist file change the value for "Bundle version" to something like "0.1 (${CURRENT_PROJECT_VERSION})" - depending on your choice for the variable in the config file.
With those two things in place, versioning should be up and running in no time. Thanks, Diego!

Friday, October 9, 2009

What a Fight!

I spent the whole day migrating a Grails-based application from a Linux / MySQL / Apache infrastructure to Windows Server 2003 / MS SQL Server / IIS. Here's my tale of this migration ...

Objectives:
1. Get Grails to work with MS SQL Server 2005
2. Integrate Tomcat into IIS so that no additional ports have to be opened on the server

Starting the day with the MS SQL Server migration, things went pretty smooth. I set up a custom environment "mssqlProduction" in DataSource.groovy using the driver class and connection string as outlined on the MS driver's homepage. Afterwards, I copied the MS driver jar sqljdbc4.jar into the project's "lib/" dir and generated the first .war file of the day (using "grails -Dgrails.env=mssqlProduction war" because of the custom environment).

Logging into the server, I installed Tomcat 6 in Program Files (x86) and encountered the first issue: the Tomcat service did not launch. Turns out that Tomcat 6 is delivered with 32bit binaries but since my system is running a 64bit OS, the binary failed to execute. Once I had replaced the binary with the 64bit version (which can be downloaded right from Tomcat's SVN), things were running smoothly.

Next step: creating a new DB and user account in MS SQL Management Studio so that Tomcat is able to connect. This worked like a charm (once I figured out how MS SQL Management Studio works). After I had adjusted user name and password in DataSource.groovy, I attempted the first deployment into Tomcat. As the Grails project uses the domain classes "User" and "Rule" and Grails automatically maps those to the tables "user" and "rule" respectively, the DB eventually gave some errors during deployment. "user" and "rule" are both reserved keywords within MS SQL Server 2005 and thus raise issues in SQL statements. Changing the "mapping" closure for each of the classes and adding "table 'new_table_name'" statements fixed that issue.

Without any further problems, the app was up and running within Tomcat using MS SQL Server as its DB. Sweet!

Since I did not want to open up more ports on the server, the second task of the day was integrating Tomcat with IIS 6. I basically followed the instructions given on the Tomcat website. Obviously, this didn't work the first time around and I had to go back and forth verifying the different Registry settings and the changes that had to be made in other places. My key take away: rename the redirect file to exactly what's proposed in the How-To as you're bound to run into problems if not.

Eventually, the Tomcat ISAPI filter in IIS came up green and was launched successfully. The problem, however, was that it was only invoked properly for certain virtual directories defined within IIS but failed to forward any requests to Tomcat (instead, I was greeted with Service Unavailable messages in my browser for any site I tried to access). Turns out that I had to configure the App Pool containing the jakarta virtual directory to have Local System as the account to run with. Now that solved the problem of the filter not redirecting any traffic to Tomcat.

However, when trying to access one of the Tomcat-managed sites, IIS was constantly asking me for my Windows logon credentials. Obviously something was off. After a lot of unsuccessful digging, I eventually changed the security settings for the isapi_redirect.dll to grant execute permissions to the IIS user account that was configured for anonymous browsing of the jakarta virtual directory. Another issue down!

Server's up and running now though I have seen a couple of things that I want to take another look at:
  • Currently, all filter files except for the dll (workers.properties, uriworkermap.properties, isapi.log) are stored in root directory as I was really struggling to get rid of the dreaded red arrow that kept appearing in IIS' ISAPI filter dialog.
  • Regular HTTP-authentication requested by a Tomcat-served page does not seem to work correctly.
Let's see whether we can crack those nuts, too.

Wednesday, October 7, 2009

Properties vs Instance variables

So being able to work with properties in Objective-C is very nice but there are subtle things to keep in mind when using them.

I just came across a problem which cost me about 30 mins of my time. In one of my methods I was (supposedly) assigning an object to one of my properties. The property was marked with retain so that it was supposed to be retained unless re-assigned or the owning object is dealloc'ed. Unfortunately, in a different part of the code, accessing that very property threw an exception.

Turns out that I hadn't yet mastered the subtle difference between properties and instance variable. Assume the following code sample:

@interface Foo : NSObject {
NSString* bar;
}
@property (retain) NSString* bar;
- (void) test;
@end

@implementation Foo {
@synthesize bar;

- (void) test {
NSString* str = @"Test";

// this assignment does not use the synthesized setter
// but accesses the instance variable directly
bar = str;

// same here
self->bar = str;

// only this way of accessing uses the setter and thus
// retains the object reference
self.bar = str;
}
}

First of all I did not know about the arrow-way of accessing instance variables, secondly I thought access as displayed in the first assignment would use the setter method.

Hope this helps in case you're ever going to scratch your head because of this!

genstrings / copystrings

Setting up an iPhone project I came across some weird behviour with genstrings / copystrings commands.

In principle, genstrings is responsible for searching your source code for macro statements of the form NSLocalizedString(@"keyword", @"description") and will place an entry in a (UTF-16) text file called Localized.strings for each macro it discovers.

Now if you use this command to generate the file, add it to your project, localize it (by Right-clicking on the file, choosing "Get Info" and "Make Localizable") everything works great. If, however, you create that file manually (in my case using TextWrangler) the copystrings command will fail during the build process. I'm quite sure that this is somehow related to file permissions on Mac OS X but couldn't quite figure out what was going wrong. After all, the file permissions that you could see in Finder were the same either way.

If anybody else came across this and solved it (got manual creation of that file to work), let me know!

Thursday, October 1, 2009

iPhone drawing

I'm not sure whether I just got bad at googling things but apparently, when I first researched bits and pieces about rendering stuff on iPhone, I did not find the way of rendering I was so desperately looking for:

Instead of diving into OpenGL ES right from the start, I was looking for a rendering mechanism similar to what J2ME offers: subclassing Canvas, overriding the paint() method and adding all of your drawing calls to that method.

For iPhone I expected to find a similar way of rendering and, sure enough, came across Quartz as iPhone's 2D rendering library of choice. What I did not find, however, was the part where I subclass and add the statements to a particular function in my code. Now, reading the first few lines of Dave Mark's and Jeff LaMarche's chapter on Quartz and OpenGL ES (from their book Beginning iPhone 3 Development), I finally found the missing piece:

  1. Subclass UIView
  2. Override drawRect:
  3. Add Quartz-calls

If you're wondering where you can get a handle to the Graphics context (that you'll get automatically as an argument to the method in J2ME), you use UIGraphicsGetCurrentContext() to get a handle to it.

Maybe this post looks dead-simple, I just hope some people will find it in their quest to discover the information I was looking for myself :-)

Saturday, September 26, 2009

Mac Security - follow up

After recently reinstalling my iMac to make sure that it's save, some time has passed and things seem to be secure. LittleSnitch takes good care of my internet connection and, so far, I have not spotted any troublesome activity.

Obviously, I'm curious to know whether my system had been compromised at all. I cannot find out, however, since I just completely formatted the hard drive once I had decided to reinstall. I just came across an interesting article at heise.de, though, which discuss the value of compromised Mac systems. The article cites the analysis of activities within a malware community called Partnerka where, apparently, malware had been distributed through video codecs.

Before the infection I had actually tried to install video codes for decoding some weird formats I came across. Could this be the explanation for the troubles I had with my system? In any event it is interesting to see that, contrary to popular (internet) opinion, malware people and botnets are targetting Mac - and seem to be successful doing so.

Thursday, September 17, 2009

Adobe AIR, Flex and Mac OS X Dock behaviour

Here's a quick pointer implementing the common behaviour of hiding windows when clicking the Exit button used on Mac OS X. Clicking on the dock icon will make the window visible again.

Article at ThanksMister

Thanks, Mister!

Tuesday, September 15, 2009

Probabilities in Monopoly

I just read some paragraphs in a book called "The Art of Game Design: A Book of Lenses" by Jesse Schell. It really is a very interesting book, analyizing the design of games from a rather theoretical standpoint but giving rules of thumb that can guide your designs.

Anyways, the paragraph I read was an introduction to probabilities for game designers. It was really well-written and a fun read. One thing I have to comment on, though, is the statement that it is "nearly impossible to calculate the probabilities of landing on a particular field in Monopoly using theoretical means" (in contrast to simulating a very, very long game). It actually can be done with good thought and knowledge of Markov Chains. Googling a bit, you will find really nice articles analyzing the game of Monopoly in this regard. This place might be a good start.

So now that I've given this one away, let me know whether you succeeded in the game by purchasing the most likely fields!

Monday, September 14, 2009

SSL errors in Firefox

Since recently I have noticed that Firefox, every now and then, tries to access two servers using SSL that have no valid certificates. Both servers are accessed without me requesting anything so it must either be something that another website is using (the last times this has happened I had Gmail open in one of my tabs) or something else is trying to open.

One server is int.fmsolutions.pl which returns a "sec_error_unknown_issuer". I have no idea why anything would try to connect to that server so I'm slightly worried again. My password paranoia is back :-S

Anybody knows what that server does? Googling only reveals one dodgy SMS login page ...

The other server was a subdomain of blue-cdp.com which belongs to a company called QPASS. I know these guys from previous work experience where they have acted as a content management solution for a mobile operator. Why would anything on my system connect to that server? The SSL error I see mentions a problem with the server mentioned in the certificate: it contains a wild-card character '*' but that does not seem to match the server my Firefox tried to access.

Is there any option in Firefox that allows you to see the exact history of URLs that have been accessed recently? Like a log or something?

Tuesday, September 8, 2009

Mac Security - part III

No Blizzard mail since last night informing me of another account cancellation - even though I used my Mac to play and installed one of the addons (QuestHelper). LittleSnitch only detected regular communications going to Blizzard servers. No strange behaviour. I start to feel save again.

What bugs me is that I still don't know what exactly happened. The only thing I can think of is that, while installing WoW, I downloaded the installer file from a non-official source. This might have been a modified file contain a Trojan or something. Seems rather unlikely, though ...

Monday, September 7, 2009

Mac Security - part II

My account has been re-activated and Blizzard was kind enough to delete all the characters that had been created without my knowledge. I logged in to their website and changed my password on my Windows machine - which has been equipped with ZoneAlarm in the meantime. Afterwards, I logged in using the game client (once I deleted all the add-ons I had still installed) and verified that things were in order. No breach of security so far (which is about 10 hours).

I'll be courageous and will log in using my iMac now. Fingers crossed that re-installation fixed the issue.

Sunday, September 6, 2009

Menus with cocos2d

If you intend to use the Menu class in cocos2d, remember that each method used as an invocation target by a MenuItem must take exactly one argument which is going to receive the object that invoked the method. If you don't conform to this, you will see an error message like:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSInvocation setArgument:atIndex:]: index (2) out of bounds [-1, 1]'

Here's a sample method that will work:

- (void) doMenuItemAction: (id) sender;

Saturday, September 5, 2009

Mac Security

I consider myself a savvy computer user: have been online since well into the 90ies and have programmed loads of apps on desktops, servers and mobile devices. With my approach to using passwords and navigating around the web I felt fairly save - till just recently.

To drive some iPhone development, I have recently switched to a nice 24" iMac (this doesn't add any value to the story - am just bragging here). Like probably a lot of other users I felt fairly save with my OS X setup and I didn't worry too much about the security setup: I did not install anti virus software nor did I install a personal firewall of any sort. The system is sitting behind a router, though, so direct connections to the system are not getting through.

Now here's the fun part: since a couple of months I have been playing - and now I admit to it publicly - some World of Warcraft. There were never any issues with my account as long as I was on my Win XP machine. Once I got the iMac I installed WoW on that system since it's way more powerful than the laptop I had been using before. Things worked smoothly (except for a really bumpy install process) for the first couple of days or so but this week I received notice from Blizzard that my account had been cancelled permanently due to involvement in online trading activities.

I surely was surprised by this since I have never done anything illegally within the game. I sent Blizzard a notice on re-activating my account since I hadn't done anything violating their ToS and, after a couple of days, received notice that they had reset my password and I could start using the account again. Immediately I went to their site and picked a new password *that I had never used before*. The password was of ok strength, I think, looking similar to "bla5623bRealm". I logged in to my account and noticed that, indeed, two characters had been created within my account that I didn't know of. I deleted those characters, verified that nothing majorly had happened to the other chars and logged off to get on with work.

About four hours later I receive another mail from Blizzard, cancelling my account again due to the very same reason! Through the WoW iPhone app I could see that another six or eight chars had been created within my account. I have, obviously, not shared my password with anybody, not posted it on any websites and - most importantly - I have never, ever used it before. Now I'm obviously quite concerned about the security of my system since the explanations which do not imply that my system has been pwned (brute-force attack, Blizzard people using my account, hackers breaking into Blizzard servers) are fairly unlikely.

Scanning my system using popular virus scanners and rootkit detection software did not detect any oddities and, eventually, I chose to re-install the Mac. Obviously, if something like the keyboard hack made it into the wild, a reinstall won't fix anything. Is there anything else I should've considered as a possible means of intrusion?

Which also leaves the question through which means I might have received the evil intruder. Have only used a couple of very popular WoW add-ons and software that was recommended on websites. No pr0n apps, no illegal software. Any comments are very much appreciated - I'll post follow-ups as the story develops.

BTW, is there any easy way to download the firmware from my keyboard for checksum comparisons? I must look pretty paranoid :-D

Thursday, September 3, 2009

Extending cocos2d

Today was my first real day of doing something vaguely productive using cocos2d on the iPhone.

I coded an animation creation framework (aptly called Pixel Animation Studio) some months ago which can be used to compose animations using 2d pixel graphics. Basically, an animation is broken down into frames which in turn are broken down into small fragments. This technique encourages reuse of image fragments and can save a lot of space normally wasted by duplicate content in images. I guess you can see my background as a J2ME engineer shine through ...

Anyways, to support the animations created using this tool, I need a Sprite class that can be assembled by rendering multiple images instead of a single texture. To get this working, I investigated the CocosNode, TextureNode and Sprite source code to see, how rendering is performed deep within cocos2d. Turns out it's fairly easy to do:

cocos2d already handles most of the behaviour you need for a Sprite in CocosNode. It takes care of position translations and rendering all the sub-nodes added to a CocosNode. Now you just go ahead, sub-class CocosNode and add all the images you'd like to render as children of type Sprite (or AtlasSprite). cocos2d will take care of the rest!

Since the animations produced with Pixel Animation Studio are slightly more advanced than the ones provided out of the box by cocos2d (btw, I didn't realize plain 2d, frame-based animations were supported out of the box to begin with - they are just not properly highlighted as a feature on their site), I also had to implement a new IntervalAction. That's pretty straight-forward, too: just subc-class and override the + (void) update: (ccTime) time method. When instantiating, keep in mind that cocos2d takes parameters in seconds for the actions which accept a duration parameter, not in milliseconds.

Wednesday, September 2, 2009

+ (void) load

I just happened run into one of those things that must happen to you if you just go out there and try to learn a new programming language from scratch without using any tutorial books.

Just for the sake of getting started with some Objective-C coding, I'm implementing some 2D animation functionality based on an animation tool coded in Java. Trying to load the files its creates using Objective-C, I implemented a method called load in one of my classes. Things got properly loaded - but, to my surprise, I also saw some error messages in the console hinting at leaking memory. An autorelease-pool was set up in my main class so I was wondering what could possibly have gone wrong.

Turns out + (void) load is method defined in NSObject class which is used for initializing objects. It got called even before my autorelease-pool was initialized, thus the leaking. Keep that in mind if you see error messages saying "No autorelease pool in place" or "Just leaking" even though an autorelease-pool is set up in your main class.

Wednesday, August 26, 2009

Xcode and SVN

Today was my first time trying to work with Xcode 3 and Subversion. Using two separate Macs to check out the shared project from SVN, I quickly discovered that it was not as straight forward to work with Subversion from inside Xcode as I had hoped (and come to know from NetBeans and Eclipse).

First of all, only one of the Macs successfully set the SCM repository after the checkout on the other one I had to manually set the repository after checkout. I think I did the very same steps on both Macs but behaviour was different - how strange.

Next thing I noticed: if you'd like to update your project but have a file already displayed in the editor, make sure you use Refresh Entire Project before selecting Update Entire Project. It seems that without calling Refresh, the file is indeed updated on the file system but the change won't be visible within the editor unless you choose a different, external editor to open the file.

If anybody can shed some light on the issue, let me know in the comments!

Friday, August 7, 2009

JsUnit

If you happen to run into problems with the Test Runner page of JsUnit in Firefox, try setting the property Security.fileuri.strict_origin_policy on your about:config page to false. Unless you do that change, the Test Runner will come to a halt while displaying the "Opening test page ...." message.

Wednesday, August 5, 2009

Transaction Logs in MS SQL Server 2005

The other day I tried to find a solution for an excessively large transaction log file in one of our production systems. It grew to an astonishing 40 GB which set off some alarms. Our middleware service provider offered to take care of this problem for a rather high monthly fee that I didn't feel like paying: after all, how difficult could it be to shrink that stupid file and keep it under control?

Turns out it with a little trickier than I thought. I, actually, have never used MS SQL Server before and have never come across any transaction logs I had to take care off. In my previous server-based project we worked with MySQL which did not provide such a facility (and I shall stand correct if you show me where I missed it). So off I went to find some information about the transaction logs for MS SQL Server and, in theory, things were supposed to be easy: execute two SQL statements, one backing up the transaction log, the other shrinking the log file - that's it.

Backing up worked (with a 40 GB log it took quite some time, of course) like a charm but shrinking did not seem to work. Once I found the command
DBCC SQLPERF (logspace)
I was at least able to verify that the backup had worked and had really set the records in the log to inactive. After some more trial and error I found that I had just passed the wrong parameter to shrinkfile: instead of the database name it expects the name of the log file (excluding the file extension.

A long story short, the following two commands executed in SQL Management Studio will successfully backup and shrink your transaction log file:
USE [database];
BACKUP LOG [database] TO DISK = '[filename]';
DBCC SHRINKFILE ([name of transaction log without extension or quotes], 1);
Here's a more tangible example:
USE BenDB;
BACKUP LOG BenDB TO DISK = 'C:\Backup\BenDB_log.bak';
DBCC SHRINKFILE (BenDB_log, 1);
Hope this can save you some time one of these days.

Tuesday, July 21, 2009

Generalizations of the TSP

Here's my first post in a row of posts detailing what I'm doing in my thesis - and for what it's good. Typically, math students don't necessarily know whether the contents of their thesis can be applied to anything in the real world at all (I'm exaggerating - but for most of them, it's more difficult to find the connection). In my case, however, it's pretty straight forward:

Imagine you're working for UPS and you pick up your truck at 7am in the morning to start your delivery tour. Now, if you're a clever driver, you might want to take a moment and consider how to best approach today's deliveries: what's the shortest (or cheapest or fastest or ...) route to take through town delivering all the packages and, after the last delivery, returning to your depot. That's the Traveling Salesman Problem (TSP) - a very classic example of a problem that's hard to solve to optimality.

Now UPS offers clients to dispatch packages with high or normal priority. High priority packages will be treated with a higher urgency and will typically be delivered before a normal priority package is delivered. In addition to that, a realistic constraint for the delivery of packages is to impose a latest time for delivery, say you have to finish the delivery of all packages by 5pm (receptionists leave rather early, I hear). Trying to come up with a tour for the driver that takes both extensions into consideration (prioritization of deliveries and maximum time allowed for delivery on a single day) is a generalization of the TSP - the Orienteering Problem (OP).

There are a lot more variations of the original TSP. The OP, however, should give you an idea of what such a variation / generalization can look like. In my thesis I'm having a look at these kind of generalizations and trying to come up with algorithms that will solve them to optimality (ie. we find the best tour possible, guaranteed!) but take a lot of computation time or algorithms which only come close to the best tour (which we cannot guarantee, however :-( ) but are fairly quick.

That's enough for a first post - I don't want to scare anybody away before the real fun starts. In the next post I'll try to give a low-math overview of how one can tackle these problems. Let's see whether that's possible!

PS: For the nit-pickers out there: the OP is not really a generalization in the sense that you can solve the TSP by means of an OP. I still like to call it a generalization so bear with me.

Monday, July 20, 2009

IIS and ASP.net

This morning I had to deploy an ASP.net-based application to an IIS. Everything had worked fine on the development system but once I deployed it on our production system, an error message was displayed that didn't give me a clue about what could possibly have gone wrong:
Error initializing the AppDomain
Quickly followed by another error:
The request could not be processed because the application domain could not be created. (translation of Die Anforderung konnte nicht ausgeführt werden, weil die Anwendungsdomäne nicht erstellt werden konnte.)
Google didn't find clear steps to fix the issue but hinted at file permission problems. In fact, I had just extracted a zip file on the server into the application directory instead of creating one manually. Therefore permissions of the containing folder were not reused and just set to some defaults. Comparing and adjusting the file permissions (Security in context menu) of the directory with the permissions of the Inetpub directory fixed the problem.

Sunday, July 19, 2009

OpenGL origin

Looks like OpenGL is just doing what all the other 3D frameworks are doing, too. At least this article implies that 3D frameworks generally adopt the maths view of having the origin in the lower left. Good to know!

cocos2d

First time really trying to get something done in iPhone SDK. After struggling ages getting a simple game loop to work - only to discover that I was calling the update routines on the wrong thread - I found a forum post which talked about the cocos2d iPhone 2D game engine.

Have now spent most of the day working on a simple Memory-like game. The engine is pretty straight forward to use once you get to know the APIs. There are a couple of things I didn't quite figure out this time, though - any insights are appreciated:

  1. Is there any reason why rendering origin in iPhone / cocos2d / OpenGL seems to be lower left corner instead of upper left? It sure matches the mathematical way of thinking about an origin but AFAIR most of the other frameworks have their origin in the upper left, don't they?
  2. To render the game board, I have assembled a Scene using a Layer and a couple of Sprites contained in that Layer where each of the Sprites was supposed to be touchable. I haven't found a way to get that working other than reacting to touches on the Layer and manually checking whether the touch fell within the bounds of one of the Sprites. There must be a better way to do this, right?
  3. How does memory management work when you replace Scenes using the Director singleton? You access the Scenes via [Scene node]; so I assume there's autorelease at work.
  4. Why do Texture2D.pixelsHigh / .pixelsWide return different values than Texture2D.contentSize?

Friday, July 17, 2009

MacBook Air

Here's another one to start off with: did Apple ever test the first edition MacBook Air in summer time? Don't get me wrong, I love the Air for it's gorgeous design but I just can't stand its' performance!

Even on colder days, the thing becomes so hot it's barely touchable (at least around the ESC-key). But in summer-time, the thing is hot by default! If it was just for the heat, I can live with that. Whenever it's hot, performance goes down big time, however, down to a point where any letter you type is only displayed on screen about a second later!

For something as expensive as the Air I would've expect more. Though, as far as I know, the second edition Air does not have the performance problems anymore (it still gets very hot, though).

iTunes and Single Tracks

So iTunes has this great view on your track collection where you see the cover art for each album you own, one by one.

But every now and then this list is cluttered by album which only contain a single track - it's like having the single, which you love, but not going for the full album. I have loads of those tracks and they mess up my albums view.

Why doesn't iTunes filter those one-track or two-track albums and create a single album entry for those labeled "My Single Compilation" (well, any name will do, I guess) and file all of them into that album entry? The cover art could be a nice patchwork created from each of the individual track's album art.

Hey, Apple, give it a thought!