Jaanus

Life, people and technology.

An Example on How to Use NSProgress

I spent some time with NSProgress. It’s a pretty recent API to help Apple platform objects report progress to each other in a loosely-coupled manner, as well as handle cancellation easily.

My goal was to more clearly understand its behavior in the context of a desktop app and multiple progress objects feeding into each other.

TL;DR

I made an example project. Here’s what it does.

The rest of this post is just some musings and ranting that I went through while making this project.

Background

I’m not going to explain what NSProgress is. You should just read Ole Begemann’s great post and the platform docs, in that order, that tell you all you need to know about NSProgress’s background, why it exists, what it tries to do etc.

Ole has some code fragments that I used, but it’s nicer to have something that you can just build and run, to see a complete use case, together with the UI quirks etc. So I made a project.

I was expecting this to be a walk in the park, but in the end, it took me 8 hours of solid coding and cursing. Maybe too much for such a silly little thing. But I spent several hours of this on things that were not really related to NSProgress, but rather with my own limitations as an engineer, which brings me to the first topic…

Swift

I honestly wanted to do this example in Swift. I really, really did. That’s how I started. Not very far into it, I hit a roadblock, which was creating NSWindowControllers.

A pattern that I find highly usable in Objective-C is:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@interface MyWindowController : NSWindowController

- (instancetype)initInSomeCustomWayWithParameters:(NSWhatever *)parameters;

@end

@implementation MyWindowController

- (instancetype)initInSomeCustomWayWithParameters:(NSWhatever *)parameters
{
  if (self = [super initWithWindowNibName:@"SomeNibName"]) {
    // do something more with parameters
    // like capture them as private properties etc
  }
  return self;
}

The best I can tell, there is no way to do this in Swift that does not look insane and ridiculous. See, -[NSWindowController initWithWindowNibName:] is a convenience initializer on NSWindowController, and Swift is much more restrictive about its initialization behavior in this case. You can’t call the parent’s convenience initializer from your own designated initializer.

Now, on paper, Swift’s initialization behavior looks great. And I admit a lot of it is due to me being lazy and not having fully internalized it yet. It is indeed much more predictable than the Objective-C honey badger that just (mostly) don’t care about what inits you call. But in this case, after fighting with it for a while, my conclusion was “uhhh… no” and just do my small project in Objective-C.

Okay, the other thing was, I fix up some window frames so that when you run the demo, the windows are reasonably positioned relative to one another, and you see what’s happening in all of them. Objective-C is pretty loose and permissive about types here, whereas in Swift, you get to put up with lovely gems like this.

You’ll notice there’s even a “fix it” thing. If you let it fix it, you’ll get an equally unhelpful message.

I really want to like Swift and wanted to use it in this example. But, as you’ve noticed, the last few paragraphs haven’t said anything about NSProgress, because before getting to that, I kept wasting my time fighting with Swift. I haven’t learned it correctly yet, I know. But in this case, I just wanted to get the example done, so I went back to Objective-C so I could actually do something useful.

Unwanted crosstalk

Different parts of the NSProgress tree are loosely coupled and there’s no way to know which objects implement it and what don’t. As Ole says…

For instance, did you know that NSData now comes with built-in NSProgress support for the dataWithContentsOfURL:options:error: method?

He makes it sound like it’s a good thing, and it could be, sometimes, I guess. Nevermind that I couldn’t see it working as I expected: trying both with local file and web URL-s, I only got binary progress readings (jumping from 0 to 1 without any intermediate progress).

But, at one point I was seriously confused because I got erratic progress readings. My progress went from 0, to 1, to 0.5, and then gradually from 0.5 to 1. Or even jumping more times between 0 and 1 before finally settling on something like 0.66 or 0.75 and going on from there.

My code looked something like this:

1
2
3
NSProgress *progress = [NSProgress progressWithTotalUnitCount:1];
[progress becomeCurrentWithPendingUnitCount:1];
[self.worker1 showWindow:self];

This progress was behaving wrongly. It took me a while to figure out that this is because of the window showing happening after your progress becoming current. Because first-time window showing causes the NIB to be loaded from disk, and how is that done?

