Category Archives: Mac OS X

SVGKit (iOS) now supports more SVG’s – including most Wikipedia maps

Finally got the complicated viewBox / transform-matrix code working for SVGKit. Net result: the remaining maps from Wikipedia that used to fail catastrophically now render perfectly, e.g. their European map:

Why so hard?

For the curious…

This European map is specified at “180,000 units wide and 150,000 units high”, but … “Oh, by the way, we suggest you render it at 1800 pixels by 1500 pixels”.

This is a problem unique to scalable vector graphics (and part of what makes vector images so interesting). There is *no* “correct” size for a vector image – it can be rendered at *any* size, by definition.

Unlike a bitmap (i.e. the images used in 99% of situations today), a vector image never goes “blurry” or “pixellated”. If you want to view it at ultra-high res, you’re welcome.

And, because some code in the world still uses low-quality “floats” to store data (which are very inaccurate at high numbers), a lot of the world’s SVG files are specified using large integer numbers, and they assume you will “scale down” to your desired display size. Which is great. Except that (until today) SVGKit didn’t support that scaling, and tried to render everything literally, causing huge memory use and crashes.

NB: all this is currently in an experimental branch of SVGKit – we’re hoping to merge it into the master branch soon, but for now you’ll have to access this directly from https://github.com/adamgit/SVGKit/tree/transforms or not at all – sorry!

Apple’s C compiler (LLVM) doesn’t set float to 0.0 – why not?

With this piece of code, what gets output?

float aFloat;
NSLog(@"Default value of a float is zero, right? A float = %.3f", aFloat );

(Hint: USUALLY, you’ll get “0.000”. But not always… )

A common expectation

Apple’s C compiler doesn’t always initialize float’s as you might expect.

The C standard has two different aspects to float initialization. One version will set floats to 0.0 *always*. The other version … will set them to random mem contents – which on iOS, for instance, is normaly but not always … 0.0.

(and the C++ equivalent is, of course, more complicated still … depends on the surrounding context of your variables, e.g. are they in a class? how’s that class getting constructed? etc)

e.g. I had to fix the following code, which was running fine 9 times in 10, but crashing/asserting occasionally:

float infitesimal; // In almost all languages, this = 0.0;
float smallPositiveFloat = 0.0001;

infitesimal += smallPositiveFloat;

NSAssert( infitesimal > 0.0, @"Not with Apple's LLVM version 3, it ain't (sometimes) ..." );

Apple should fix this anyway…

UPDATE: As pointed out by Nathan, Build won’t hilight this, but the Static Analyzer *will* (by default). This is great, but like many devs, currently we only use Xcode’s “Analyze…” every few days (and/or the weekly build) – it’s too slow to do “every” build, and it errors on things that you’re forced to do (e.g. it doesn’t understand asynch callbacks, e.g. it doesn’t like dead code that’s sometimes needed to workaround the Xcode debugger).

It doesn’t surprise me that Apple has left their C mode compiling this – it’s slightly annoying, but technically correct, and following standards is a very good thing.

But the question begs: why doesn’t Xcode flag this as a WARNING by default? That would still be standards compliant, and yet reduce the bugginess of many iOS apps.

(I find it very hard to think of real situations today where an iOS or OSX app would actually want to use a float uninitialized – meanwhile, it’s begging for data corruption bugs, security holes, etc)

In the meantime, of course … whenever you see “float something;” without an ” = 0.0;” on the end … well, you know what to do.

A general problem with Objective C

A brief note on the general case: this isn’t just about floats.

The above behaviour is often removed from modern languages – or is reduced in extent (originally I wrote: doesn’t happen in C++. As James points out below, it does happen in C++, my mistake – although I’d still argue it happens less easily / accidentally). The tiny, rare benefit is outweighed by the large, common loss.

Unfortunately, since ObjectiveC is defined as an extension of C … we’re stuck with it.

Ironically, Apple’s choice of Obj-C (rather than – say – Obj-C++) sometimes has the unwanted effect of pushing programmers back to the dark ages, to the days when “the x-y position indicator” was still just a research project.

(Apple brought out their first consumer desktop with a mouse in 1984. C++ launched in 1983 … )

iOS project gets: “_objc_read_weak”, referenced from:

I got this recently from XCode4 – not the most obvious of error messages, and google had zero results. So, to help anyone else who gets the same problem…

What’s happened?

Somehow, you’ve included a library in your project that was written for Mac OS X – not iPhone/iPad.

The problem seems to be (note: I’m not 100% sure of this) the library is using OS X’s Garbage Collection directives. Often, the line above will be just in a few places in the project.

