1. If the object may come in a mutable variant (like NSString has NSMutableString), use copy, so that you don’t end up holding a mutable object that somebody mutates while you’re holding it.

  2. If you will own the object, use strong. (Optionally, leave it out, because strong is the default for objects.)

  3. If the object will own you, use weak. For example, a table view weakly references its data source and delegate, because they are very often the VC or WC that indirectly owns the table view.

  4. If the object cannot be referenced with a true weak reference, use unsafe_unretained. A select few classes*, such as NSTextView, do not support weak references. You will get an exception at run time if you try to establish a weak reference to such an object. You will have to use unsafe_unretained instead.

    The reason weak is preferable is because, if the object dies while being weakly referenced, the weak references automatically get changed to nil. That’s also the part that certain classes are allergic to. unsafe_unretained doesn’t have this feature, which is why the classes that don’t support weak can still be referenced with unsafe_unretained—but, the caveat is that if you use unsafe_unretained, you must ensure that the object will never get deallocated while you are weakly holding it—i.e., that you let go of your unsafe unretained reference before the last owner of the object lets go of that ownership.

  5. Never use assign. For objects, unsafe_unretained is synonymous and clearer (it explicitly says that it is unsafe, which it is). For non-objects (such as NSUInteger and CGFloat, leave it out—assign is the default for such values.

* The Transitioning to ARC FAQ includes a complete list of classes that do not support weak references.

(This is an expanded version of a comment I posted on Stack Overflow.)

How trigonometry works

 

2013-06-10 15:48:12 UTC

I’ve never been a very mathy person, and I came to trigonometry particularly late in life—surprisingly so, considering I’m a programmer who has to draw graphics from time to time. (Guess why I started learning it.)

So, for folks like me who can’t read Greek, here’s an introduction to trigonometry.


Trigonometry largely revolves around three basic functions:

  • Cosine
  • Sine
  • Tangent

You know these from the famous mnemonic acronym “SOHCAHTOA”, which is where I’ll start from.

The acronym summarizes the three functions thusly:

  • sine = opposite / hypotenuse
  • cosine = adjacent / hypotenuse
  • tangent = opposite / adjacent

Very buzzwordy, and nonsensical when every time you use them, you pass in an angle. And yet, 100% correct.

The cosine, sine, and tangent functions work by creating an imaginary triangle whose hypotenuse has the given angle, and returning the ratio of two of that triangle’s sides.

Given the angle of 30° (or π × 30180 radians, or τ × 30360 radians):

Diagram of a right triangle of 30° within a circle

All three functions create this triangle, and then return the ratio of two of its sides.

Note the proximity of the three sides to the origin.

  • The opposite side is the vertical side, literally on the opposite side of the triangle from the origin.
  • The adjacent side is the horizontal side, extending from the origin to the opposite side. It’s the adjacent side because it touches (is adjacent to) the origin.
  • The hypotenuse is the (usually) diagonal side that extends from one end of the adjacent side (namely, from the origin) to one end of the opposite side (namely, the end that isn’t touching the other end of the adjacent side).

Let’s consider a different case for each function—namely, for each function, the case in which it returns 1.

Cosine

Definition: adjacent / hypotenuse

Circle with a 0° triangle from its center

With the hypotenuse at 0°, there basically is no opposite side: The hypotenuse is in exactly the same space as the adjacent side, from the origin to the lines’ ends. Thus, they are equal, so the ratio is 1.

Sine

Definition: opposite / hypotenuse

Circle with a 90° triangle from its center

With the hypotenuse at 90° (or τ/4), there basically is no adjacent side: The hypotenuse is in exactly the same space as the opposite side, from the origin to the lines’ ends. Thus, they are equal, so the ratio is 1.

Cosine and sine: What if we swap them?

Try sin 0 or cos τ/4. What do you get?

Zero, of course. The 0° triangle has effectively no opposite side, so the sine of that (tri)angle is 01, which is zero.

Likewise, the 90° triangle has effectively no adjacent side, so the cosine (adjacent/hypotenuse) of that (tri)angle is 01.

Tangent

Definition: opposite / adjacent

You should be able to guess what the triangle for which tangent returns 1 looks like. Go on, take a guess before you scroll down.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Circle with a 45° triangle from its center

A 45° (tri)angle’s adjacent and opposite sides are equal, which is what makes the tangent function return 1.

Cosine and sine: The unit circle

Cosine and sine return the ratio of one side or the other to the hypotenuse.

Accordingly, the length of the hypotenuse affects the result. But, again, these functions take only an angle, so where do you tell it what hypotenuse to use? And why do these functions, on any calculator and in any programming language, return only a single number?

The trigonometric functions are defined in terms of the unit circle, which is a circle with radius 1.

If you look at the diagrams above, you’ll notice that the hypotenuse of the triangle always extends to the perimeter of the circle—that is, it’s always equal to the radius. This is no accident: The hypotenuse of the constructed triangle is the radius of the circle. And since the radius of the unit circle is 1, that means the hypotenuse of the imaginary triangle is 1.

Thus, the fractions that cosine and sine return are adjacent / 1 and opposite / 1. That’s why they return single numbers: the “/ 1” is simplified out.

From this follows the method to compute cosine or sine for an arc with a different radius: Multiply the cosine or sine by the desired radius.

Cosine and sine: What if we use an angle greater than 90°?

What happens if we take the cosine and sine of an angle like, say, 4 radians (about 230°)?

Let’s draw out the triangle:

Circle with a 230° triangle from its center

Geometrically, the origin is 0,0. As long as we’re in the 0–90° range, no problem, because both the x (cosine) and y (sine) values in that quadrant are positive. But now we’re in negative territory.

With the hypotenuse in this quadrant, the adjacent and opposite sides are now negative numbers. cos π = cos τ2 is -1, and sin (τ×34) is likewise -1. For this triangle, they’re similarly negative, though not -1.

(Exercise: What about the other two quadrants? What are the cosine and sine of, say, 110° and 300°?)

Tangent: What if we use an angle greater than 45°?

As we saw above, if we give the tangent function an angle of τ/8, the ratio is 1. What if we go higher?

Well, then the ratio goes higher. Very quickly.

Graph of tan(x) for x = 0 → τ/4

The half-curve at left is the quadrant from 0 to τ/4 (the upper-right quadrant).
The curve in the middle is the two quadrants from τ/4 to τ×34 (the entire left half of the circle).
The half-curve at right is the quadrant from τ×34 to τ (the lower-right quadrant).

In words, the tangent function returns a value from 0 to 1 (inclusive) for any angle that is a multiple of π plus or minus τ4 (45°). 0 counts (it’s 0π), as does π, as does π2 (= τ = 360°), and so on. Likewise 45°, 360-45=315°, 180-45=135°, 180+45=215°, etc.

Segmentation of a circle by what sort of values tan(x) returns

Outside of those left and right quadrants, the tangent function curves very quickly off the chart—it approaches infinity.

(Programmer note: In some environments, there are both positive and negative values of zero, in which case tan 0 returns positive zero and tan π returns negative zero. Mathematically, there is only one zero and it is neither positive nor negative.)

Tangent is the only one of the three that can barf on its input. Namely, a hypotenuse angle of τ/4 (90°) equates to the opposite (vertical) side being 1 and the adjacent (horizontal) side being 0 (as shown above for the sine function), so tan τ4 = 1/0, which is undefined. The same goes for tan τ34, which equates to -10.

The tangent of an angle is its slope, which you can use to reduce an angle down to whether it is more horizontal (-1..+1), more vertical (< -1 or > +1), perfectly horizontal (0), or perfectly vertical (undefined).

As a practical matter, whenever I need to compute a slope ratio, I special-case perfectly vertical angles to result in ∞.

Cosine and sine: Width and height

From the above definitions, the practical use of cosine and sine emerges: They return the width and height of the right triangle whose hypotenuse has that angle.

As described above, these results are typically interpreted in terms of the unit circle (a circle with radius 1), meaning that the hypotenuse of the triangle is 1. Thus, if you’re working with an arc or circle with a different radius, you need to multiply your cosine or sine value by that radius.

A practical problem

For example, let’s say your friend has a 50″ TV, and you’re wondering what its width and height is. Maybe she’s moving, or giving or selling it to you, or both, so one of you is going to need to know whether and where it’ll fit.

The length of the hypotenuse is the radius of the circle; in the unit circle, it’s 1, but we’re dealing with a hypotenuse (diagonal measurement of the screen) whose length is something else. Our radius is 50″.

Next, we need the angle. No need for a protractor; TVs typically have an aspect ratio of either 16:9 (widescreen) or 4:3 (“standard”). The aspect ratio is width / height, which is the inverse of the slope ratio: the ratio that the tangent function gives us (which is opposite / adjacent, or height / width). Dividing 1 by the aspect ratio gives us the slope.

Only problem is now we need to go the opposite direction of tangent: we need to go from the slope ratio to the angle.

No problem! That’s what the atan (arctangent) function is for. (Each of the trigonometric functions has an inverse, with the same name but prefixed with “arc” for reasons I have yet to figure out.)

atan takes a slope ratio and gives us, in radians (fraction of τ), the angle that corresponds to it.

Let’s assume it’s an HDTV. (I don’t want to think about trying to move an old 50″ rear-projection SDTV.) The aspect ratio is 16/9, so the slope is 9/16 (remember, tangent is opposite over adjacent); atan 916 is about 29–30°, or about 0.5 radians.

Diagram of a right triangle of 30° within a circle

I promise that my choice of 30° for the first example and subsequently deciding to measure an HDTV as the example use case was merely a coincidence.

So we have our angle, 0.5 radians, and our radius, which is 50″. From this, we compute the width and height of the television:

  • Take the cosine and sine of the angle. (Roughly 0.867 and 0.577, respectively, but use your calculator.)
  • Multiply each of these by 50 to get the width and height (respectively) in inches. (Roughly 44″ and 29″, respectively, rounding up for interior-decorative pessimism.)
  • Add an inch or two to each number to account for the frame around the viewable area of the display.

So the TV needs about 45 by 30 inches of clear space in order to not block anything.

More good iOS games

 

2013-05-25 17:48:32 UTC

Inspired by this post from last year by Mike Lee, here’s a list of the best games from my iOS app library.

Many games are excluded, for any of these reasons:

  • Games on this list must not be violent (e.g., I excluded Carmageddon and even Bastion, Sonic 2, and Sonic 4)
  • Games on this list must not be Zynga-tastic (e.g., I excluded Draw Something)
  • Games on this list must not be on last year’s list (see Mike’s post)

Also, I’ve restricted myself to iOS games. Some of the games below are available on multiple platforms, but all of the links are to the iOS App Store.

The games

(Enigmo violates the “not on Mike’s list” requirement, but I gave it a pass for two reasons: because I linked to both the iPhone and iPad versions, and because I linked to the sequel.)

A language-contrast exercise

 

2013-03-31 14:59:34 UTC

Python’s str type has a translate method that, given a second string representing a translation table, returns a new string in which characters in the first string are looked up at their ordinal positions in the translation table and replaced with the characters found at those positions.

The identity translation table, performing no changes, is table[i] = i. For example, table['!']* is '!', so exclamation marks are not changed. If you made a table where table['!'] were '.', exclamation marks would be changed to periods (full stops).

I’d like to see implementations of a program that does that, with the input string encoded in UTF-16 and the translation table encoded in UTF-32 (a 0x11000-element long array of UTF-32 characters), with the table initialized to its identity: table[i] = i.

And yes, you need to handle surrogate pairs correctly.

Some languages that I would particularly like to see this implemented in include:

  • C
  • Haskell
  • LISP
  • A state-machine language (I don’t know of any off-hand; this might be their time to shine)

I know how I would do this in C, and I’m sure I could bash something out in Python, but how would you do this in your favorite language?

As a test case, you could replace “ and ” (U+201C and U+201D) with « and » (U+00AB and U+00BB).

If you want to post code in the comments, <pre>…</pre> should work. Alternatively, you can use Gist.

* I’m using the C sense of '!' here. In Python, this would be table[ord('!')], since characters in Python are just strings of length 1, and you can’t index into a string with another string; ord is a function that returns the ordinal (code-point) value of the character in such a string.

“The Matrix”—the first movie—is one of my favorite movies for a few reasons, of which two stand out:

  • The visuals and sound design are exceptionally well-crafted. For just one example, consider the moment early in the movie where the human police officer unbuttons his handcuffs pocket on his belt. That moment shows the kind of beautiful sound design that you hear several times throughout the movie.
  • In the dialog, nearly everything is significant in at least one, usually more, way.

I’ll demonstrate the latter with the full text of the police interview between Agent Smith and Thomas Anderson, starting 17 minutes and 15 seconds into the film.

SPOILERS BELOW


ANDERSON is already seated at the interview table. Enter Agents SMITH, NUMBER TWO, and NUMBER THREE. TWO and THREE enter first and stand on either side of ANDERSON; SMITH sits across from ANDERSON at the table.

SMITH plops a thick green folder onto the table, whereupon ANDERSON looks at it. He then looks up at SMITH, who looks back at ANDERSON. SMITH then unwinds the cord that holds the folder shut, opens it, and begins to leaf through the pages while ANDERSON watches.

SMITH: As you can see, we’ve had our eye on you for some time now, Mr. Anderson.

This is the scene where they’re about to start monitoring him even more deeply.

SMITH: It seems that you’ve been living two lives.

SMITH: In one life, you’re Thomas A. Anderson, program writer for a respectable software company.

In a world of computers, a “program writer” would be pretty powerful, no?

SMITH: You have a Social Security number, you pay your taxes, and you… help your landlady carry out her garbage.

SMITH: The other life is lived in computers, where you go by the hacker alias “Neo” and are guilty of virtually every computer crime we have a law for.

SMITH: One of these lives has a future… and one of them does not.
[SMITH closes the folder to punctuate his last statement]

At this stage of the movie, and in this context, we’re meant to conclude—as Anderson himself presumably does in his situation—that Smith means that Anderson has a future, and Neo does not—that Anderson’s life of crime, as “Neo”, must come to an end, ideally with Anderson’s cooperation.

Of course, what actually happens later in the movie is the opposite: It is Neo who lives on past the end of the movie, and Anderson, the resident of the Matrix, whose time will soon end.

SMITH: I’m going to be as forthcoming as I can be, Mr. Anderson. You’re here because we need your help.

Again, we’re meant to believe at this point that this is simply a police interrogation, that the Agents are “Agents” in the FBI sense of the word. We are thus meant to believe that “help” means Anderson’s voluntary cooperation.

They need his help, all right, but they do not need his cooperation.

[SMITH takes off his sunglasses]

SMITH: We know that you’ve been contacted by a certain individual, a man who calls himself “Morpheus”. Whatever you think you know about this man is irrelevant. He is considered by many authorities to be the most dangerous man alive.

More words that don’t mean what we think (and Anderson would think) they mean. “Authorities”, again, does not simply refer to law enforcement; it refers to the computer systems in charge of the Matrix. “Dangerous” not in the sense of life-threatening, but dangerous to the Matrix.

[SMITH points briefly to TWO and THREE]
SMITH: My colleagues believe that I am wasting my time with you, but I believe you wish to do the right thing. We’re willing to wipe the slate clean [SMITH pushes the folder aside], give you a fresh start.

Anderson isn’t the first person they’ve made such an offer for. This is foreshadowed, ever so subtly, in the first minutes of the movie, and explicitly confirmed later on in the restaurant scene.

SMITH: All that we’re asking in return is your cooperation in bringing a known terrorist to justice.

Unlike Smith, all of Anderson’s lines have exactly one subtext, which is this: Anderson is still a resident of the Matrix, nominally aware that there is a thing called “The Matrix” but unaware of any of the particulars or its significance in his life.

As such, Anderson’s lines have no subtext, and this is, itself, their subtext.

ANDERSON: Yeah. Wow, that sounds like a really good deal. But I think I got a better one: How about, I give you the finger,
ANDERSON: ..|.
SMITH: Hm.
ANDERSON: and you give me my phone call.

[SMITH sighs]
SMITH: Oh, Mr. Anderson.
[SMITH puts his sunglasses back on]

You’ll notice that Smith takes one of his headgear items off when he’s about to behave a bit more human-like. He takes off his sunglasses to do a fairly standard interrogation on Anderson. He takes off his earpiece later on for another, different kind of questioning. In both cases, he puts them back on to return to his normal role as part of a computer system.

SMITH: You disappoint me.
ANDERSON: You can’t scare me with this Gestapo crap. I know my rights. I want my phone call.
SMITH: Tell me, Mr. Anderson… What good is a phone call if you’re unable to speak?
[ANDERSON’s mouth begins to seal; ANDERSON stands up from his chair as he panics]
[TWO and THREE walk over and seize ANDERSON, open ANDERSON’s shirt, and throw ANDERSON onto the table as SMITH steps away from it]

SMITH: You’re going to help us, Mr. Anderson…
[SMITH takes out a case full of tracers, and takes one out of the case]
SMITH: whether you want to or not.

One of the aforementioned implications is resolved here: As I mentioned above, they need only Anderson’s help, not his cooperation.


The richness of subtext in “The Matrix” isn’t limited to that one scene by any means. Most of Morpheus’s lines are similar, and the Oracle does it every bit as much as you’d expect. (“You look like you’re waiting for something. … Your next life, maybe. Who knows?”)

This is just an example, and it’s just one of the reasons why I love this movie.

I was at Staples today and saw a Microsoft Surface (the tablet, not the big-ass table) demo unit, so I spent about ten minutes with it.

Illustration of a laptop, with the thicker, heavier portion resting on the desk, and the Surface, with its keyboard cover on the desk and the thicker, heavier portion sticking up.
Yup, that’s accurate. (No idea who made it, but here’s where I grabbed it from.)

  • Their demo unit was in the Desktop (classical Windows minus Start menu) view when I found it. Looks about the same as it does on a Windows 8 laptop. The desktop proper only had the Recycle Bin on it.

  • As I’d figured out previously on a Windows 8 laptop, the Windows key on the keyboard switches in and out of the Start screen, which replaces the Start menu in previous versions of PC Windows with something a lot more like the Mac’s Dashboard.

  • I tried two of the widgets, or whatever they’d call the things on the Start screen. The first was Games, which resembles the Xbox 360 dashboard (and even says “xbox games” at the top), set in the typographic theme of Windows 8.

  • Of the half-dozen or so games listed there, most had the “Play” button disabled. The one that didn’t was “Angry Birds Space”, which gave me a barely-meaningful error message (something along the lines of “link not recognized; would you like to show this app in the Windows Store?”).

  • When I launched Word and chose the Blank Document template, it displayed the document as ready to type into briefly, then showed some kind of tutorial dialog or something (I closed it without caring enough about what it said to read it, as I do with all such dialogs). Thanks for the interruption, Microsoft.

  • Tapping on the screen instead of using a mouse feels more natural than I’d expected, although it helps having had a year and a half of training from the iPad. There’s no mouse cursor to be revealed by such actions, unlike past touch-screen versions of Windows.

  • Word on the Surface feels like a simplified version, as Pages is on the iPad. But maybe there’s some progressive disclosure that I didn’t drill down into.

  • Imagine typing on a Smart Cover. That’s about what typing on the Surface’s keyboard cover is like. You can feel some give underneath your fingers, but there’s no tactile feedback by which to know that the keypress has registered. For this reason alone, I can’t see myself adopting this as my daily driver for Real Writing as some have with the iPad + a Bluetooth keyboard.

  • Once I got a little bit used to the keyboard cover’s key-feel, my accuracy was somewhere close to what I get on my iPad’s on-screen keyboard. Unfortunately, the Surface (or at least Word, at least however it was configured there at that moment) doesn’t have auto-correct like the iPad has, so my actual output accuracy was significantly lower.

  • The biggest problem was insufficient keypresses causing missing characters. The iPad doesn’t have this problem, since a keypress is only insufficient if you miss the key outright.

  • I didn’t attempt to detach the Surface from its keyboard cover, which might have been prevented for anti-theft reasons even if it is possible with sold units. Consequently, I don’t know whether there’s an on-screen keyboard for typing without the keyboard cover.

There are no official ebooks of SICP, but there are a few unofficial ebook conversions from the free web version. Here are the two best versions I’ve found:

An insight on the construction of meals

 

2012-12-22 02:25:37 UTC

Last year, I started cooking for myself rather than depending on microwaved meals and fast food.

Earlier this year, a realization dawned on me, pertaining to the basic food groups that were drilled into every kid’s head via TV when I was growing up.

Those old PSAs talked about healthy eating, and how it was Very Important to eat something from the “four basic food groups” with every meal. As a kid who greatly preferred cookies to celery, this was no sale to me—I didn’t give a rat’s ass how healthy it was or wasn’t, I wanted food that tasted good. All the droning about “healthy eating” did nothing to make me think about it when deciding what I wanted.

Fast forward 20 or so years, and it hits me: Those “four basic food groups” (the number has varied over the years, as the aforelinked article outlines) are the framework of constructing a meal.

Nearly every single meal in the American diet is some combination of those four groups.

(This is particularly true of dinner. Numerous meals for other times of day leave out some of the groups.)

Here are the groups as I was taught them:

  • Meat (nowadays more generally classified as Protein)
  • Grains, especially bread
  • Fruit and veg
  • Dairy, such as cheese

Butter seems to often get filed under “fat” and excluded, which is technically true, but whenever it makes it to the plate, I think it makes more sense to file it under dairy. (Another reason to shun margarine, the False Butter.)

Let’s look at some example meals and how they satisfy the categories.

Note: I’m not claiming that these are all healthy meals—those healthy-eating PSAs are simply where I got the “four basic food groups” from. I’m reappropriating the groups as a framework for constructing meals. Anything that checks all four boxes is automatically a complete meal.

Also, this is mostly observation, not prescription. My epiphany is that most meals, particularly nearly all dinners, already fit this framework.

Cheeseburger
  • Bread/grains: Bun
  • Meat: Beef patty
  • Fruit/veg: Any of lettuce, tomatoes, pickles, onions
  • Dairy: Cheese
Spaghetti and meatballs
  • Bread/grains: Pasta
  • Meat: Beef meatballs
  • Fruit/veg: Marinara sauce
  • Dairy: Cheese
Pizza
  • Bread/grains: Crust
  • Meat: Toppings; often pepperoni, ham, sausage, or a combination thereof
  • Fruit/veg: Sauce, plus some toppings, such as pineapple
  • Dairy: Cheese
Sandwich
  • Bread/grains: Sliced bread, such as white, wheat, rye, or sourdough
  • Meat: Sliced turkey, roast beef, or other
  • Fruit/veg: Lettuce and/or tomato
  • Dairy: Cheese
Dinner plate
  • Bread/grains: Often potato-based, such as baked or mashed potatoes; alternatively, rice
  • Meat: Steak, chicken, sliced turkey, etc.
  • Fruit/veg: Varies
  • Dairy: Cheese and/or butter

A meal doesn’t necessarily have to hit all four categories, though. Here are some that don’t:

Hot dog
  • Bread/grains: Bun
  • Meat: Meat frank, usually either beef, turkey, pork, or a mix of turkey, chicken, and pork
  • Fruit/veg: Relish (diced pickles) and/or diced onions (often both omitted)
  • Dairy: Omitted
Chili dog
  • Bread/grains: Bun
  • Meat: See hot dog
  • Fruit/veg: Usually omitted, AFAIK
  • Dairy: Cheese (optional)
Grilled cheese sandwich
  • Bread/grains: As above for sandwich
  • Meat: N/a
  • Fruit/veg: N/a
  • Dairy: Cheese

(On the other hand, panini are basically grilled cheese sandwiches that may include meat and/or fruit/veg.)

Bowl of cereal
  • Bread/grains: Cereal
  • Meat: N/a
  • Fruit/veg: Some folks put chopped strawberries or bananas on theirs, at least in the commercials
  • Dairy: Usually milk, but I eat mine dry
Pancakes/waffles
  • Bread/grains: Pancakes/waffles
  • Meat: N/a
  • Fruit/veg: As above for cereal, but can also include blueberries or similar berries (which may be either whole as a topping or chopped and mixed into the batter)
  • Dairy: Butter (optional)
Hamburger
  • Bread/grains: Bun
  • Meat: Beef patty
  • Fruit/veg: As above for cheeseburger
  • Dairy: N/a

A few points I want to acknowledge:

  • Vegetarians will, of course, exclude the meat category. (I consider veggie meats, such as tofu burger patties, to be cheating—you don’t get to check the meat box by having fake meat.) Some vegetarians will also exclude dairy.
  • Various dietary conditions, such as celiac disease, greatly restrict what sufferers can eat. I can barely imagine the problems that the tendency of American meals to fit this framework causes to sufferers of dietary restrictions that break it. (Those with celiac disease, for example, must not eat nearly all bread items—anything with gluten.)
  • I know very little of cuisine outside of the US. I wonder how much cuisine outside the US fits this same template, and how much is radically different.

This insight leads me to two conclusions:

  1. I can “invent” other meals that I might like simply by swapping items in the four boxes.
  2. It could be a worthwhile adventure to try to break out of this framework. What would a complete meal look like that doesn’t fit into all four categories? Vegetarians will have some idea in one direction; what other possibilities are there?

How to create a new class in Xcode 4

 

2012-10-16 12:36:04 UTC

  1. Choose which group you want to put the class into. You must do this first, before anything else, or you will have even more work to do later.
  2. Right-click on the group or on any file reference inside it. You must create the class this way, or you will have even more work to do later.
  3. Choose “New File”. You use this same command to create classes, nibs, storyboards, plists, and files of several other types. There is no “New Class” command, and the command is called “New File” even though it often creates multiple files.
  4. Choose which platform you want to create this class for. You must choose exactly one, even if your project is cross-platform, and even if this class will be cross-platform (e.g., NSManagedObject subclass). Even if your project is single-platform, the platform for which the file(s) should be created will not be inferred from the project’s platform.
  5. (Optional) Choose which group of file templates to look in.
  6. If you performed step 5, and guessed wrong, correct yourself. (For example, OS X nibs are not among the “Resource” templates, even though they go in the Resources subfolder. You want “User Interface”.)
  7. Choose which template to use.
  8. Set the class name.
  9. Set the superclass name.
  10. Turn on “With XIB for user interface” if you’re creating a window controller or view controller.
  11. Choose where to save the file(s).
  12. Nibs created along with a WC or VC are created unlocalized (outside of a .lproj folder), so if you did step 10, select the nib and click “Make localized”.

It seems to me that there is room here for optimization.

How to ride a bike

 

2012-10-02 12:05:17 UTC

For the past year (2011–2012), I’ve been teaching myself to ride a bicycle. My goal is transportation; I’d like to be able to ride at least a mile or two without burning gasoline.

I would not have been able to do this by myself without YouTube. You can learn about any bicycle-related topic you’re interested in; all you have to do is find the right video (or videos).

Background

I’m 28 as I write this; I was 26 or 27 when I started (I don’t remember which month it was). How didn’t I know how to ride a bike already?

I had a bike as a kid, with training wheels. My parents wanted to take the training wheels off. I objected on the quite reasonable grounds that the bike stayed upright just fine with the training wheels, so why did they want to make it capable of falling over?

So they gave me an ultimatum: Either we take the training wheels off, or we put the bike away and you don’t ride it again until you change your mind. Guess which one I chose.

(More recently, I found out that there’s a right and a wrong way to use training wheels. What you’re supposed to do is raise them up, a little bit at a time, so that eventually they’re nowhere near the ground, by which point the child doesn’t need them anymore and might not even notice if you take them off. That’s not what my parents did, so I never learned to ride without training wheels.)

Step 1: How to not fall over

Read the rest of this entry »

Characters in NSString

 

2012-06-03 18:43:45 UTC

Working with Unicode in any encoding but UTF-32 (which we don’t use because, for nearly all text, it wastes tons of memory) has some pitfalls:

As UTF-8’s name implies, its code units (roughly speaking, character values) are 8 bits long. ASCII characters are all one code unit long (in UTF-8, this means that 1 ASCII character == 1 byte), but any character outside of that range must be encoded as multiple code units (multiple bytes). Thus, any single character above U+007F will end up as more than one byte in UTF-8 data.

This first observation is not limited to Emoji; it’s true of most characters in Unicode. Most characters take up more bytes in UTF-8 data than “characters” in an NSString.

As we’ll see a couple of tweets later, though, even NSString’s length can be problematic.

UTF-16 data may begin with a single specific character that is used as a byte-order mark.

(I should point out, just in case it isn’t obvious, that code units in UTF-16 are two bytes, as opposed to UTF-8’s one-byte code units. This still isn’t enough to encode any Unicode character in a single code unit, though, which will become important shortly.)

The BOM’s code point is U+FEFF. If you encode this in big-endian UTF-16 (UTF-16BE), it comes out as 0xFEFF, exactly as you’d expect. If you encode it in UTF-16LE, it comes out as 0xFFFE, which is not a character.

Thus, a BOM indicates which byte-order all of the subsequent code units should be in. If the first two bytes are 0xFFFE, you can guess that it’s 0xFEFF byte-swapped, and if that’s true, then the rest of the code units (if indeed they are UTF-16) are little-endian. The BOM isn’t considered part of the text; it’s removed in decoding.

The BOM is also used simply to promise and detect that the data is UTF-16: If you see one, whichever way it is, then the rest of the data is probably UTF-16 in one form or the other.

So it’s useful to include the BOM for data that may be saved somewhere and later retrieved by something that may need to determine its encoding.

-[NSString dataUsingEncoding:] includes the BOM, so that you can just take the data and write it out (if it is the whole data—more on that in a moment). Since the data it returns has the BOM character in it, the data’s length includes the two bytes that encode that character. -[NSString lengthOfBytesUsingEncoding:], on the other hand, counts only the bytes for the characters in the string; it does not add 2 bytes for a BOM.

A corollary to this is that if you send dataUsingEncoding: to an empty string, the data it returns will not be empty. So, are you testing whether the string you’ve just encoded is empty by testing whether the data’s length is zero? If so, your test is always succeeding/always failing.

One problem with the BOM is that it should only appear at the start of the data, which means you can’t just encode a bunch of strings using dataUsingEncoding: and then, say, write them all to a file or socket one after another, because the output will end up with BOMs (or, worse, invalid characters, namely U+FFFE) sprinkled throughout.

The naïve solution to that is to staple strings together, then encode and write out the entire agglomeration. If performance (particularly memory consumption) is an issue and you’re writing the output out piecemeal anyway, a more efficient solution would be to use getCharacters:range: or getBytes::::::: to extract raw UTF-16 code units into your own buffer.

Unicode, the character set, can hold up to 0x20000 characters. Foundation’s unichar type is 16-bit, which means it can only hold values within the range of 0x0000 to 0xFFFF.

This is a problem for all of the characters above 0xFFFF, including the Emoji characters, which are in the range from U+1F300 to U+1064F.

UTF-16 addresses this problem by means of a system called surrogates. It’s similar to what UTF-8 does for the same problem, except that the values that UTF-16 uses are within two defined ranges of actual characters.

Surrogates come in pairs. The first one is called the high surrogate, and the second is called the low surrogate. The ranges of usable characters are named accordingly.

The bomb character, 💣, encodes to UTF-16 as 0xD83D 0xDCA3.

NSString and CFString use the word “character” all over the place, but what they really mean is “UTF-16 code unit”. So the aforementioned single-character string actually contains two “characters”:

2012-06-03 13:15:45.498 test[14761:707] 0: 0xD83D
2012-06-03 13:15:45.501 test[14761:707] 1: 0xDCA3

Beware of such things when enforcing length limits. Be sure of whether you’re counting ideal characters or code units in some encoding. Also make sure you’re clear on whether a destination with a length limit (e.g., Twitter) counts up to that limit in ideal characters or in code-units in some encoding.

Also, as @schwa mentions in the same tweet, this all applies to characterAtIndex: as well (indeed, everything in NS/CFString that talks about “characters”). So, for example, [bombString characterAtIndex:0UL] will really retrieve only half of the character.

As noted above, each of these Emoji characters is encoded in UTF-16 as two code units in a surrogate pair. A surrogate pair has a high surrogate and a low surrogate.

The high surrogate identifies a range of 210 characters; the low surrogate identifies a specific character within that range. Since the poop character and the bomb character are within the same range, they have the same high surrogate—i.e., the same first “character” in their NSString/UTF-16 representations.

As the example demonstrates, just because a string contains only one ideal character doesn’t mean that characterAtIndex:0 will return 1.0 character. It may return 0.5 characters.

Greg Titus answered this one for me:

No worries about surrogate pairs or lengths greater than 1 for characters that exist in ASCII (≤ U+007f).

Recap

  • “Characters” in NS/CFString are really UTF-16 code units.
  • Some characters in Unicode—including, but by no means limited to, Emoji—are outside the range of what a single UTF-16 code unit—a single NSString “character”—can hold.
  • Therefore, do not assume that a single character is a single “character”.
  • Neither should you assume that a single character will be a single byte in UTF-8. That sounds obvious, but…
  • Both of the preceding rules can trip you up when checking against length limits (or sending text to something else that will do such a check). Make sure you know whether the limit is in ideal characters (U+whatever) or code units in some encoding, and make sure you count the appropriate unit and do so correctly.
  • Those rules also have a way of tripping you up whenever you extract a single “character” at a time from a string. You should probably only do this when looking for known ASCII characters (e.g., for parsing purposes), and even then, please consider using NSScanner or NSRegularExpression instead.

On the API design of CGBitmapContextCreate

 

2012-06-01 03:24:38 UTC

Let’s review the prototype of the CGBitmapContextCreate function:

CGContextRef CGBitmapContextCreate (
 void *data,
 size_t width,
 size_t height,
 size_t bitsPerComponent,
 size_t bytesPerRow,
 CGColorSpaceRef colorspace,
 CGBitmapInfo bitmapInfo
);

The arguments:

  • data may be a pointer to pixels. If you pass NULL, the context will create its own buffer and free that buffer itself later. If you pass your own buffer, the context will not free it; it remains your buffer that you must free after you release the context, hopefully for the last time.
  • width and height are what their names say they are, in pixels.
  • bitsPerComponent is the size of each color component and the alpha component (if there is an alpha component), in bits. For 32-bit RGBA or ARGB, this would be 8 (32÷4).
  • bytesPerRow is as its name says. This is sometimes called the “stride”.
  • colorspace is a CGColorSpace object that specifies what color space the pixels are in. Most importantly, it dictates how many color components there are per pixel: An RGB color space has three, CMYK has four, white or black has one. This doesn’t include alpha, which is specified separately, in the next argument.
  • bitmapInfo is a bit mask that specifies, among other things, whether components should be floating-point (default is unsigned integer), whether there is alpha, and whether color components should be premultiplied by alpha.

The most immediate problem with this function is that there are so damn many arguments. This is especially bad in a C function, because it’s easy to lose track of what each value specifies, especially when so many of them are numbers. Suppose you want to make an 8-by-8-pixel grayscale context:

CGContextRef myContext = CGBitmapContextCreate(NULL, 8, 8, 8, 8, myGrayColorSpace, kCGImageAlphaNone);

Now, without looking at the prototype or the list, which argument is bitsPerComponent, which is bytesPerRow, and which are width and height?

Objective-C’s names-and-values message syntax can help with this, as we can see in the similar API (for a different purpose) in NSBitmapImageRep:

NSBitmapImageRep *bir = [[NSBitmapImageRep alloc]
    initWithBitmapDataPlanes:NULL
                  pixelsWide:8
                  pixelsHigh:8
               bitsPerSample:8
             samplesPerPixel:4
                    hasAlpha:YES
                    isPlanar:NO
              colorSpaceName:NSCalibratedRGBColorSpace
                 bytesPerRow:8
                bitsPerPixel:8*4];

But this has other problems, notably the redundant specification of bitsPerPixel and samplesPerPixel. With that and the isPlanar argument, this method takes even more arguments than CGBitmapContextCreate. More importantly, it doesn’t solve the greater problems that I’m writing this post to talk about.

EDIT: Uli Kusterer points out that bitsPerPixel is not redundant if you want to have more bits not in a component than just enough to pad out to a byte. That’s a valid (if probably unusual) use case for NSBitmapImageRep, so I withdraw calling that argument redundant.

I’m going to use the example of both of these APIs, but mainly CGBitmapContextCreate, to talk about a few principles of API design.

The first is that it should not be possible for an object to exist in an unusable state. From the moment a freshly-created object is returned to you, you should be able to use it without it blowing up in your face.

From this principle follows a corollary: Everything an object needs in order to function, it should require when you instantiate it. Otherwise, the object would exist without the needed information—and thereby be unable to function—until you provide it.

It might seem that these APIs are as long as they are in order to uphold that principle. After all, a bitmap context needs to have someplace to put its pixels, right? (In fact, CGBitmapContextCreate‘s buffer argument was required until Snow Leopard and iOS 4.) It needs to know what format the pixels should be in, right?

Now for the second principle: Any information that an object does not need in order to function should be omitted from initialization and provided afterward. In Objective-C, the most common means of this post hoc specification are readwrite properties and delegate messages. Generally, for anything that could be specified in the initializer, the post hoc way to specify it would be via a property.

We’d like to invoke the second principle and move things out of the initializer, but that would seem to conflict with the first principle: What can we move that the context does not require?

The resolution is in a third principle—one that is not specific to APIs, but applies to all interfaces, including user interfaces: An interface should have reasonable defaults for as many parameters as it can—it should only require the user to provide values for parameters for which no default can be reasonably chosen in advance.

With that in mind, let’s look at some of CGBitmapContextCreate‘s arguments and see how we might apply the reasonable-defaults principle to simplify it:

  • bitsPerComponent, bitmapInfo, and colorspace: Most commonly, the caller will want 8-bit RGBA or ARGB, often with the goal of making sure it can be used on the graphics card (either by way of a CG- or CALayer or by passing the pixels directly to OpenGL). That’s a reasonable default, so these three can be eliminated.

    We could make them properties, but there’s an alternative: We could dynamite bitmapInfo and merge some of its values with bitsPerComponent in the form of several pixel-format constants. You’ve seen this approach before in QuickTime and a few other APIs. CGBitmapContext only supports a specified few pixel formats anyway, so this simply makes it impossible to construct impossible requests—another good interface principle.

  • bytesPerRow: Redundant. The number of bytes per row follows from the pixel format and the width in pixels; indeed, CGBitmapContextCreate computes this internally anyway and throws a fit if you guessed a number it wasn’t thinking of. Better to cut it and let CGBitmapContextCreate infer it.

    Making you compute a value for bytesPerRow does provide an important safety check, which I’ll address shortly.

    EDIT: Alastair Houghton points out another case for keeping bytesPerRow. This doesn’t apply to CGBitmapContextCreate, which rejects any value that doesn’t follow from the pixel format and width in pixels, but could be valid for NSBitmapImageRep and CGImage.

  • data (the buffer): Since Snow Leopard and iOS 4, the context will create its own buffer if you don’t provide one. That makes it explicitly optional, which means it is not required.

The only arguments that are truly required are the width and height, which tell the context how many pixels it should allocate its initial buffer for in the given (or default) pixel format.

In fact, if we take the above idea of replacing three of the arguments with a single set of pixel-format constants, then we don’t actually need to make any of the properties readwrite—there isn’t any reason why the owner of the context should be changing the pixel format on the fly. You might want to change the width or height, but CGBitmapContext doesn’t support that and we’re trying to simplify, not add features.

So, what problems do the current APIs solve, what problems do they raise, and how would we address all of both problems?

  • Specifying the pixel format (bitsPerComponent, colorspace, bitmapInfo) up front saves the context having to reallocate the buffer to accommodate any pixel-size changes.

    If we simply removed the pixel format arguments from the initializer and made them readwrite properties (or a property), then the context would have to reallocate the buffer when we change the pixel format from the default (ARGB or something similar) to something else (e.g., grayscale).

    The immediate solution to that would be for the context to allocate its buffer lazily the first time you draw into it, but that would mean every attempt to draw into the context would hit that “have we created our buffer yet” check.

    A better solution would be to follow the above idea of condensing the specification of the pixel format down to a single constant; then, we could have a designated initializer that would take a pixel-format value, and a shorter initializer for the default case that calls the DI with the default pixel-format value.

  • Specifying the buffer as a plain pointer (or pointer to one or more other pointers) requires the dimensions of the buffer to be specified separately.

    It’s a mystery to me why CGBitmapContextCreate doesn’t take a CFMutableData and NSBitmapImageRep’s initializers don’t take an NSMutableData. With these, the length in bytes would be associated with the buffer, enabling the context/rep to check that the length makes sense with the desired (or default) pixel format. This would be better than the current check in two ways: First, the current check only checks bytesPerRow, ignoring the desired height; second and more importantly, the current check only checks the value you gave for bytesPerRow—it can’t check the actual length of the buffer you provided.

    (From that, you can derive a bit of guidance for using the current API: If you pass your own buffer, you should use the value you computed for bytesPerRow in computing the length of your buffer. Otherwise, you risk using one stride value in allocating the buffer and telling a different one to CGBitmapContextCreate.)

  • Requiring (or even enabling) the buffer to be provided by the caller is redundant when the API has all the information it needs to allocate it itself.

    This was especially bad when the buffer was required. Now that CGBitmapContext can create the buffer itself, even having that optional input is unnecessary. We can cut this out entirely and have the context always create (and eventually destroy) its own buffer.

  • The caller must currently choose values for parameters that are not important to the caller.

    The current API makes you precisely describe everything about the context’s pixels.

    WHY? One of the central design aspects of Quartz is that you never work with pixels! It handles file input for you! It handles rendering to the screen for you! It handles file output for you! Core Image handles filtering for you! You never touch pixels directly if you can help it!

    99% of the time, there is no reason why you should care what format the pixels are in. The exact pixel format should be left to the implementation—which knows exactly what format would be best for, say, transfer to the graphics card—except in the tiny percentage of cases where you might actually want to handle pixels yourself.

With all of this in mind, here’s my ideal API for creating a bitmap context:

typedef enum
#if __has_feature(objc_fixed_enum)
: NSUInteger
#endif
{
    //Formats that specify only a color space, leaving pixel format to the implementation.
    PRHBitmapContextPixelFormatDefaultRGBWithAlpha,
    PRHBitmapContextPixelFormatDefaultRGBNoAlpha,
    PRHBitmapContextPixelFormatDefaultWhiteWithAlpha,
    PRHBitmapContextPixelFormatDefaultWhiteNoAlpha,
    PRHBitmapContextPixelFormatDefaultCMYK,
    PRHBitmapContextPixelFormatDefaultMask,

    PRHBitmapContextPixelFormatARGB8888 = 0x100,
    PRHBitmapContextPixelFormatRGBA8888,
    PRHBitmapContextPixelFormatARGBFFFF, //128 bits per pixel, floating-point
    PRHBitmapContextPixelFormatRGBAFFFF,
    PRHBitmapContextPixelFormatWhite8, //8 bpc, gray color space, alpha-none
    PRHBitmapContextPixelFormatWhiteF, //Floating-point, gray color space, alpha-none
    PRHBitmapContextPixelFormatMask8, //8 bpc, null color space, alpha-only
    PRHBitmapContextPixelFormatCMYK8888, //8 bpc, CMYK color space, alpha-none
    PRHBitmapContextPixelFormatCMYKFFFF, //Floating-point, CMYK color space, alpha-none

    //Imagine here any other CGBitmapContext-supported pixel formats that you might need.
} PRHBitmapContextPixelFormat;

@interface PRHBitmapContext: NSObject

- (id) initWithWidth:(NSUInteger)width
    height:(NSUInteger)height;
- (id) initWithWidth:(NSUInteger)width
    height:(NSUInteger)height
    pixelFormat:(PRHBitmapContextPixelFormat)format;

//There may be an initializer more like CGBitmapContextCreate/NSBitmapImageRep's (taking individual pixel-format values such as color space and bits-per-component), but only privately, to be used by the public DI.

//Mutable so that an asynchronous loader can append to it. Probably more useful in an NSBitmapImageRep analogue than a CGBitmapContext analogue.
@property(readonly) NSMutableData *pixelData;

@property(readonly) NSColorSpace *colorSpace;
@property(readonly) bool hasAlpha;
@property(readonly, getter=isFloatingPoint) bool floatingPoint;
@property(readonly) NSUInteger bitsPerComponent;

- (CGImageRef) quartzImage;
//scaleFactor by default matches that of the main-menu (Mac)/built-in (iOS) screen; if it's not 1, the size (in points) of the image will be the pixel size of the quartzImage divided by the scaleFactor.
#if TARGET_OS_MAC
- (NSImage *) image;
- (NSImage *) imageWithScaleFactor:(CGFloat)scale;
#elif TARGET_OS_IPHONE
- (UIImage *) image;
- (UIImage *) imageWithScaleFactor:(CGFloat)scale;
#endif

@end

With the current interface, creating a context generally looks like this:

size_t bitsPerComponent = 8;
size_t bytesPerComponent = bitsPerComponent / 8;
bool hasAlpha = true;
size_t bytesPerRow = (CGColorSpaceGetNumberOfComponents(myColorSpace) + hasAlpha) * bytesPerComponent * width;
CGContextRef context = CGBitmapContextCreate(NULL, width, height, bitsPerComponent, bytesPerRow, myColorSpace, myBitmapInfo);

With an interface such as I’ve described, creating a context would look like this:

PRHBitmapContext *context = [[PRHBitmapContext alloc] initWithWidth:width height:height];

Or this:

PRHBitmapContext *grayscaleContext = [[PRHBitmapContext alloc] initWithWidth:width height:height pixelFormat:PRHBitmapContextPixelFormatWhite8];

Free stuff on the O’Reilly store

 

2012-05-07 07:04:05 UTC

After downloading a bunch of free O’Reilly books on a run through the Kindle Store, I decided to see which of them were available in O’Reilly’s own store. Here’s what I found.

(Note that I have no intention of updating this list periodically, so some of these may no longer be free or available if you’re reading this some months after I compiled it.)

Publishing

“What Is”

Adobe stuff

Microsoft stuff

“Data products” and “data science”

I have absolutely no idea what order these should be read in, or even really what they’re about.

Some of these are currently in a list of “Free Reports” along the side of O’Reilly’s “Data” category.

Assorted

“Bibliographies”

These are basically catalogs of other (not so free) books.

Analysis of Matias Tactile One Keyboard

 

2012-03-22 12:44:58 UTC

I can’t really call this a “review”, because I don’t have one (it costs two hundred freaking dollars), but I did notice some things about the Matias Tactile One Keyboard (which I saw an ad for in MacTech magazine) that I wanted to write down.

  • Weird fn key placement: They put it where the AEK2 and Tactile Pro have the right ctrl key. (Indeed, it looks like the lower-right caps are the same sizes as their mirror counterparts in the lower-left.)
  • Weird eject (⏏) key placement: It’s fn-return. Huh?
  • Weird ⌦ key placement: It’s where the AEK2 and Tactile Pro have the right option key. That’s because…
  • No six-block. The AEK2 and Tactile Pro have a block of six keys—four navigation-related, plus “help” and ⌦—above the arrow keys, between the letter-board and number pad. The One, for some reason, omits this. The full photo shows an iPhone resting there, but I see a missed opportunity in its place: For two hundred freaking dollars, they could have put in an iPhone/iPod dock in the gap between the function keys, and kept the six-block.
    • As on Apple’s laptops and Wireless Keyboard, they moved the navigation keys onto the arrow keys as their fn variants.
  • PC-style number pad (with double-height plus key and no equals key), even on the so-called Mac version. This made sense for the Unicomp SpaceSaver M and Das Keyboard Model S for Mac, since they’re PC keyboard manufacturers and probably reused the same PCB (also, both of those keyboards’ fn key placement follows from the Windows layout’s extra “menu” key in the same area), but I can’t figure why Matias did this.
  • An extra tab key where the clear key used to be. I like this idea.

The headlining feature of the “One Keyboard” series (and the reason why they call it that) is the fact that you can switch it between talking to your Mac over USB and talking to some other device (nominally an iPhone, iPod touch, or iPad) over Bluetooth. If they brought that and the number-pad tab key to the Tactile Pro, that might be worth $150 to me. (As for $200? No. Never have I wanted to use the same keyboard on both my Mac and iPad.)

Xcode and Friends

 

2012-02-17 04:35:03 UTC

Xcode’s distribution has changed greatly in 4.3.

First, it’s now simply an app, without an Installer package. If you install it through the Mac App Store, it’ll install directly–no more “Install Xcode.app” (which I think I read earlier that you have to delete, although I can’t speak to this myself). If you install it from the disk image, it’s a drag-and-drop install.

Second, the set of applications that come with it (now bundled inside) is now much smaller. The other developer applications have been split out into separate disk images that are only available on connect.apple.com.

So, I thought I’d make a catalog listing where everything is now. Every one of the below sections corresponds to a disk image on connect.apple.com, and with the exception of Xcode, every one of those disk images is only available from connect.apple.com—only Xcode is available from the Mac App Store.

Xcode (and the other core tools)

The core tools are inside Xcode regardless of where you get it from. That will be either:

The applications bundled inside Xcode are:

  • Application Loader: One way of submitting your application to the Mac App Store.
  • FileMerge: Differencing tool. As its name implies, primarily for visually merging three versions rather than comparing two.
  • Icon Composer: Create IconFamily (.icns) files from multiple individual images.
  • Instruments: Use this to make your app more efficient, or to hunt zombies.
  • OpenGL ES Performance Detective

Accessibility Tools for Xcode

  • Accessibility Inspector (a.k.a. UIElementInspector): Examine the Accessibility properties of NS/HIViews in any application.
  • Accessibility Verifier: Automatically runs through an application’s accessible object hierarchy, including windows and views, and produces an outline of things it does wrong or fails to do that could cause accessibility problems for users.

Audio Tools for Xcode

  • AU Lab: Set up chains of Audio Units to filter audio or route it from a source to a destination.
  • CoreAudio: Sample code for some of Core Audio’s older APIs.
  • HALLab: Tool for inspecting the audio object hierarchy.

Auxiliary Tools for Xcode

  • 64BitConversion: Tools for porting 32-bit Cocoa code to 64-bit.
  • Clipboard Viewer: See every type on the clipboard (general pasteboard).
  • CrashReporterPrefs: Change how your system reacts to an application crashing.
  • Dictionary Development Kit: Build your own dictionaries for Dictionary.app.
  • Help Indexer: Makes your Help Books searchable. (Only useful for Mac developers.)
  • LegacyAPISurvey: Tells you what APIs you’re using that are in danger of being deprecated.
  • Modem Scripts: Examples of CCL scripts (essentially, modem drivers).
  • PackageMaker: Build Installer packages.
  • Repeat After Me: Test the Speech Synthesis Manager, exporting to either phoneme text or an AIFF file.
  • SleepX
  • SRLanguageModeler: Something to do with Speakable Items, but I couldn’t figure out how to work it.

Dashcode for Xcode

  • Dashcode: IDE for making Dashboard widgets. It “includes a design canvas that produces the graphics assets for you, as well as a powerful code editor, and even a full JavaScript debugger”.

Graphics Tools for Xcode

  • CI Filter Browser (Dashboard widget)
  • OpenGL Profiler
  • OpenGL Shader Builder
  • Pixie: Like DigitalColor Meter, but more developer-oriented. YMMV on which is better.
  • Quartz Composer: Create compositions that can be used within applications or as screensavers. Also useful for developing Core Image filters.
  • Quartz Composer Visualizer
  • Quartz Debug: Monitor your computer’s graphics performance (global frame rate), toggle various settings in the Quartz Compositor, and enable or disable the HiDPI resolutions.

Hardware IO Tools for Xcode

  • Bluetooth Diagnostics Utility
  • Bluetooth Explorer
  • btdump
  • IORegistryExplorer: See what’s connected to your Mac.
  • Network Link Conditioner (prefpane): Makes your internet connection pretend to suck so you can see how your app performs under such conditions.
  • PacketLogger: Another Bluetooth tool.
  • USB Prober: Inspect your USB buses and the devices connected to them.
  1. You’ll understand the bug better. This means you can write a better bug report, which will help Apple fix it more quickly (meaning you may get the fix more quickly).

  2. They’ll understand the bug better. This, too, helps Apple fix it more quickly.

  3. You may find that it is not a bug in the API at all, but that you were misusing it. Perhaps you were using something on a thread that you shouldn’t have been, or expecting some argument to be used a certain way when it’s actually used differently.

    In this case, you may be able to use the API after all, saving you the time you would have spent hacking around a non-bug. This also saves them the time they would have spent triaging and eventually responding to a non-bug.

    If your misunderstanding was borne out of poor documentation (misleading, inaccurate, vague, incomplete), you can file a bug report about that instead. Then the documentation gets better and future users of the same API avoid making the same error you did.

A test app isn’t appropriate for every kind of Radar, but when it is, including it helps everyone.

iOS device user guides on the iBookstore

 

2011-10-16 14:00:50 UTC

Apple has user guides for their three iOS devices (not counting the TV, in which iOS is an implementation detail), for both iOS 4.3 and 5, free on the iBookstore:

iOS 4.3

iOS 5

Much faster

 

2011-10-15 15:13:33 UTC

I’ve just pushed a couple of improvements to my ISO 8601 date formatter. Previously, it was pathetically slow compared to C standard library parsing and unparsing; now, it is faster.

Timing ISO8601DateFormatter
Time taken: 0.130194 seconds
Number of dates and strings computed: 10000 each
Time taken per date: 0.000013 seconds
Timing C standard library parsing and unparsing
Time taken: 0.192645 seconds
Number of dates and strings computed: 10000 each
Time taken per date: 0.000019 seconds

You’ll want at least revision [61d2959c6921] or later.

My thanks to Sam Soffes and Rudy Richter for alerting me to the speed problem.

Edited at 16:35. Previously, it was almost as fast as C stdlib. Now it is faster.

Desktop picture: Yawning Void

 

2011-09-15 21:10:04 UTC

This is a desktop picture for Macs running at 1366 by 768, such as the 11-inch MacBook Air:

Yawning void

No, it’s not pure black. Yes, that bar at the top is part of it.

It’s meant to be used at that resolution and no other, with menu-bar translucency turned on. Scaling it, especially vertically, will make it look wrong.

If you want to adapt it to a different size, here’s the original document, editable in Lineform. You should scale the document and the background to the desired screen size, and the menu-bar background to the desired width.

Conferences 2011

 

2011-09-12 06:12:23 UTC

It’s that time again! Just like last year, there are a bunch of different conferences going on; unlike last year, I’m not going to even attempt to list all of them.

The two that I have a reason to mention are:

  • Voices That Matter. This time it’s in Boston, November 12 and 13. Their early bird pricing is still on through September; I’ll let their site tell you more. As I do whenever I mention it here, I have a coupon code for it, which is BSTBLOG. As usual, due to time and expense constraints, I won’t be attending this one.
  • MacTech Conference. I’m presenting again—same topic as last year, how to recognize, find, and fix bugs in Cocoa applications, but this time it’s the Xcode 4 edition. The early bird period has ended, but you can get the same $500 off by signing up through this referral link. The time and place is November 2, 3, and 4 in Universal City, California.

Last year at the MacTech Conference, I brought with me some of my useful Cocoa links business card. I’ll be doing that again this year, so if you attend the MacTech Conference, feel free to ask me for one.

I hope to see you at the MacTech Conference!