With +[NSData dataWithContentsOfURL:], of course.

Oops.

Some method call that I was not expecting to have anything to do with my progress metering at all, was suddenly interfering with it, and giving me unwanted progress readings. See an example that isolates this behavior.

Now, I was able to fix my demo project because it is a small, tightly controlled thing. I can be pretty sure that no other unwanted stuff is running after I fixed the above (first show window, and only then become the current progress object). But this might not be feasible for bigger projects where more things are happening at the same time and you don’t have tight control over all of them. Like, during the time where you are the current progress object, can you guarantee that nobody in your app is going to read anything from disk?

I’m not sure what’s the way out here. Should you be the current progress object for the shortest time possible, and resign it as soon as you can? It’s OK to construct the tree and then resign current, since you no longer need to be current during the actual work and its observation. But this means you might miss some elements of the tree that are instantiated later.

I suppose another solution is what Ole describes, to forgo the whole “current progress object” business and just pass the parent around between objects, and you can then become a child of that particular one and not just a child of whatever happens to be “current” at that point. This defeats the “loose coupling” aspect, though.

UPDATE: … though, on the previous paragraph, I missed one thing in the docs:

Well… that certainly makes it more interesting. I don’t know how to react to that or what to suggest for constructing your NSProgress tree in an environment where you may have unknown objects broadcast unwanted progress updates.

Stability

NSProgress was crashy for me in this demo project. It doesn’t crash at every run, but if you run the example a few times, you’ll soon enough hit something that looks like this in a NSZombiefied run, when just trying to increment the completed unit count of an instance:

1
2
3
2015-01-24 20:33:47.325 NSProgressExampleObjc[55053:6928978]
*** -[_NSProgressFraction release]: message sent to
deallocated instance 0x618000226120

I’ve filed a Radar.

Cancellation

The above has been mostly complaining. Cancellation, on the other hand, is an absolute joy to build with NSProgress approach, and really drives home the point of the “progress object tree”.

  1. For each NSProgress instance that should run some cleanup work when it is cancelled, you give a cancellation block.
  2. When you want to cancel a bunch of operations that are tied together in a progress object tree, you call [progress cancel] on the topmost parent (tree root). This causes all NSProgresses in its tree to be cancelled.
  3. For long-running code blocks that may be running after the cancellation, you can check progress.cancelled and bail out of that’s the case.

Very straightforward and you’ll see all of the above covered in my example.

Conclusion

My goal was to understand NSProgress better, and I now understand what to look out for when producing or consuming things built with it. The two things that I worry about most are the crashiness and the unwanted crosstalk from things that you weren’t expecting to report progress.

What Games I Recommend on iPad

Someone asked me the other day: “Hey Jaanus, you play a bunch of games on iPad. What games do you recommend if I want a slightly deeper experience than most of the casual games?”

What a great question. Yes, I’ve been playing games on iPad ever since it came out in 2010. It is a fantastic gaming device that is quite different from other game platforms: phone, PC and console. These days, I play games on phone, PC and iPad. I never was too big on consoles.

Also, I like the framing of “slightly deeper than casual”. There’s a spectrum of depth on all of these devices. On one hand, you have silly casual games whose sole purpose these days is to appeal to your lowest reptile instincts and suck money out of you in their “free-to-play” formula. On the other extreme, you have insanely deep, rich and beautiful cames that suck hours and hours out of you and where you must spend a lot of time to gain any sort of progress, in the spirit of good old PC gaming.

Both of these are fine, but I do think that there is a space inbetween that I’d describe as “deeper than casual, yet not so deep that you’d get lost in it.” That’s what the question was about, and that’s what appeals to me as well.

Over the years, I’ve developed a highly subjective taste of games. Sometimes it matches with the big blockbusters and advertising, and sometimes it doesn’t.

So, allow me to present, Jaanus iPad game recommendations of 2015. This is the “best of” through the past few years. I’ve tried many more than these, but here’s only the good stuff, separated across genres.

Strategy