If so, I’m surprised this breaks Xcode builds – I’d have thought they’d have set iOS compilation to ignore this stuff.

Workaround

iOS doesn’t (yet) support GC, and it looks like Apple intends that it never will do. If you’ve got access to the library source code, it seems you can usually just remove the “weak” directive, it’s there to provide a hint to GC, and isn’t actually needed.

Obviously, you don’t want to break the OS X code, so the typical workaround is to take the original line of source:

@property (nonatomic, readonly)  __weak  NSObject *thing;

and wrap it in an OS X only conditional compile:

#if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
@property (nonatomic, readonly) NSObject *thing;
#else
@property (nonatomic, readonly)  __weak  NSObject *thing;
#endif

If you don’t have the source to the affected library…

…then you’re stumped. Best I can suggest is to implement the _objc_read_weak function itself, and make it effectively do nothing – but I haven’t looked at the Apple docs to work out when/why/how it’s invoked.

Loading SVG files on iPhone/iPad: SVGKit (not the javascript one!)

UPDATE SPRING 2012: The main SVG lib described below (SVGKit) now works a LOT better, and is only a short way from loading all mainstream SVG files.

NB: it also has a new URL (due to GitHub’s internals) – https://github.com/SVGKit/SVGKit/

I’ve got a bunch of SVG files – hand-drawn maps for a computer game – which I wanted to load onto iPad, and port the game. The files are standard, straight out of Inkscape (the most popular free vector-editing / SVG-editing program).

Unfortunately, Apple doesn’t provide any rendering-support for SVG, and the nearest they do provide – PDF rendering – is slow and uses too much memory. PDF isn’t easy to render, and it does a great job on accuracy, but even on OS X, Apple’s API is often too slow for real-world use.

So, a quick look around the open-source alternatives…

SVGQuartzRenderer

This is the library I found via googling. It sort-of works, and it was only designed for a very narrow use-case (so: fair enough) … but it has some pretty major problems, and it’s not really workable for general SVG loading:

  1. The project is badly organized – it has iOS-only files referenced in the OS X project, and vice versa
  2. You can’t do a simple “build this and use in another project” – there’s source bugs/typos that have to be fixed by hand first, mostly because of the bad project organization.
  3. The interface to your Cocoa / iOS app is weak – it’s not designed to integrate cleanly, and it seems to jump you through hoops that most programmers would find makes life hard

SVGKit

While trying to fix SVGQuartzRenderer, I found SVGKit by accident. There are two projects with this name – one is a Javascript library, the other is an Objective-C library. They appear to have nothing in common except the name.

UPDATE SPRING 2012: new URLhttps://github.com/SVGKit/SVGKit/

SVGKit worked pretty well out of the box – you can do a build direct for iPad from their sample project, and it loads up into an “SVG Browser” that lets you try a couple of example SVG’s included in the project.

TL;DR – do NOT download the main version, it’s out of date and buggy, and the original author has disappeared. But there are high-quality forks you can download instead that work very well (instructions below).

UPDATE SPRING 2012: the project now has a team of contributors and admins, and the “main version” should soon be up to production quality

SVGKit installation / getting started

Tragically, the install instructions on the front page of the github project are simply … wrong. There’s no way you can use it in your own projects with those instructions. The sample projects work, so it was a case of doing a line by line compare to work out what special magic settings were needed.

UPDATE SPRING 2012: All the instructions have been re-written (I updated a lot of them myself :)) – use the instructions on the https://github.com/SVGKit/SVGKit page

Corrected instructions are:

  1. Drag/drop (or copy/paste) the “iOS” and “Core” folders into your Xcode project
  2. edit the Build Phases, and add to the Libraries phase: libxml2 (this gets Xcode4 to add it as a framework/dylib)
  3. edit “Header Search Paths” and add /usr/share/include/libxml2 (this gets Xcode4 to actually USE it when building)
  4. edit your Build Settings, and set “GCC_VERSION” to be: “com.apple.compilers.llvm.clang.1_0”
  5. add “QuartzCore.framework” to your iOS project.

The only one of those that’s particularly unusual is changing the Compiler to LLVM 1. If you don’t … the project won’t compile.

SVGKit: basic SVG files … use Reklis’ fork

Then I started opening Inkscape-generated files in SVGKit. Sadly, most files in Inkscape will – literally – crash SVGKit. There are major bugs in the parser, a combination of mis-reading the SVG spec, and a bit of really sloppy C code (buffer overruns in the parser! Ouch).

