Skip to content

Archive

Category: iOS/Cocoa

I’ve been itching to write about something interesting (it’s been a while) but today all I’ve got is a sticky crash that bubbles up fairly anonymously in the organizer.

I’m suspecting this has to do with graphic memory allocations.

Found a great article about VM tracker here:

And a no-less-informative article from Ray Wenderlich, here:

As in the Ray Wenderlich article I see process/type as unknown/unknown (how elegant). However I don’t get jettisoned.

Instead I get [vm] under ‘reason’ and the statuses of my app are:

(audio) (frontmost) (resume)

So, given that texture allocations are a likely reason for memory shortage, I think I’m on the right track. Reading a stack overflow item, I also find that the number of pages used by my app at the time of crash looks dangerously similar to what I get, so if you feel worried you may be gobbling too much memory, have a look here for comparison: http://stackoverflow.com/questions/13152502/my-app-crashes-and-closes-down-and-there-is-very-little-information-as-to-why

Yea that’s it for me so much for the exciting stuff.

One word of CAUTION: modify build settings at your own risk. These are MY build settings. Pending our next release, I cannot confirm that these build settings will even work for us.

Project Settings

Architectures

  • Base SDK: latest
  • Valid Architectures: armv7 armv7f armv7k i386
    => I exclude armv6, see ‘Deployment’ section. If you go down that road, make sure to add ‘armv7′ to ‘Required Device Capabilities’ in your info.plist (for the flip side of this, see this stack overflow item ).
    => Once I excluded armv6, my code wouldn’t run into the simulator, with the compiler broadcasting a ‘no architecture to build for’ error. Adding i386 resolves the issue. 

Build Options:

  • Compiler: Apple LLVM 3.0
    => Provisionally.
    With one of our libraries I build with GCC 4.2 because builds will stall with LLVM and (-O2/-O3/-Os). With the same library compiled against Apple LLVM 3.0 , GDB crashes. 

Deployment:

  • iOS deployment target: iOS 4.3
    => targeting iOS 4.3 excludes 2nd generation devices ( ~3.5% of iOS market ) ; more helpfully, this strategy avoids targeting devices that are too slow to run high performance applications.

Code generation:

  • Optimization:
    • Debug: -O0
      => aggressive optimization may confuse debuggers
      => 1.1x to 2x faster build times depending on compilers.
    • Release: -Os or -O3
      => I favor -O3 because our codebase is ‘small’ so I’m not overly worried about executable size. How small is small? Less than 64k lines of code.
  • Relax IEEE compliance: YES
    => The compiler switch for this is -ffast-math, which is what we’re after. Won’t work if you use isnan(x) or other functions.
.
Unit test targets
.
  • Build active architecture only : YES
    => reduces build time

XCode notes

  • Code generation settings are under project > Build Settings > Code generation
  • The ‘main switch’ is under LLVM GCC 4.2 > Optimization level.
  • You can pass additional flags under LLVM GCC 4.2 > Language > Other C flags
LLVM or GCC?
In the best case scenario you can pick between 3 compilers. I don’t have benchmarks; the overall feel from reading around is that GCC may generate faster apps.
Incidentally, my system stalled while building a C++ library with -O2/-O3/-Os turned on (LLVM GCC, LLVM 3.0). Adding -fno-inline-functions to Other C flags ‘fixed’ the issue. But now, that’s quite note what I wanted to do. Switching to GCC 4.2 solved the problem (the target library wraps basic maths with inlines; enforcing inlining yielded 10-15% gain).
.
Read here?
.
Thumbs up?
.
On ARMv6 ( iPhone 3GS and earlier), turning thumbs off, used to yield a dramatic performance increase on floating point calculations. Well not anymore. Put in a better way, there aren’t many ARMv6 devices around anymore ( ~3.5%? )
.
I tested an FP intensive task and observed a marginal improvement ( maybe less than 3%) with an iPad2.
.
-/O0/O1/O2/O3/Os
.
I was curious to see whether -Os (smallest/fastest) would perform significantly worse than -O3. It doesn’t – well not in my case. I observe about 4% speed increase between -O2/O3/Os and -O0 (-O0 : no optimizations).
.
I tested this on a graphic application running OpenGL ES 1.x . I measure the performance increase by looking at % usage per frame for non GPU tasks (In my case, the CPU/GPU balance is fairly even).
.
Measuring performance
.
Running with GDB or Instruments turned on will slow down your app; a crude way to measure release-grade performance may be to stick a frame rate meter right on top of your UI (now that is common practice, right?) and check with an unplugged device.
This won’t tell you where your overheads are going. For this, I still find Instruments an invaluable help.
.
I’m looking at averaging performance over one or several game sessions to get useful figures. Formal test cases can help solving specific performance issues – keeping in mind that optimization issues and level design strongly interact.
.
Stuff that looks interesting
.
.
Conclusion
.
With a background in Java and other virtual languages, I find that playing with compile time settings is, overall, almost a waste of time. Sadly (cf. the thumbs episode) it isn’t always quite so.
.
Wasting a day on belittling tweaks and flags from time to time isn’t altogether bad.