Civilization Revolutions. A great adaptation of the classic desktop came that’s not just a port, but seriously rethought and made a bit more casual. You can complete a whole game in just an hour or two, unlike the desktop one that went on for days.

Plague Inc. Your goal is to kill all humans. As morbid as it sounds, it’s quite fun and challenging to create the ultimate pathogen. I think we get better at morality by imagining ourselves at the other side of the good-and-evil fence once in a while, and this game is the perfect opportunity for that.

XCOM: Enemy Within. A remake of the great XCOM desktop classic that I played 20 years ago. Perfect fit for the touch interface. According to reviews, only some “visual effects” are missing from iPad as compared to desktop, but I couldn’t care less.

Adventure / sandbox

GTA Chinatown Wars. My full review.

GTA3. I never played this classic on a PC or console. This is a straight port, but with super playable touch controls. Highly enjoyable/recommended. See my full review.

Dead Space. Can’t say it was my favorite experience, too repetitive. But it’s another huge franchise and by trying it on iPad, I saved myself the time and effort of trying it on a bigger platform.

Tower Defense

Another genre that’s a great fit for the iPad big touchscreen.

FieldRunners 2.

Tower Defense.

Puzzle

Bicolor. Hands down the best iOS puzzle game by a huge margin. Nothing comes close to this one. I was really sad when I completed it, because I did enjoy pushing through its harder levels. Some of them are really challenging, but you always find a way eventually. If you just get one puzzle game, make it this one.

Quetzalcoatl. From the maker of Bicolor. I’m still playing it. Bicolor is better, but this is still really good and way above anything else on this list.

Threes.

Dots

Colorbind

Hundreds

KAMI

Letterpress. Differently from everything else on this list, this is a multiplayer game. You’ll always be playing against another human. Both scary and fun.

Quento

7 Little Words. Great for honing your English language skills.

Music / Zen

I made up this category. It’s games where either music is the main component/goal of the game, or it just has a zen/relaxing feeling.

Beatstream

The Plateau. One of the earlier games in this genre. Really good. Also could be in the puzzle genre, some of the later puzzles explode your head.

Osmos

Zen Bound

Board

Only the first one is a true port of a physical game. The other ones don’t have physical equivalents but I felt they belong in this category because they have a limited rectangular space where you do things.

Carcassonne. A fantastic iOS version of a physical board game (which I also recommend.) If you have multiple iOS devices in your family, this is a great family game to play with your spouse and kids.

Gesundheit

Flight Control. One of the earliest iOS games that got big, and still great.

Platform

I guess Angry Birds could also be here, and I have played it, but I’m not linking to it because duh.

The Incident

Jetpack Joyride

World of Goo

Leo’s Fortune

Tiny Wings

Action

Monument Valley. All in all, the most beautiful and zen iPad gaming experience. If I had to give out a grand prize through this whole list, I’d give it to this game.

Infinity Blade

Karateka. A remake of the old classic available on C64 and other old platforms, developed by the original author Jordan Mechner. Not a straight port: nicely adapted to new graphics and touch interface.

Wishlist / wildcard

I intend to play these games, and I have a feeling they will be good, but haven’t yet tried them so I can’t give a recommendation. But still listing them here.

Papers Please. This has already won many awards on desktop, and supposedly works great on the touch interface as well.

Hitman GO

Space Age

The Wolf Among Us

Ending 2014 on a High Note With Hone

I haven’t posted much about work in the past few years. I’ve posted specific things about iOS, web and Mac engineering, but not really about the products that I’m working on.

Now, I can talk about work again. We launched not one, but two things in the past few weeks. For the world at large, mostly the first one matters. For me, both are huge.

First, there’s Wire. I was Wire’s first engineer. We’ve been working on it for a while and it feels immensely gratifying to finally ship a new product. I don’t have much to add to all the press and buzz, except to say that I’m privileged to work with a fantastic team on this, especially Priidu and others on the design side of the house, and it’s been an incredible learning and growth experience for me.

