All posts by Jeffrey J. Early

Profits, privacy, and the business model of Google

I’ve noticed that many people don’t seem to understand how the different business models of Google and, say, Apple result in completely different products, pricing, and privacy terms.

First, it is absolutely a given that both companies’ primary goal is to make money. Second, it is also a given that both companies strive to provide innovating, industry leading products to their customers and both companies are wildly successful.

The part that is apparently not clear to everyone is that when you buy an iPhone from Apple, you are now one of Apple’s customers, but when you sign up for Gmail, you are not one of Google’s customers. If you’re thinking about this correctly, then it should already be plausible to you that Google makes more money from Apple’s iOS on iPhones and iPads than Google does from their own operating system Android. The punchline here is that Apple’s customers are electronics consumers and Google’s customers are advertisers.

The consequences of this difference are huge.

Apple’s business model requires that their electronic gadgets remain appealing enough that they can get your money for one of those gadgets. Compare this to Google’s business model requires that they convince an advertiser that they can get your attention and collect the advertisers money.

If you are a small business owner like me whose enjoys Apple gadgets and has tried advertising with Google, then you have forked over money to both companies and this distinction and the consequences are probably obvious. But what if you are just an electronic gadget consumer with no interest in advertising? Then it’s quite possible that you have used google “products” such as gmail, maps or android for free, but paid a nice premium to buy that new iPhone. Strange, no? So, from this perspective these google products are a fantastic value—how could a company actually wanting to sell you an email client or map program compete?

As it turns out, Apple does have an email client built in the iPhone and available through their iCloud services. For Apple, this email client is used to sell iPhones and other gadgets to you by virtue of their tight integration. For Google, their email client, Gmail, is used to sell advertising to businesses, by virtue of their ability to harvest user data and better target ads to users of Gmail.

So finally, it should be clear that it is in Apple’s interest to keep your information private (since gadget consumers don’t like their information shared), but it is in Google’s interest to harvest your information (since it targets ads better).

Note that you could substitute Sony or Microsoft or Garmin for Apple here, and the same basic logic would apply. The biggest difference is that the advertising model that Google has requires that they find eyeballs, which they have chosen to do by giving away decent software for free. In contrast, the others companies, generally, make their money on the very products they are asking electronics consumers to use. Very different.

Memory leak in ARC with synthesized properties for CF objects

Specifically, if you have a property that looks like this,

@property(readwrite, strong) __attribute__((NSObject)) CGLayerRef theLayer;

which you use to treat Core Foundation objects like usual reference counted objects, you need to set this property to NULL in -dealloc, otherwise an extra reference is maintained.

– (void) dealloc

{

self.theLayer = NULL;

}

Fixed a minor memory leak for me.

Synthesized properties for IBOutlets

I made a huge mistake in my synthesized properties for IBOutlets that resulted in a memory leak and many, many wasted hours. So, here’s what I was doing,

@property(readonly, unsafe_unretained) IBOutletIKImageBrowserView* photoBrowser;

I’m targeting 10.6, so I can’t use a weak property, but have to use an unsafe_unretained — but either way, you would think that this wouldn’t cause the image browser to leak, right? Nope. Here’s what you need,

@property(readwrite, unsafe_unretained) IBOutletIKImageBrowserView* photoBrowser;

Ah, that’s right — the property needs to be read-write, not read-only. Given that the pointer is unretained, I can’t imagine what’s causing this.

Broken Command Line Tools (CLT) in Xcode 4.3

After upgrading to Xcode 4.3 my “make distribution” script for PhotoLinker failed because it couldn’t get the command line tool xcodebuild to work. To fix this, you need to do two things.

1. In the Xcode preferences under ‘Download’, install the command line tools.

2. In the terminal, run,

sudo xcode-select -switch /Applications/Xcode.app/Contents/Developer 

and that will point everything in the right direction.

Trolls and Krugman

I saw two quotes via Jon Gruber that I feel the need to repost.

The first is a wonderful essay on trolls by Paul Graham,

The third cause of trolling is incompetence. If you disagree with something, it’s easier to say “you suck” than to figure out and explain exactly what you disagree with. You’re also safe that way from refutation. In this respect trolling is a lot like graffiti. Graffiti happens at the intersection of ambition and incompetence: people want to make their mark on the world, but have no other way to do it than literally making a mark on the world.