Recently I experimented with various ways of configuring data programmatically.

Okay, I’ll say loud what some will be thinking when reading this. Why not use an XML file?

Well… no. Not unless you need to store this data, share it… load it over a network… (then, yes). In many other cases, using hard, compile safe code to assign values and configure objects, has advantages.

  • XML data without a validator (including build system integration) is no better than interpreted code.
  • Without a template (and a convenient editor driving the ‘form filling process’) XML data is tedious to write and tedious to maintain.
  • Hard-wired configs break at compile time. Data loaded from XML files or CSV rarely breaks before runtime.
  • There’s no point in writing data formats and validators for data that changes often – for example when a codebase / paradigm is relatively ‘fresh’.

So I’ll go with hard-wiring and try to figure a decent pattern for it. I’ll use macros if I have to, and avoid them if I can. I was, then, looking for a patterned way of configuring my data, and I came up with this:

  1. Have a class Foo, need to configure instances of Foo.
  2. Created an interface IFooSetup, specifying getter methods for configuration data: getA(), getB(), getC()… etc… etc…
  3. Created a class FooDefaultSetup <IFooSetup> providing a default configuration.
  4. Created multiple subclasses of FooDefaultSetupBlueFooSetup, YellowFooSetup, GreenFooSetup etc etc…

Not just I won’t do it again (at least, not in ObjC). I will also refactor my code.

Why is this approach troublesome – why did I come up with this idea in the first place?

Setup interface/protocol

IFooSetup is a protocol dedicated to helping programmers configure instances of Foo. Sometimes it can work. One advantage of using an interface is that (inside an IDE) it works much like a form (a piece of paper with blanks that one needs to write into). The compiler helps the programmer ensure (often, in realtime) that all required config parameters are set.

So good so far (and I don’t care whether anybody’s bothered writing a class just to configure another object).

Maybe it is a pattern, then. A fortiori, however, it does take a couple of useful language features for this to actually work.

Default config class

Sooner or later, the idea of creating a class named FooDefaultSetup will arise. Why, because several objects shared common parameters. It is logical.

Unfortunately, although some languages allow abstract classes, ObjC does not. As a result, once we go with FooDefaultSetup, we have to implement all the methods declared by IFooSetup, including getters for which FooDefaultSetup can supply no meaningful default – and as a result we have just short-circuited the usability of IFooSetup – it no longer works ‘more or less like a form’ – to determine what methods we’d like to override, we have to check the source code for IFooSetup.

Breakable code.

No real mess will start until we change the signature of a method in IFooSetup. At this point, it would be neat if the compiler could help us make sure that the many, many implementers of IFooSetup (BlueFooSetup, YellowFooSetup, … ) are updated accordingly, alas…

  • Some languages (quizzically, the defunct Javascript 4) will have you tag every method intended to override a method up the inheritance chain. This means that you can’t accidentally override methods. It also means that you get an error when the method no longer overrides another method. Not so in ObjC
  • Other languages won’t let you implement a method that hasn’t been declared. Not so in ObjC.

What happens, then?

FooDefaultSetup is somewhat maintainable since it must implement all methods in IFooSetup.

Sadly, none of the subclasses of FooDefaultSetup are maintainable. Forgetting to update/correct the method signature for any of these subclasses is now the easiest thing in the world, resulting in code never being called. Not just any code, but sound, simple, honestly good looking trivial code that mainly consists in getters.

A little down the line we’ll be looking at bugs and wondering why an object doesn’t behave as expected, the trivial reason being: configuration code is out of date, and the compiler knows nothing about it.

K.I.S.S

So, yea… never again. Instead of configuring objects in this way, I’ll sooner do the following and be better for it:

  • Keep it simple, stupid. Configure an object by calling accessors on this object.
  • If you need a ‘checklist’ of what needs to be configured… consider copy-pasting the config block from another, similar object. Or write a checklist. Or write a validator.
  • At least when an accessor’s signature changes, the compiler will warn against all and every deprecated use of the modified method.