If you’ve worked with me, you know that I’m never entirely happy. There’s always more and better work to be done. This is true also for Wire, it was to be expected, and indeed we keep working on it. There are many aspects of the product that we need to improve, the team is looking at the qualitative feedback as well as numbers and stats, and continues to burn long nights and weekends to release new versions.

You’ll notice that the title of this post is not about Wire, though. Now that it’s out, I’m dialing back my personal involvement in it to focus on another project I’ve developed on the side, Hone. It’s in a much earlier stage, and it’s not yet launched in the sense of being publicly available. Rather, what we’re doing is inviting more people to join our closed beta. (If you’re a designer or engineer working on iOS or Mac apps, and Hone sounds interesting to you, I encourage you to sign up immediately. The response has been great and we’ll close the first round of signups very soon. We’ll probably have more rounds at some point in the future too.)

Hone is a very different product from Wire. It is a niche tool for designers and developers, people making things rather than consuming—but these days, “making” is a growing target, as software continues to eat the world. You can read more about Hone in my previous post and on the project blog.

I’ll continue to help the Wire team where I can, but I’ll mostly spend my time with Hone now. That involves two things: working tightly with the closed beta members to see how Hone can help them best, and adjusting the software and components based on the reactions that we get. I’ll need to balance between the vision of the product, and the results of that vision colliding with realities of other people and teams. Hone is based on many years of experience of myself and others, but we’ll need to test it with more people and teams before it’s ready.

So, thank you, 2014. You were a great year. You brought me lots of pain and misery as I was grinding my teeth on many hard problems while making Wire and Hone, but nothing beats the joy and satisfaction of great progress with both of them. 2015 will be great.

I Finished GTA3 on iPad

I recently finished playing GTA3 on iPad.

By “finished”, I mean I got through the final mission when the credits rolled and the game is officially considered “over”. There’s around 10 missions left according to the stats, but I don’t know how to find those, and I did not complete all the side missions (police, medical, or firefighting). But I do feel that the final mission brought some closure, and I’m probably done with the game.

If you’re not familiar with it, GTA3 is a key episode in the long-standing Grand Theft Auto franchise. It’s the first one that uses a 3D perspective, and was originally released in 2001. This is truly ancient in computer history.

Nevertheless, I never played it originally when it was released, because I wasn’t really into gaming and didn’t own any required console at the time. That it was released at all on iPad many years later, and that it plays so well, is a true testimony to its original high quality.

Yes, I can attest to that: it truly plays well on an iPad. Maybe not fully as well as some other titles that are designed for touchscreens, but remember, this is a game that was designed long before any good touch device became mainstream. They managed to port it over and it is highly playable. The touch countrols are a bit awkward for a game that was originally designed for a console controller, but it just takes a little bit of time to get used to, and you’ll be up and running in no time.

Now, I admit. It did take me more than a year of calendar time to get through this game. It’s ridiculously long, but of course, it wasn’t a sustained effort. Sometimes I wouldn’t play it for months, and then I would just pick it up again. That it kept sucking me in and re-inviting, is a testimonity to the thing that matters the most in games: the core gameplay experience.

The gameplay and missions were pretty smooth and straightforward, though I did have to try some of them many times. But the design is such that you can keep learning while repeating a mission until you nail it. This went on right until I got to the final mission, The Exchange, which I miserably failed the first few times. The final mission becomes much easier if you have access to a bulletproof car and all the weapons. You get the bulletproof Patriot car from one of the previous missions, and you can get the weapons by finding all the 100 Hidden Packages in the game.

So I took a bit of a detour and went on a journey to find all 100 of them, which is also a cool way to find more corners of the game universe than you otherwise woudl have. Of course, I wouldn’t go look for them all through the universe myself, but there’s some great guides available these days. I recommend this one that I followed myself and I indeed did get all the 100 packages using that guide. This gives you all the weapons, and makes the final mission a breeze and even somewhat anticlimactic, I completed it just after a few tries.

GTA3 had a rich universe and my favorite style of open-world gameplay. You do have missions, but you can pick at your leisure when and how you go through them. In the meantime, you can wonder around the world, do side missions or just generally cause mayhem. Another more recent title of the same genre I would recommend is Far Cry 3. I’ll definitely try also Far Cry 4 that will come out later this year.