This is why I no longer post anonymously. If I have anything to say that is worthwhile, then I had better be able to put my name behind those words and stand by what I wrote.

The second quote, not unrelated, comes from a contribution by Jonathan Chait in a list of Reasons to Love New York. He explains, better than I possibly could, why it is I love reading Paul Krugman,

The most remarkable attribute Krugman has brought to the Times is rudeness. The social niceties that accompany his exalted position are utterly lost on him. He does not seek out the company of famous politicians and cannot be courted with flattery or access. He understands that you can’t arrive at truth without explaining why mistaken beliefs are wrong.

If you read any of Paul Krugman’s blog you know how much time he spends fighting of forum trolls as well as public trolls (a.k.a, pundits).

Occupy Wall Street (OWS) is off the rails

I was totally behind the principals and methods of the Occupy Wall Street movement for the first several months of its life, but as of the last two weeks, I’m no longer on board.

With first the occupation of vacant, foreclosed homes and now the blocking of shipping ports in Seattle and elsewhere, the movement has drifted to far from its core values and is now in left-wing-liberal-la-la-land. The movement either needs to return to the core idea, the global wealth imbalance, or needs to give up and move on to other forms of political activism.

GC->ARC: From Garbage Collection to Automatic Reference Counting

I just transitioned PhotoLinker and its dependent frameworks from garbage collection (GC) to automatic reference counting (ARC). For the most part this transition went fairly smoothly—I actually had an ARC converted version running in a few days. However, the transition also exposed some poor design patterns (or lack of design patterns one might argue) and ultimately prompted me to do a fairly extensive code refactoring, but I won’t dwell on that here.

The transitioning to ARC release notes are fairly sparse, but do provide most the basic pieces necessary to proceed. ARC and GC use the same basic conceptual rules for memory management: object ownership, strong and weak pointers. With retain and release out the way, this means you use the exact same code for ARC and GC when you’re dealing with pure Objective-C, however, anything outside those bounds and it gets more complicated.

The basic idea is that there are two types of pointers to objects: strong and weak. One or more strong pointers prevent an object from getting deallocated, whereas weak pointers simply point the object and turn to zero if/when the object gets deallocated. The only difference between ARC and GC is that in GC two objects with strong pointers to each other, but no other references, will get deallocated, whereas in ARC this is a retain cycle. So, while you’re coding, just keep in mind which objects have strong pointers to them.

Strong and weak pointers get declared like this in a class definition,

@property(readwrite, strong, nonatomic) NSObject *anObject;

@property(readwrite, weak, nonatomic) NSObject *anObject;

Because the memory management patterns of ARC and GC are nearly identical, there really wasn’t much code transitioning, with one exception: C code. The largest amount of work went into transitioning my primitive C code data chunks that were allocated with NSAllocateCollectable and then freely passed around with weak or strong pointers. Really, it was quite beautiful with GC. I was able to create C structures that contained strong and weak pointers to memory and pass the pointers around freely, while using the same rules that apply to Objective-C objects. Transitioning to ARC meant that I had to do everything in terms of mallocs and frees, and/or wrap things with NSData objects. That was a real pain to transition and, as with anything in C, I ended up with some nasty buffer overflow errors that caused all kinds of trouble.

 

From a developer’s perspective there’s no question that GC was nicer to program with than ARC. Not having retain cycles was great, though not critical. Passing around chunks of malloced memory with the same strong and weak pointer rules was fabulous, and I’m really going to miss that. On the other hand, the coding differences are small and the runtime differences are huge. PhotoLinker with GC on 10.6 was okay, but running PhotoLinker with GC on 10.7 was like getting in a car with a drunk driver: odds are you were going to crash.

I wish I had taken better notes, but here are a few tidbits on transitioning that may be helpful.

– If you want Core Foundation object can be treated as a Cocoa object by using,

@property(atomic, strong) __attribute__((NSObject)) CGLayerRef theLayer;

– When NSMapTable deallocates, it does not cleanup after itself. This means you need to call -removeAllObjects.

 

– When using -beginSheetModalForWindow:ModalDelegate:didEndSelector:contextInfo:, the last argument takes a (void *). Right now I’m casting this as  (__bridge_retained void *) and then getting it as (__bridge_transfer NSArray *) in the alertDidEnd:.

– When implementing -copyWithZone. The first (highest) class needs to call [[self class] alloc] init].