In case you’re not getting it from the title, I may not have learned anything substantial while writing this article. I just created yet another static library, tried linking it against another, and there goes XCode (build 4C104) NYAAAAN.

Since I used to write my own coding tools, I bloody well knew how to compile a java (sigh) program on the command line. I also wrote tools in such a way that they found jars in myland (comforting it was, however restrictive).

XCode workspaces are meant to improve the (sodding) developer experience when dealing with complex projects. Don’t get me wrong, I’m all for wizardry – Clearly, however an ignoramus ex machina is usually at work when I try stringing libraries together.

Useful notes?

Check this article from the Carbon Five blog for useful notes about linking static libraries. I’ll provide a new article on this topic at some point. I just wasted a couple of hours clear because this stuff is having its way. Here’s a lame summary of what I found:

  • Like pixies, build issues appear when you least expect it. Sadly they also disappear mysteriously as soon as you try getting to the root of the problem.
  • You can fix build issues by fiddling:
    • If at first you don’t succeed…
    • Don’t assume a library won’t get found because it appears ‘marked red’
    • Don’t assume a library will get found because it doesn’t appear ‘marked red’
    • Assume duplicate items can easily arise when adding libraries to a project.
    • Remove duplicate items whenever you stumble on them.
    • Play with the ‘Location’ combo (relative to group, relative to project etc…).
  • Don’t be afraid to check build logs. The paths often look infuriatingly convoluted, but while you’re poking around to find what’s really gone wrong, the problem is getting itself fixed (and at least you’re kidding yourself that you have something to do with it).
Need I say this is only the beginning of an idiotic battle? I will get to the bottom of this (if there is one).

The case

Okay, let’s say I made a library called ‘foobar’ (I actually did)

Initially, under ‘products’, libfoobar.a is red. In my file inspector the location is relative to build products (and cannot be changed)

For sake, build (don’t add any source file) and check what happens: nothing. Well that’s good, innit? No source files, no library.

Now, add a source file and rebuild. Check the messages window. We now have 3 items: Precompile…, Compile… and Libtool.

Under Libtool, we can see the intended location of the output:

-o /Users/johndoe/Library/Developer/Xcode/DerivedData/workspace-fdpyddpbphekphdqtzzutyjcagva/Build/Products/Debug-iphonesimulator/libfoobar.a

Feeling paranoid (would Libtool ever lie?) we can verify that the library has been created by browsing to this path (Finder is gracefully setup to overlook whatever path this stuff goes under).

But the item still appears ‘marked red’ under ‘Products’. Suspicious?

Can’t copy libfoobar.a?

Now let’s try linking foobar against a target inside another project (same workspace, right?). Open project settings (yea click on the project in the navigator), go to Build Phases > Link Binary With Libraries, hit the [+] button. A cute browser now appears with libfoobar.a under Workspace (or whatever your workspace is named). Select libfoobar.a, press return and… *build*.

Mind, this operation adds an item to your project, now also visible in the navigator (libfoobar.a, still marked red).

If there is an error, it may look like this:

error: /Users/johndoe/Library/Developer/Xcode/DerivedData/workspace-fdpyddpbphekphdqtzzutyjcagva/Build/Products/Debug-iphonesimulator/../../../../../../../../svn/components/base/build/Release-iphoneos/libfoobar.a: No such file or directory
Command builtin-copy failed with exit code 1

What’s going on here? Let’s go and check the added library item inside our project (select the item and make check sure the inspector is open). I see this:

Location: relative to group

Path: ../../../components/base/build/Release-iphoneos/libfoobar.a

Clearly not right (yet, consistent with the failed copy operation)

Fancy patching the path manually?

Location: relative to build products

Path: ../Debug-iphonesimulator/libfoobar.a

Worked for me, but not right away. Digging around I found yet another duplicate of the same library reference (marked red!). Removed it, cleared (what appears to be) the same item under ‘build phases’ and re-re-re-added it all over again (this time by checking the box I wanted in ‘target memberships’).

Not happy

I felt somewhat unconvinced (notably, I’m not happy with the Debug-iphonesimulator part of the relative-to-build-products-path – how’s that supposed to backfire?).

So I removed the library altogether and started over. Just repeated the initial steps going by the book… sadly it… worked.

Until next time.

This article is a revision of a previous article I wrote about unit testing with XCode.

I describe the steps carried to setup a test target long after a project has been created, so initially the test target will lack most of what’s needed to operate correctly (e.g frameworks, libraries and source files)

Setting up may take up to a few hours.

Creating a test target isn’t a big deal (just go to the project panel, add a new target and follow the steps).

I expect tests to run every time I try to build/run the main target. If the tests won’t pass I’d rather not fire up the simulator.