Why do I keep spending my time on these games? It would be an interesting psychological exercise. As I go forward, I’ve found that I keep developing my taste for games that I like and don’t like. Open-world single-player shooters a la GTA and Far Cry seem to be my favorite.

Gaming device choice is another interesting question. I recently got a retina iMac with maxed out specs that is a fantastic computer. Yet, sometimes I use my iPad Mini just to “get away” from my computer (nevermind that it is also a powerful computer, just in a different form factor). It’s also more convenient when traveling. Touch controls can’t entirely match a mouse and keyboard, but they come pretty damn close in most of the gaming scenarios that I see.

GTA3’s distributor Rockstar Games has released some other GTA classics for iDevices (GTA San Andreas and GTA Vice City). Will I play those as well? Not sure at this point. I might.

How to Install Windows With Boot Camp on New Retina iMac

I got a new Retina iMac recently. It is every bit as fantastic machine as the hype says. Since I use it for both work and play, I did not hesitate to splurge a ridiculous amount of money on it and max it out in all the tech specs, as I will be heavily using it for the next several years. I guess I might write more posts about different aspects of the machine.

The one thing I do want to write about today is how to get Windows to work with Boot Camp. My main (well, the only) use case is Windows games with Steam.

TL;DR summary: don’t bother with Windows 7. The installation doesn’t work correctly and the whole system is aging. Just buy the new Windows 8 from Microsoft (Windows 8.1 is the current version as of this writing) and live happily ever after.

Here’s a bit more detail about how I got to that conclusion.

I have a legal box copy of Windows 7 Home Premium that has been serving me well over the years. Windows 8 caused a big fuss with its Metro interface and did not sound like a good idea on desktop, so I’ve been avoiding it until recently.

So, my first step was to try to get Windows 7 installed on Mac Bootcamp partition. The way to do it these days is to run Boot Camp Assistant on Mac, that prompts you for the location of Windows ISO image, and then prepares a bootable USB stick containing both the ISO image and the extra needed drivers.

So first I had to convert the DVD into an ISO image. No biggie, plenty of ways to do that. And then ran the Assistant that prepared the USB stick, Windows partition, and rebooted into Windows installation.

That’s where trouble started, and I had to revise yet another piece of my hardware knowledge. I had a USB keyboard and mouse available, that I thought I could just plug in to the computer, and they would be backwards compatible with the ports and software and would work under any conditions, including Windows installation. Apparently, this is no longer the case. The USB3 ports on recent Macs are apparently not supported without drivers in Windows at all, and so what the Boot Camp Assistant does, is augment the Windows installation image with these drivers. And it sort of worked, I could see the mouse cursor. Sometimes. But then, installation froze at 65%, which is supposedly another artifact of the USB system (remember, the installation media is also on a USB drive that is plugged in to the USB port). When I rebooted straight into Windows installation, there often would not be any mouse cursor and keyboard access at all.

All in all, Windows 7 just wouldn’t install for me correctly at all. Fair enough, let’s give Windows 8 a shot.

I was prepared for many hours of ordeal and wasted money, trying to sort through Microsoft’s different Windows versions and licensing options. If it is an “upgrade” version, do I need to have previous versions around as well? What if there are similar driver troubles and I find myself having wasted money on a license, but still unable to install?

Fortunately, none of this happened, and all went fine. First, you head to Microsoft Store and buy a Windows license. Windows 8.1 comes in regular and Pro versions. You don’t need any Pro features for gaming, so I just got the regular one for 119 EUR. This gives you the license key. Very important. Write it down and hold on to it.

Next, you need the install media. You can click the “Download” link on your order page in the store, or you can go to this page. You can’t just download an ISO image: you need access to another Windows machine to run the installer that downloads the image. If you do not currently have access to Windows, I don’t know what to recommend you. Luckily enough, I had a Parallels Windows VM around in my Mac, so I could just run that downloader. It first prompts you for the license key, and makes it look like you are about to install Windows, but don’t be scared and just follow the prompts carefully. At one point, it offers you to save an ISO image and that is what you want.