Fortunately, the parser has been completely rewritten by reklis, who’s fork seems to be now the “de facto” release of SVGKit. (incidentally, I tried emailing the original author, who I think is the only one that can update the main project, but his website email link is broken :(. I’ve tweeted him too, hopefully he can pass-on the project to reklis to maintain).

UPDATE SPRING 2012: … the original author has now made it a shared project, with multiple admins.

…but there were still some major bugs. More than half of the Inkscape files wouldn’t render even vaguely correctly (although all the crashing bugs are fixed).

I delved into this, and it turned out to be two very small remaining bugs in the parser, which I was able to fix quite quickly, and merge back into reklis’ fork – if you grab his fork now, it should work pretty well.

SVGKit: …advanced SVG files

Unfortunately, the really complex / rich SVG files still fail in SVGKit. With my fixes, most of them render approximately correct – e.g. I have a version of the famous Tiger.SVG which gets the main outline exactly correct, but loses all the internal colours and objects.

Others – such as the almost-as-famous Lion.SVG – fail completely, you just get a big blob of colourless trash on screen :(.

UPDATE: Lion.SVG now works OK. Colours are slightly wrong, but the complex image is rendering well – you actually get a lion now 🙂

However, all the Inkscape-authored files I’ve got are working fine, with all the tools (lines, curves, “freehand”) working as expected. That’s enough for most developer projects.

Guesses at fixing the remaining SVGKit bugs…

Just in case anyone reading this needs a perfect SVG renderer on iOS, and has the time to try and fix it, here’s some thoughts on what to look at next.

My guess is that the vast majority will render the correct *shape* (I’m confident those bugs are all fixed) – but there are some advanced curve shapes that no-one has implemented yet. I suspect that Lion.SVG is using them, hence why it’s such a big mess when it renders.

Separately, I think there’s an issue with z-order layering and/or the implementation of the “fill” command in SVG, that’s causing things like Tiger.SVG to be the right shape, but missing all their internal detail.

Hopefully, someone else can fix those soon. For now, I can say that everything I’ve got / made in Inkscape is working fine, which is good enough for me to get on with my game project.

UPDATE SPRING 2012: There is experimental support for CSS styles (which make the colours correct for every SVG file) – it’s not yet merged to the main fork (still needs testing).

Also, there is partial support for the “transform” attribute – currently only handles translation, not rotation. So, for instance, SVG files that have rotational symmetry (e.g. compass roses) fail badly. But this is coming soon…

Finally, there is partial support for SVG Text.

When all three of those have been tested and merged, SVGKit should be loading almost all SVG files correctly.

Archiving old GIT projects on Beanstalk or Github

EDIT: re-written to make it much clearer what I’m trying to achieve, and why.

Why Archive? Why not Archive?

The pricing model for hosted git has settled down to:

  1. Pay per month
  2. …for an upper limit on the number of active repositories
  3. ……measured by simultaneously limiting the number of “projects” (separate git repositories) and “people” (user accounts that are allowed to access projects)

Their aim seems to be: charge for peak concurrent usage, rather than for total historical usage.

For instance: if you have 20 user accounts allowed, and you use all of them, then delete 10, you can create 10 new ones. The vendor will NOT delete all the history of the deleted accounts – they just won’t allow you to login as those users any more.

This probably is setup that way to make sure:

  1. their revenue scales with their costs – these days, with scalable hardware costs, that’s straightforward.
  2. their prices scale with the budget-size of their customers

Some SAAS vendors selling at the same kind of price level / model allow this same “disabling” function on whole projects, not just on people. That enables you to e.g.:

  1. Work on 1 new project day-to-day
  2. Have 10 “old” projects that are no longer active (previously shipped)
  3. Reserve the right to temporariliy activate any ONE of the 10 – e.g. to enact a quick bugfix / maintenance release
  4. …while only paying for “2 simultaneous projects”

This works fine – the resource usage is closer to that of a company with only 2 active projects than it is to a company with 12 active projects, and the price you’re able to pay is too.

Unfortunately, at the moment neither Beanstalk nor Github offer this – although they’re both great git-hosting services.

Archive options

In practice, we need to support these use-cases:

  1. Old project that MIGHT still be around in a local repository needs small tweaks and a quick re-launch: typically only 1-3 files need to be edited.
  2. Very old project that definitely isn’t in a local repository any more: ditto
  3. New project needs to solve a problem that was previously solved in an old project: need read ONLY access to the full project to revise “how we fixed this last time”

Before signing up to a git host, I asked each of them how they coped with these use-cases (in some detail); each company responded with, essentially:

We don’t have any support for this. Best we can sugest: copy all old projects into a single repository

Archiving git projects via copy/paste

What happens when you try to do this?

Well, for a start, you can’t “just copy” the contents of one git project into another.

Git uses hidden directories to manage its source control, and is hugely reliant upon them. This causes a handful of problems relating to “is file X still file X?”, one of which is this one of copying between repositories.

Naively, you’d try to do this:

  1. Create a global “archive” repository where you will move *all* old projects (this was initially recommended to us by Beanstalk/Github)
  2. PULL the latest copy of the git repos you want to archive
  3. MOVE the root directory into your “archive” repository
  4. PUSH the “archive” repository to the git-host

In practice, what happens is:

  1. Every modern Operating System moves the .git hidden directory too
  2. …so you fail to do a checkin (and at this point: a lot of the current Git GUI clients will break in interesting ways; it’s a good test for a new client if you’re considering buying one)
  3. …so you fail to do the PUSH

Copy/pasting by discarding the history

EDIT: if git-archive works for you, I’d use that instead. Everyone I know who’s used it has had at least some problems, so I’m leaving this section for now – but scroll down to the next section and check git-archive too.

On anything unix-based (i.e. linux + OS X) the simple path is to use the command-line (or “terminal” as OS X calls it)

  1. “cd [the root directory of your project you want to archive]”
  2. “cd ..”
  3. “cp -R [the directory of project to archive] [the root directory of the “archive” repository]/[name of the project you want to archive]”
  4. “cd [the root directory of the “archive” repository]/[name of the project you want to archive]”
  5. “chmod -R u+rw .git” (otherwise you’ll have to say “yes” to every individual file delete)
  6. “alias rm=rm” (otherwise you’ll have to say “yes” to every individual file delete)
  7. “rm -R .git”

…then, in your git-client:

  1. COMMIT the “archive” repository

…then, in your git-host service:

  1. DELETE the old project

The key points here:

  1. You’re copying the repository, not moving it – so the original is unaffected (if you don’t have to delete it yet, you might as well leave it intact)
  2. You’re removing all git status from the files: it becomes a virgin archive
  3. DISADVANTAGE: you’re throwing away (deleting) all history for the old project.

Using Git Archive

Git archive isn’t perfect (archiving is a complex task, and from what I’ve seen git archive doesn’t cover every use-case). I’ve met a couple of people who’ve tried it and given up (e.g. because it didn’t support submodules), but it might work for you: Worth a try.

Other alternatives

In furture, I’m going to try out some of the many other alternatives listed on the SO page linked above.

“CodeSign error: Certificate identity … appears more than once in the keychain. The codesign tool requires there only be one.”

One morning last week, I fired up Xcode4, and all projects were refusing to build. The Apple Developer certificate had expired (why does Apple make this expire *earlier* than your annual iOS $99 subscription? Odd).

Anyway, a quick trip the Apple Developer Portal, and the Provisioning page, one-click “renew” certificate (free), 30 seconds refreshing for Apple to process it, re-download, delete the old one (using the Apple app: Keychain Access), install the new one, re-build.

FAIL

…only to be hit by this error message:

“CodeSign error: Certificate identity ‘iPhone Developer: XXX (YYY)’ appears more than once in the keychain. The codesign tool requires there only be one.”

What?

I just deleted that, in Keychain Access. I selected the one that was expired (it’s highlighted with a red error icon), and hit delete. It then disappeared. And allowed me to install a new one.

Xcode4: Clean, re-build. Nope, still refusing
Xcode4: restart, delete all build directories. Nope, still refusing.

Symptom: Apple’s “delete” does not “delete”

It’s a bug – a HUGE bug – in Keychain Access (Apple’s app that is part of OS X).

When you hit “Delete” (either the delete key, or right-click and select the Delete menu item) … Apple 50% of the time doesn’t process the deletion.

However, 100% of the time, Apple makes the item disappear from the screen.

To check if it’s deleted, close Keychain Access and re-open. If the delete was ignored, then you’ll see that the certificate you deleted has RE-APPEARED:


(third-from-the-bottom, you see the cert I had already deleted … has come back from the dead)

Solution: Delete and delete and delete until Apple stops ignoring you?

I’ve found that if you switch to the “All Items” view, on the left hand side, the deletion seems to work every time. But maybe that was just blind luck. Even if it fails, the act of switching back and forth between “All Items” and “My Certificates” seems to force KA to refresh the view, and tells you if the delete has “worked” yet:

App launched: Regexp Helper for Mac OS X v1.1

Our (hopefully) idiot-proof Find/Replace Regexp utility for Mac just had a major update.

New features:

  • Find-matching previewed as you type: automatically higlights all the matches it’s going to replace, while you type. Hit enter when you’re happy, and they’ll all replace at once
  • Built-in regexp Cheat Sheet: Dave Child’s excellent cheat-sheet is integrated into the app as a quick-reference for any regexp syntax you can’t remember
  • Live feedback on syntax: if your syntax is wrong, you get informed on each keypress until it’s valid again (makes it much faster to get your syntax right)
  • Faster. Much faster (some bugfixes, but also using a more advanced regexp library)

Download / upgrade from the Mac App Store here:
http://itunes.apple.com/app/regular-expressions-helper/id429461864?mt=12&ls=1

Mac OS X: custom background for your app-window

I found this neat little technique: http://parmanoir.com/Custom_NSThemeFrame … for drawing a custom image to the background of your Application Window.

Here’s a screenshot of the technique applied to Regular Expression Helper (currently in submission, waiting for Apple to approve it for the App Store):

Things of note:

  1. The author was inspired by Apple’s own apps – recently, Apple has been doing this more and more, even though I’m sure it’s against their own Human Interface Guidelines … so I’m assuming they’ll have no complaints about you doing this in the App Store
  2. This covers your ENTIRE background – it overwrites the default titlebar, overwrites the default bottom bar, everything
  3. The author uses method swizzling to make this work *without* creating custom classes, and *without* altering Apple’s own system classes. That’s very neat: you can comment out a single line of code to enable/disable the customization

For my last OS X app – Regular Expressions Helper – Brett made an excellent icon. As required by Apple’s App Store policies, we’ve got it in all sizes up to 512×512. So, I wanted to use that as the background to the app. This needed some tweaks.

Also, the Parmanoir site skipped over some minor points (all obvious when you read the source code they provided), but for future reference, here’s my changes:

Code requirements

You need to import objc/runtime.h for method swizzling to work – a little surprising, considering you’d expect this to be part of the base stuff pre-imported by NSObject et al. No matter.

Complication: Xcode4 auto-complete is buggy on the objc directory – it displays it as a file, and attempts to autocomplete:

#import  // FAIL...

So, just remember to type it manually (or copy/paste this):

#import  // Correct

Loading your application icons (.icns file) as a background image

If you load an NSImage directly, using the standard method from iOS:

	NSImage* backgroundImage = [NSImage imageNamed:@"image-name"]; // DONT DO THIS

…then you’ll discover a slightly irritating feature of OS X v10.6: it loads a 32×32 pixel version of the image *no matter how big the image is*. This is well documented, but it’s easy to overlook, especially coming from iOS, where “imageNamed” is the method you *always* use, to take advantage of it’s built-in caching.

Instead, if you simply use a different init method, you get the “maximal resolution” version of the image:

	NSImage* backgroundImage = [[NSImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"Regular Expressions Icons" ofType:@"icns" ]];

(note: this is loading an .icns file – the one that Apple requires you to create, and requires you to put a 512×512 image into – rather than, say, a PNG file. That makes things easier to maintain: just one image file to update ;))

Copy/pasteable final custom drawRect method

For sheer convenience, here’s the default basic method for doing background-image rendering from icns, with the alpha scaled down so you can see the image more clearly:

-(void) customDrawRect:(NSRect) rect
{
	// Call original drawing method
	[self drawRectOriginal:rect];
		
	//
	// Build clipping path : intersection of frame clip (bezier path with rounded corners) and rect argument
	//
	NSRect windowRect = [[self window] frame];
	windowRect.origin = NSMakePoint(0, 0);
	
	//
	// Draw background image (extend drawing rect : biggest rect dimension become's rect size)
	//
	NSRect imageRect = windowRect;
	if (imageRect.size.width > imageRect.size.height)
	{
		imageRect.origin.y = -(imageRect.size.width-imageRect.size.height)/2;
		imageRect.size.height = imageRect.size.width;
	}
	else
	{
		imageRect.origin.x = -(imageRect.size.height-imageRect.size.width)/2;
		imageRect.size.width = imageRect.size.height;
	}
	
	NSImage* backgroundImage = [[NSImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"Regular Expressions Icons" ofType:@"icns" ]];
	
	[backgroundImage drawInRect:imageRect fromRect:NSZeroRect operation:NSCompositeSourceAtop fraction:0.55];
}