By default, the test target is not setup to work this way. Maybe it makes sense (after all, how does it know which target to depend on).

  1. Go to project panel => build phases ; add the test target under target dependencies.
  2. In the project panel, open ‘build settings’ for the test target, search for and tick ‘Test After Build’.
Note: You can also edit the scheme for the main target; under ‘testing’, add the test target. However doing it this way won’t action tests every time you run the application; you’d have to select the test action instead of run (top-left of xcode window, press and hold the ‘run’ button).
Up to ‘housekeeping’, the steps described below are likely necessary. Try to build before/after every step and check build messages to help you move on.

1. Adding source files

Maybe the fastest way to add your .m files: go to Build Phases and scroll to ‘source files’, then press add. type *.m as search filter. If you have many groups you may need to do this a few times to include all the required files.

2. Disable/Enable Automated reference counting.

In your test target, under build settings, search for ‘Reference counting’ and tick/untick “Objective-C Automatic Reference Counting”

3. Replace/Edit precompiled headers

In build settings, search for ‘pch’. If possible I just copy the *.pch from my main target settings to the test target settings.

4. Add the required frameworks & libraries

Most of this should be copied from your main target. Opening the assistant editor so you can compare/check both targets at once is useful (see build phases > link binary with libraries).

If you miss a library it will result in countless unresolved dependencies so it’s easy to figure.

5. List additional headers

If you’re pointing at additional headers in build settings, ideally you can share definitions by declaring them in the project’s (not the target’s) build settings – target-specific entries can be overwritten using $(inherited).

Housekeeping

Keep your framework/library references tidy: Checking the list of frameworks/libraries included in your project (there may be some in several places) may be a good idea as (harmless) duplicates may arise.

With frameworks/libraries, getting ‘red files’ is not rare. In many cases this doesn’t mean anything is actually broken (sigh…)

Remove unused files: remove files created by the wizard, if unused (e.g. precompiled headers)

Rename/Regroup: Renaming/Regrouping may cause references to break and need further editing. It’s a bit fidgety so you’ve been warned.

I like using generic names for my source folders (e.g. not MyApp Tests/ , just test/ ) and certain files (info.plist instead of MyAppTests-Info.plist). Renaming the info.plist will require editing in build settings etc… so maybe it’s easier to leave things as they are (XCode can help you rename project items).

Caveats

Beware that some classes in related libraries may rebuild after setting up the test suite; if old files were lingering in the system this may cause errors and confusion. Clean the build if things start looking weird.


We use blender to create game assets; we also use blender as level editor. Blend files are exported to our proprietary format using py scripts.

Exporting files manually is okay… to a point. Soon we find out not only that exporting files manually is a chore, it contributes to creating a beautiful mess.

How to automate the conversion? With XCode, it can be done using build rules. I’m covering the following points:

  • Build integration – add files to your build, automatically translate them using utilities and include the products in your app bundle.
  • Defining useful build rules.
  • Invoking blender from the command line.
  • Modifying blender scripts so that they won’t crash in a windowless environment.
  • Signaling export errors (notably, errors generated by a script running inside blender) using XCode.

While we have a mixed workflow (Blender 2.49 / Blender 2.61), we’re dominantly using 2.49b, so I started with the older version. I’ll be covering 2.61… later.

I used the following articles as a starting point:

This article is not concise; I’ll summarize my findings in a coming article.

The experiment

The first step is to configure build rules to process *.blend files I guess, so in a first approximation I used this:

  • Source files with names matching *.blend
  • Custom Script: /Applications/blender/blender.app/Contents/MacOS/blender ${INPUT_FILE_PATH} (bad)
  • Output Files:
    ${TARGET_BUILD_DIR}/../../${INPUT_FILE_BASE}.scg (bad)
I just thought it would be interesting to try this way although it’s obviously not complete. And indeed, it was.
First surprise, Blender opens in a window. Good for testing (notably because it’s displaying errors already; for a nice smooth build I’ll want to disable this).
Both Blender & XCode are displaying messages in the XCode errors & warnings panel, which is nice.
The initial problem is path related. The file won’t open because spaces in the path are incorrectly interpreted. So the correct form to open the blend is like this:
  • /Applications/blender/blender.app/Contents/MacOS/blender “${INPUT_FILE_PATH}” (good)
Running the script is the next obvious step. For now blender just opens and idles happily until I quit. So I modify my command, like this:
  • /Applications/blender/blender.app/Contents/MacOS/blender -b “${INPUT_FILE_PATH}” -P qwagga.py (bad)