So, now I had the ISO image of Windows 8.1, as well as a license key. I could run the Boot Camp Assistant that again prepared me install media, booted into Windows installation … and from there on, everything was smooth. Apparently Windows 8.1 has better USB3 drivers, so mouse and keyboard worked, as did the rest of the installation. Only at one point, it tells you “Almost done, do not turn off your computer” and seems like it is stuck on this screen, I think it was like 15 minutes for me. Eventually, though, it goes on, and the installation finishes fine.

8.1 is also much friendlier than 8 on the desktop. There is still some Metro interface around, and some dialogs talk about “Tap here”, but overall, it’s fine and you can stay in the regular desktop environment for most of the time.

Cultural Studies Based on Salsa Tequila

Every summer must have its summer hit. Two years ago, it was “Gangnam style”. Last year, it was some Avicii stuff and maybe “What does the fox say”. I did not know this summer’s, but I just recently found out about “Salsa Tequila”. This must be it.

The song climbed the charts in Nordic countries, the Netherlands and Belgium.

All that they did is just mash together a bunch of popular Spanish words. Add an inane but catchy tune, and a silly video, and make sure the instrumental version is available, and what do you get? Infinite mashup potential, that’s what.

Indeed, many people have taken to converting this to their own language, or some other language/culture they want to make fun of. I recently spent some time going through a bunch of them, because why not. Here’s my selection of the better ones.

Kudos to the video-makers for turning this to a meme. For example, pay attention to the sound device and where it’s inserted, some of these are pretty creative.

German. (Made by some Dutch guys.)

Dutch. It’s well made (by the same guys) but I don’t know enough about Dutch culture/language to appreciate the jokes.

Polish.

Finnish. Appropriately named “Sauna and Nokia”.

Scandinavian.

Russian. These guys are lazy and didn’t even remix the song to their language. But they did make a video.

Heavy metal. (Well, it’s not a language, but cool video and music.)

“Folly of Fools”, Deceit, and Self-deception

I recently finished reading “The Folly of Fools: The Logic of Deceit and Self-Deception in Human Life” by American evolutionary biologist and sociobiologist Robert Trivers.

This is part of my reading series on the intermingling topics of security, psychology, and behavioral economics. The last book I read in the series was “Liars and Outliers” by Bruce Schneier.

I read these things because in the modern world, it is increasingly difficult to answer simple questions: What is real? What is important? Why and how do we make decisions? There are many companies who enormously profit from distorting your view of these questions. This has, of course, always been true with advertising and such, but increasingly so in the tech world.

This book is useful to reason about these topics. You’ll note mixed reviews on Amazon, and some of the one-star ones are from scientists who don’t see this book as scholarly. They’re right. It is based on science, but it is not a scientific/academic book.

It begins with an examination of evolutionary biology where the author’s background lies. While deception is “bad” as a human moral concept—thou shalt be honest and not deceive others, right—deception and the tools to counter it have been crucial in evolution and continue to be so in the modern human world.

Family and sexual topics are examined, and then onwards to many practical applications and anecdotes. I was delighted to see my own field of usability and human factors also covered, which was done in the form of discussing hierarchy and relations in airplane crews, and how obedience and self-deceptions have caused several airplane crashes.

War, history and religion are covered. In the part about false historical narratives, the discussion is around US, Palestine and Israel—probably among the most loaded topics there can be, but deconstructing the narratives from self-deception perspective can help bring rationality to the table. Modern Russia was not mentioned, but would fit into the series very well.

How I Fixed HTML List Items Jumping Around

Does this kind of thing drive you nuts?

I was working on a list of items in HTML. It is a bunch of list items, and the selection is indicated with a border. Every time you change the selection, though, the list jumps around by a few pixels. And it is terrible.

(None of this is particularly insightful to anyone who works on this stuff day to day. But I am brushing off my web skills that haven’t gotten much use for a while, and I was glad I could reason through this problem like I did. Maybe this is useful to someone else too.)

The problem is caused by how the CSS box model works. Border adds to the dimensions of the item. The non-selected items do not have a border, and are thus narrower. When a box appears, the width of the item changes, and the items after it shift right. When a box disappears, the width decreases, and the trailing items shift left.

Annoying. But easy to fix.

Now, it is possible to hack the box model in various ways. I don’t know if there is a box model that would end this jumping around without the modification that I did. My fix is dead simple though: let’s add an invisible border to all the elements. There is no border-opacity CSS property, but this can easily be done with using RGBA color for the border, instead of the more common hex format. This way, the size of the elements stays fixed, just that the border is visible for the selected one, and transparent for the others, but the border is always there.

The result is much nicer. No more jumping around.

See and play with all the code in the fiddle.

A Tragic Story That Happened to Someone I Know

I heard a tragic story recently. One of those things that you see in movies, or news. Sadly, this is real and recent.

There was a couple planning to get married. He was older and had a family before. The marriage had been planned for a long time and everyone was looking forward to it.

The bride and groom were from different countries. The wedding was set to happen in the bride’s home country. A few weeks before the wedding, the groom flew in and they got busy with the final arrangements. Everything was set, and ready, and beautiful. The bride and groom were looking forward to the wedding, and another week after it that they would spend together.

A few days before the event, the groom’s family flew in. Two days before the wedding, the guys went out partying to town. Among them was the groom’s son from a previous marriage.

They got really drunk. At one point, the team dispersed, and the son wondered off. In the middle of a night, all by himself, and wasted beyond oblivion, he stumbled across a high ledge, and fell down.

The fall was many meters, and he was stopped by some bushes. Luckily, this was in a city and not in the woods, and he was soon found. He broke most of his bones and went into a coma.

The couple decided to cancel the wedding. They would still get married eventually, but much, much later, and somewhere else, and not in the elaborate way they had planned. Now, instead of spending time together as newlyweds, they had to spend time in the hospital and insurance, arranging the son’s medical evacuation to his home country by emergency flight.

I hope they do get married eventually, but events like this clearly leave a scar.

The saddest part is that this was entirely avoidable and unnecessary. Someone’s reckless behavior caused angst and suffering not only to themselves, but the whole family.

We’re all free people. We do what we want. Just be safe and don’t be dumb. A police officer once said that if you took away “alcohol” and “stupid”, 90% of police work would disappear. And you would avoid a lot of pain and misery.

How to Correctly Configure Building Private OS X Frameworks

I’ve been recently dealing with building a private / embeddable framework on OS X. By “private framework”, I mean a framework that’s not installed system-wide, but one that’s bundled with an OS X application. Now that frameworks are also coming to iOS, it’s probably of wider interest, although this specific post is only about OS X. I spent several hours yesterday trying to get it to work, and thought to just document it, so that I wouldn’t forget myself.

TL;DR version: you need to change some build settings to the following values:

Skip Install = YES
Installation Directory = @executable_path/../Frameworks

You also need to add a “Copy files” build phase to your application target to copy the framework into its “Frameworks” group. And you also need to think about code signing, which I’m not covering here.

Okay. That was the summary. Below is an exploration of my adventures. And grab the example project.

The test project

I created a test project with Xcode 5.1.1, consisting of the default Cocoa application target. I then added a Cocoa Framework target with default settings. My test app is called HelloFramework, and the framework is simply called Hello. The code for the framework is very simple, here’s the header.

1
2
3
4
5
6
7
@interface Hello : NSObject

+ (void)helloFromClass;
+ (instancetype)sharedHello;
- (void)helloFromInstance;

@end

And the implementations imports the framework: #import <Hello/Hello.h> and just show some modal dialog boxes a la good old Javascript alerts.

Okay, so far, so good. We add the Hello framework to our app target in “Link Binary with Libraries” phase. We add a new “Copy Files” phase to bundle the framework into the application. We run it in Xcode, and everything looks good. Dialog boxes come up.

Now, things start to get a bit weird.

Archiving trouble