-b to tell blender to ‘render in background’. -P qwagga.py is the wishful step to run my script hoping that scripts are being run from the blender scripts folder. qwagga.py is my export script. There will be a problem with that but let’s try anyway.

Indeed, -b prevents the blender window from opening. Blender is reporting (via XCode) that qwagga.py wasn’t found. Interestingly it would appear that -P could also refer a script included inside the blend file (text node). For now, however, I’ll just provide the full path.

  • /Applications/blender/blender.app/Contents/MacOS/blender -b “${INPUT_FILE_PATH}” -P /Applications/blender/blender.app/Contents/MacOS/.blender/scripts/qwagga.py (good)

Yea this works. As you’d expect since the exporter is trying to pop a file selection panel the script crashes with a fairly explicit message:

File “/Applications/blender/blender.app/Contents/MacOS/.blender/scripts/qwagga.py”, line 213, in <module>   Blender.Window.FileSelector(exportAssets,’Export to File’,PATH)
RuntimeError: the file/image selector is not available in background mode

This error can be patched easily:

    try:
            Blender.Window.FileSelector(exportAssets,’Export to File’,PATH)
    except RuntimeError:
            OUTPUT=Blender.sys.makename(ext=’.scg’)
    exportAssets(OUTPUT)

Telling XCode where the ouptut is located turned out to be a nag. The docs aren’t overly explicit about what environment variables can be used. As it turn out, however, whenever running a custom shell script (like, what we are doing now) the messages window displays a whole batch of setenv commands. That is all we need to know. I adjusted my entry in output files accordingly:

  • ${INPUT_FILE_DIR}/${INPUT_FILE_BASE}.scg

Immediately after I got this work, it seemed there was ‘a bit of weirdness’ in XCode (an error I couldn’t make sense of). For whatever reason this cleared after cleaning the build and re-saving my blend file.

It appears that each file is getting processed/converted whenever building (even if the input file hasn’t changed). I’m a bit worried about how this will turn when I have 200 blend files linked in this way – since blender loads almost instantly I’ll just wait and see.

Single input => multiple output

Now, the above looks quite useful but there are issues:

  • My py scripts don’t output just one file.
  • In fact I have two py scripts used in blender. One outputs a single file, the other outputs a whole lot of files. The names of the files match object names in blender
I would hope that both Blender and XCode can handle this situation gracefully.
For proof of concept, I just hacked a different output file path and created a file hierarchy looking like this :
  • blends
    • car_park.blend
    • build
      • car_park.blz
        • foo.rtf
        • bar.rtf
I added a ‘build’ folder under blends because we don’t want to have output files sprawling around. Then the question is to know whether car_park.blz will be exported along with all its content (for sake, foo.rtf, bar.rtf). The answer is YES.
Not perfect
Using this method I don’t know how to modify the location of the output in the resulting package. Before I would link a ‘blue folder’, so all my media 3D assets would go under [package]/3D/. Controlling the structure of this package is useful in various ways. 
We just demonstrated that we can link a whole folder given a single input file; this means we could input a config file describing which blend files we want to translate and how; then we’d run blender once , translate all the files and producing the correct output.
In the end I think this will turn out to be a better solution, notably because it will avoid translating the same files other and other even if they weren’t modified. Scene files process fast; not the case with files containing large meshes and animations.

For whatever reason, the next steps turned out to be troublesome.
My second py script was symlinked. I didn’t think it would matter (strictly speaking, still don’t think it does) but I found it hard to get the script to refresh (meaning, I would edit the py script and run the build again, find the same error as previously. And again. And again.

An error in the scene export script caused the wrong path to be used.

Passing several scripts on blender command line (-P foo.py -P bar.py) doesn’t work so I ended calling blender twice which is a lesser evil. Maybe.

Complications

  1. I have a mixed workflow using both Blender 2.4x and Blender 2.5x. In theory this means that I would have to go through the motions again, finding out how I can run 2.5x from the command line (likely as not, it won’t work in the same way).
  2. Scene files contain level edits and assets. Asset files do not contain level edits. Both blender 2.4x and 2.5x files are just annotated as *.blend. How do I know which version of blender to run and which scripts to call?

The answer to (1) will be simple for now. Don’t do that. I mainly use 2.4x; the only 2.5x file that really matters so far is the one containing the PC mesh and animations. So I’ll just pass and use the manual workflow for that.

The answer two question (2) will be equally simple. Use a convention. For starters:

  • level file: level.s.blend
  • asset file: asset.a.blend

( and likewise when I get 2.5x scripts working, different conventions may be used )

This is a bit lame. Maybe a better convention might be something like:

  • *2.4x/scenes*.blend
  • *2.5x/assets*.blend

Works – although the build rule does say something like “files with name matching”, the matching rule actually uses the path.

A nag here is that I don’t want to have 2 or 4 ‘build’ folders for my assets. Just one folder (that I can trash as a quick and dirty way to make sure no out of data lingers in the system) would be best. This should be straightforward, matching the output like so:

  • ${INPUT_FILE_DIR}/../../build/${INPUT_FILE_BASE}.blz

Conflating the output from various files (e.g. 2.4x/assets/foo.blend and 2.4x/scenes/foo.blend ) is possible. Collisions are unlikely, however, so I’ll keep it this way.

Polish?

Silencing the output?

When running blender directly from the desktop, getting console output to show up can be tricky. XCode surely doesn’t have this problem. All debug output appears in the messages window. Too much of it, in fact. Worse, something forces the item matching the translation script to expand.

No luck. I was assuming (maybe wrongly) that blender output is displayed because it is sent to stderr. Either way standing messages to stderr or stdout will yield the same result. Until further notice if I want to avoid script messages blotching the output, I need to disable debug output manually.

Displaying errors during the export process

An issue serious enough that putting it under ‘polish’ may be foolish : how to ensure that XCode will alert us when export errors occur? And by the way, what is an export error?

I tried my luck again, this time by looking at the unit test framework output. I thought XCode may be detecting a simple pattern to identify errors, and it is. The pattern is something like this:

  • error: description of error

The space after the colon in error : is required. In python (~2.7), use:

print (“error: something went wrong”)

And XCode will detect the error and display a flamboyant exclamation mark. Neat.

This won’t stop the build from completing but a red exclamation mark is difficult to ignore so it will be enough.

What is an error, then?

A py script failing while running inside blender does NOT cause an error to appear in XCode. This is because blender returns with exit code ‘OK’ regardless. Now that we know how to signal errors to XCode, we can insert validation related errors. But we also want to report an error when our script fails unexpectedly:

    try:
        exportAssets(PATH)
    except:
        print “error: in blender script: “, sys.exc_info()[0], “(see messages window)”
        raise

raise causes the error to propagate, allowing detailed information to appear in the log.

caveat: If the script contains a syntax error, it won’t run. In this case blender will report the error and exit, however we cannot alert XCode since the script didn’t even start running.

(how to cope with) limitations

Limitations with the approach I described derive from the atomicity of the conversion. It has to be done like this:

input file => output file or directory

For level edits, it is fine.

I see a problem when several files want to output to the same deployment directory. For example, it often makes sense to define actors as shared assets (same creatures used in different levels). Although it is a bit messy, it is often convenient to keep several actors in the same blend file. But then what we’ll end up doing is this:

  • myCreatures1 => targetFolderA
  • myCreatures2 => targetFolderA

This is bad in at least two ways:

  • We should cleanup targetFolderA before exporting (to avoid outdated files lingering in the build)
  • When exporting myCreatures2, we’ll end up copying over again data output by myCreatures1.
If we export to separate folders (myCreatures1Out/, myCreatures2Out/) the deployment structure becomes inconvenient. We may end up manually adding every output folder to the path used by a loader, and if we do so retrieving assets will take more time.
For shared assets, we have to choose. Either we start from a file listing all shared asset files and this becomes the input – processed by a special script – or we agree that each file will contain one actor / item. While the first solution is somewhat constraining it does help keeping things neat and requires less work.
So, do what?
Although not ideal, a solution is to modify the way the loader retrieves data blocks. I want to do this conservatively.
Before, a data block would be retrieved by creating a file name against the resource paths (e.g: rabbit => retrieve the mesh called rabbit.dbk)
After, a data block can also be retrieved by matching a file name against a path in a designated shared resource folder (this would have to be the bundle’s root I’m afraid) : rabbit => rabbit.blz/rabbit.dbk

Additionally, the name of the blend file for a shared resource should match the name of the data it contains.

Much easier than editing/adding project wizards, making simple changes to file templates to suit your needs is a breeze.

All you have to do is search for FILEBASENAME under your XCode install path; the filepath for each __FILEBASENAME__ .h / .m file clearly indicates what the template is used for; additionally, templates can be opened directly in XCode.

In Objective C you can easily retrieve a class by name and instantiate it:

Class clss=NSClassFromString(@”Foo”);
id foo=[[clss alloc]init];

The above is perfectly equivalent to:

Foo* f=[[Foo alloc]init];

If your package doesn’t provide a Foo class, clss will be nil.

Sometimes it’s a good idea to make sure that the class you retrieved is a subclass of a base class or complies to a protocol; for example you can use this.

BOOL okay=[clss isSubclassOfClass:FooBase.class]

There are a few uses for this. Notably this kind of technique is useful to serialize runtime graphs.

Sometimes also, you want to break type dependencies at compile time,

For example let’s say you have a ‘game shell’ module. You want to reuse the model to run various games. Each game you have may then have it’s own game class. Your game shell might retrieve the name of the game class from a plist and dynamically instantiate it. There are other tricks you might use to achieve the same goal (e.g link the same header against concurrent .m files) but I think this way of doing it is clean and simple.

Similar tricks can be found on pilky.me, and for somewhat frightening(?) hacks of the ObjC runtime, you can read an article on Phrack Magazine.

After almost a year, my third update to the ObjC beginner caveats blurb. 8 new caveats added today (marked with [NEW])

Language/SDK

1. NSArray/NSMutableArray cannot hold ints or NSInteger
>> although NSInteger is notationally similar to NSNumber, NSNumber is an object while NSInteger is an alias for int or long (depending on whether you’re running a 32/64 bits architecture). NSArray can only hold objects. If you want to add a number to an NSArray, use NSNumber and initialise your number with something like [NSNumber numberWithInt:26].
(Yes, you can use standard C arrays, there are quite a few posts about this around)

2. NSNumber doesn’t auto-unbox
>> If you try to assign NSNumber to an int (or, better, an NSInteger), you’re assigning a pointer, not the actual number. To get the actual number, use something like: [MyNSNumber integerValue]

3. Strings don’t concatenate with [+] or [.]
>>
If something like “Score: “+score is what you’re used to, try making friends with:
[NSString stringWithFormat:@"Score: %i", score];

4. In, (void)applicationDidFinishLaunching:(UIApplication *)application {…}not all IBOutlets depending on your nib file will initialize until your view is added to the main window
after [window makeKeyAndVisible]; it should be safe to access all IBOutlets attached to your viewController.

5. I updated the frame property of a subview, but the coordinates look incorrect.
>> after updating the UIView.frame property on a subview, invoke setNeedsLayout on the parent view.

6. NSTimer fires at the wrong time / fires too many times
>> When you allocate/init NSTimer with the usual code, you don’t need to invoke fire(). NSTimer is setup as soon as it’s initialized and fire() shouldn’t be called directly as it, *doh!* fires the timer.
>> Whatever you name your callback method, it should take a unique NSTimer argument ( the selector argument would typically look like @selector(myCallback:) with the semi-colon at the end).
What happened to me is that my timer kept firing over and over even though repeat:NO was set. Adding the timer argument to the callback fixed the problem.

7. You cannot declare new variables inside a switch statement

switch (foo) {

case BAR:

char foobar=’*'; // compile error

break;

}

Use this instead:

char foobar;

switch (foo) {

case BAR:

foobar=’*'; // OK

break;

}

Memory Management

8. Use NSZombieEnabled to crash and get a call stack when your program attempts accessing a deallocated object [NEW]

Google it…

9. You need a symbolic breakpoint to hit malloc_error_break and get a call stack [NEW]

Google it (I feel lazy).

10. Unless otherwise stated, objects allocated as a side effect of calling methods other than [alloc] are autoreleased.

This is especially applicable to objects created using factory methods. Take the following example:

[NSMutableArray arrayWithCapacity:5]; // will be released automatically

[[NSMutableArray alloc]initWithCapacity:5]; // we just created a zombie!

At first, it would seem that [NSMutableArray arrayWith...] forms are just shorthands for [[NSMutableArray alloc] initWith…]. Hell, not quite.

[NSMutableArray arrayWith...] and other, similar factory methods, ‘emulate stack allocation’ for reference types. This means that we don’t need to worry about releasing them, as the so-called autorelease pool will take care of them for us.

When we check our code for memory issues, knowing which objects are kept in memory (on the heap) is essential. One way to learn about these is to scan for alloc, retain and release statements. The so called ‘shorthand forms’ allow using objects transiently, without worrying about memory issues, so this convention can help reduce the time spent on memory management.

There are downsides to this for unfortunate beginners:

(1) When we start with objective c, the [alloc[init form appears verbose and cumbersome. So we're likely to create our own shortcuts -- generating 'silent allocations' that make memory management harder.
(2) If we use the 'shorthand' forms, we quickly end up with weird, hard to fix bugs, because we might end up assigning auto-releaseable objects to variables, then these objects get deleted implicitly, and finally we end up accessing... ...garbage(!!!).

11. Beware of  abusing autorelease [NEW]

Autorelease is useful and in some cases you cannot avoid using it:

  • Objects returned by factory methods
    A(n essential) convention dictates that objects created using [alloc] have a reference count of 1. In contrast, callers of factory methods are not responsible for releasing returned objects unless they retain them (see #10)
    Since we can’t use [release] before returning an object we just created, we need to use [autorelease]
  • An object on the call stack may get deallocated if [release] is called.
    Now, it may be argued that only bad design can cause this to happen. Nevertheless one way to solve the problem (it can get nasty) is to use [autorelease]

Now that this is out of the way, beware of practices involving using [autorelease] as a ‘default safe way’. Here’s why:

If an object deallocates unexpectedly following a call to [autorelease] the call stack above [dealloc] doesn’t tell you what caused this object to deallocate.

I don’t see how a coding style involving loosing track of deallocation events can be safe.

12. You can crash the leaks tool in Instruments (seen in Instruments 4.0, 4.1) [NEW]

Recently I managed quirky memory management code that didn’t crash on device or in the simulator, yet crashed instruments. Checking the details, I stumbled on something like ‘invalid leaks data’.

I was about to use up one of my support tickets but reflected that sending my code over and waiting for the ticket to process would take a lot longer than reverting my changes and use the weak muscle to figure it out.

On the downside I got lucky before I managed to narrow it down.

Even if you’re not part of a team, consider using versioning (SVN or whatever new-fangled stuff you’d like).

Kind reminder:

No versioning
=> no diff tool
=> no way to accurately revert changes
=> panic
=> loss of money
=> loss of sleep
=> loss of hair(*)

(*)If you are bald I trust this won’t be an issue.

13. WTF my code crashes when ‘unplugged’ [NEW]

Consider the following case:

  • Your code doesn’t crash when debugging on-device.
  • Your code doesn’t crash when debugging in the simulator.
  • Your code crashes when running in the simulator after pressing the app icon.
  • Your code crashes on-device when running after pressing the app icon.

Then try this:

  • Disable NSZombieEnabled. Quite possibly you’ll see a fairly non-descript crash in the debugger when running the same code.
  • Try to isolate the stack that causes the crash (it’s not meant to be fun but using a dichotomy you might get it done in less than an hour)
  • Re-enable NSZombieEnabled. At this point you may see inconsistent variable assignments in the debug window.
  • Set breakpoints on [dealloc]. Quite possibly you’re deallocating an object that’s already ‘somewhere up’ on the call stack. On sunny days this crashes the device/simulator (hey, it’s actually a GOOD thing). On rainy days it drives the debugger crazy.

Build errors & warnings

14. Warning: Multiple Build Commands for output file …

In XCode, the name of a resource (e.g. a picture to include in the build as resource) is different from the path the resource is retrieved from. Several resources can have the same name, linked with different paths. So for example we can have:

  • foo.jpg (/images/foo.jpg)
  • foo.jpg (/mypics/draft/foo.jpg)

In the final bundle, however these resources are in conflict, they both target /foo.jpg. XCode will issue a warning if resources conflict in this way.

Unsurprisingly, this typically happens when reorganizing project resources.

15. Linking C++ libraries [NEW]

If your project depends on C++/ObjC++ libraries, you may need to add -lstdc++ to other linker flags to your build (see here).

Nibbling UIs (Interface Builder)

16. Action mappings are one-to-many

Yesterday I copied a button from my UI and bound an action to it. Then I was rather puzzled to find that, when I clicked on this button, my game started off with an ominous GL error code. I thought binding an action to a button overrides the previously bound action. It doesn’t. The same user action on the same widget can bind several IBAction targets. In my case this caused the game’s start method to be called twice.

Asset management

17. Use the blue folders [NEW]

If you have hundreds of assets, adding them manually will be a pain. However you can link a whole folder; in XCode’s ‘add files wizard’ select your folder and tick create folder references automatically…

XCode is getting better at detecting changed/added assets between builds (but see #18, below)

18. Sometimes you need to remove your app from the simulator/test device [NEW]

If your code relies on a mechanism allowing to retrieve a resource from one of several locations, you need to delete your app from the simulator / device whenever you remove assets from a blue folder.

Let’s say your sound folder is organized like this:

default_sounds/
---- KO_sound.caf
---- goblin_sounds/
-------- KO_sound.caf

Now suppose you deleted KO_sound.caf under goblin_sounds. Well the goblin specific sound recorded from your little sister’s performance will still load and play because it doesn’t get removed automatically.

Between builds, no files are deleted from package contents. I don’t know whether it’s a bug or not. It’s often annoying.