Let’s archive the app target. The first sign of trouble is that the archive is not of type “Mac App Archive” as expected for the Mac app, but is of type “Generic Xcode Archive”, which most of the time in Xcode means “Probably Not What You Want”. But okay. Let’s try distributing it. I only have the choice of “Save Built Products” instead of exporting the app for distribution. Let’s do this anyway.

Here’s what’s exported.

So there’s both the application and the framework. But we don’t need the framework; we just want the application. If we peek inside the app bundle, we even see that is has a correct Frameworks group with the Hello.framework nicely sitting in there.

Well, let’s try to run the app. BOOM, it crashes.

What the what? Well, if we look at the error, it says right there what the problem is.

1
2
3
4
Dyld Error Message:
  Library not loaded: /Library/Frameworks/Hello.framework/Versions/A/Hello
  Referenced from: /Users/USER/Desktop/*/HelloFramework.app/Contents/MacOS/HelloFramework
  Reason: image not found

Okay, so it’s trying to load the library from a global path. Why is that?

System vs private frameworks

There’s two kinds of frameworks. The system ones go in /Library/Frameworks, and can be used by multiple applications. The default Cocoa Framework template seems to be set up for building these. I’m not sure what their future is, though, since a lot of app distribution happens through Mac App Store and these apps are sandboxed and I don’t think they can install system frameworks.

The other kind of frameworks, private frameworks, are the ones that are embedded in the actual app bundles. These are what we’re trying to build, and are failing so far in the example.

Turns out that the install location of a framework is part of its build settings. When we look at the Installation Directory of our framework target, it is by default, unsurprisingly, set to $(LOCAL_LIBRARY_DIR)/Frameworks, which resolves to /Library/Frameworks on my system. This is not what we want. We want the framework to be embeddable in apps, and so the installation path should be relative to the app that contains the framework.

What’s the right value? I found this post to be useful when working through this topic, but they recommend changing a bunch of values that don’t seem to be necessary. I found the official doc which says, hidden inside all the other wisdom, that the Installation Directory for private frameworks should be @executable_path/../Frameworks, which looks pretty reasonable.

Great! Let’s change the installation path. When we now archive our app, we see that it creates “Mac App Archive” as expected, we can run it, and it no longer crashes. Fantastic.

There’s a warning when archiving the app target, though. Let’s get rid of that.

Fixing the last warning

The warning says:

1
Warning: Installation Directory starts with '@executable_path' but Skip Install is disabled.

It’s not super clear, but it’s clear enough if you’ve dealt with iOS app archiving troubles before and are familiar with Skip Install build setting. Basically, for a given target, Skip Install says (in the negative) whether it’s an installable target or not, which roughly translates to “Is this the app that the user will run” (in my mind, anyway). Why it needs to do that in the negative, I don’t know, calling it “Installable” would be much clearer. But just negate it in your head and it makes sense.

Skip Install = NO makes sense for system frameworks. You do want them to be installable. Although how that actually works beyond them being exported when archiving, I don’t know exactly. Anyway, in our case, for our private framework, we don’t need it to be installable so we set it to YES, and boom, the warning goes away.

The one thing to note is that there’s no nice way to archive the framework now, since it’s not an installable target. If we want to use it in another app as a pre-built thing, I just build it in Xcode and then grab the build result from the build products folder on the disk, probably with Release configuration if it’s meant to be used by others.

The mysteries remain

A few more things to note.

How is a normal person supposed to find and gather this info? I spent a few hours googling and trying out random stuff, as I wasn’t too familiar with frameworks, before I converged on this info. I think it could be a lot cleaner.

Why did the framework with wrong installation settings work when I was running the app in Xcode, and crash after exporting and trying to run the same app outside Xcode? I guess Xcode tries to be helpful here, when the framework project is part of your app workspace, and somehow masks out all these installation problems. But I think it was harmful in this case, because it really obscures the problem and shows there’s no substitute for testing the exported end product. Some of Xcode’s ways remain mysterious to me.

How does all this interact with code signing, and how will this work with Xcode 6 and iOS 8 where frameworks are now also supported? I don’t know enough about these topics right now to cover them myself, but maybe I’ll do a follow-up once I drill down into that.

Anyway, you can grab my example project here.