inessential by Brent Simmons

January 2014

Transferring Domains - Day 10

Last night the transfer for inessential.com was completed, and today the transfer for ranchero.com was completed. The nameserver settings went along with the transfer, so there was no interruption in service. Cool.

All that remains now is clean-up — I’ll try to delete my accounts from Network Solutions. Or at least delete as much info as I can. (Especially credit card info.)

The Point of View of the Mouse

When I want to scare myself, I look at my cat and imagine being a mouse.

To a mouse he’s the size an elephant is to us humans. Maybe bigger. He’s huge.

But that’s just the beginning. He’s also fastidiously clean, so you can’t smell him coming. (That’s why cats tend to be such good groomers, I figure.)

And he’s a dark gray tabby, all stripy. Camouflaged.

Imagine you’re in the tall grass at dusk and you’re a mouse. Inches away is a creature bigger than an elephant is to us humans and he’s completely invisible.

That creature is also ridiculously patient and absurdly fast. So fast. And, unlike an elephant, he wants to kill you.

You can’t even think something like, “Oh, 50-50 he’s already eaten and doesn’t care.” Nope. Because it’s just plain fun for the cat. You’re a toy.

It’s worse if he has eaten, because he might want to play with you for a while. (To a mouse, the word “play” is the most shivery word.)

So picture the equivalent for a human. You’re going about your business, walking home from the corner produce store with tonight’s dinner — and a gigantic animal’s claws and teeth grab you out of nowhere. You didn’t even see him coming. You didn’t smell him, or see his shadow, or hear his footsteps. You walked right up to him without even knowing it.

You might get the chance to run a little bit and scream, if you’re unlucky.

Karl

In a recent post I suggested that a good business might be for someone experienced with both Cocoa and server development to do contract work for other Cocoa developers — to write their servers.

I got email from Karl Shea (who I don’t otherwise know). He’s working on building such a business. He’s still learning iOS development, but appears to be already solid on server work.

Transferring Domains - Day 8

I wonder why the wait. Both domain transfers are listed by Hover as waiting for Network Solutions to approve.

What takes so long?

I have three theories:

  1. It just plain takes a while to process requests like this.

  2. For security reasons, Network Solutions doesn’t want to make it too easy to transfer domains. This delay gives someone the chance to stop it before it completes.

  3. For business reasons, Network Solutions doesn’t want to make it too easy to transfer domains. Knowing that there’s a delay will have a negative effect on people’s willingness to start a transfer.

I don’t believe #1, because I don’t think it’s that difficult. It’s probably automated, or largely automated. And if there’s a backlog they could add resources to it. But this waiting period appears to be a standard, well-known thing.

So I think it’s #2 or #3.

It could be #3 and the company could claim #2, I’m aware. There’s a semi-plausible explanation at hand.

Describing RSS

One of the weirdly-missing pieces from NetNewsWire was always a description of what RSS actually is, written for people who aren’t developers. It’s bizarre that I skipped that part for so many years, but I did.

It wasn’t until NetNewsWire Lite 4 for Macintosh that I attempted it, and I liked how it turned out. It’s specific to NetNewsWire, but the general parts make sense for any reader.

The pitch is pretty obvious: RSS brings you the part you actually care about, minus all the headers and footers and ads and sidebar things. (Which is why NetNewsWire’s slogan was originally “More news, less junk. Faster.”)

The below is all copied verbatim from the NetNewsWire Lite 4 help book (that I’ll take down eventually):

* * *

What is RSS? What are feeds?

Lots of websites have news or updates of some kind.

They also have a bunch of other things — a header at the top of the page, and maybe links and ads and widgets on the left or right (or both). And then some more stuff at the bottom of the page.

Like this imaginary squished-down web page:

Website diagram that shows the good part — where RSS comes from

The good part is the part in the middle — that’s the part with the news. That’s the part that you read. That’s the part you’re interested in.

And that’s what RSS is — it’s just that part, minus the rest of the stuff.

Details

That “good part” is actually made available as a feed. A feed is just a specially-formatted text file that readers like NetNewsWire can read. The files look weird — they kind of look like the source behind web pages, with angle brackets and everything.

The important thing is: it’s NetNewsWire’s job to know how to read the feed. And it’s NetNewsWire’s job to show you what articles you haven’t read yet.

By doing this — by running NetNewsWire — you can let NetNewsWire find out when there’s something new. You don’t have to go to the websites and check to see if there’s something new. You can save time, and not have to rely on your memory.

Types of feeds

People often talk or write about RSS — but sometimes they mention Atom, too. Atom does the same thing as RSS.

If you see RSS or Atom, just know that NetNewsWire handles both, no problem.

Dave and Node

Dave Winer is becoming a Node.js developer:

Now I have a server on an Amazon EC2 Ubuntu micro instance. It’s running my fargoPublisher prototype. I have a pretty smooth deploy method with a folder shared between my desktop and the server, and the Macintosh Terminal program. I can upload a changed version of the software and reload the app in a few commands, a few seconds.

It’s cool that, after all these years, Dave and I are developing on the same platform again.

* * *

Were I looking to run a contracting business (I most emphatically am not), it occurs to me that there might be a business in being the server-person-for-hire for other Mac and iOS developers. Knowing the client side of development so well would give me an advantage over people who know the server side only.

Take that as a hint. There are other people like me who know both worlds — maybe that describes you — and there are plenty of iOS and Mac developers whose apps need online services. Could be a good business.

Transferring Domains - Day 7

Last night I noted that I couldn’t turn off private registration for ranchero.com — the option just didn’t appear. So I emailed support.

Support replied this morning: she told me I don’t have private registration for ranchero.com, so there would be no option to turn it off.

I replied with info from a whois query which clearly shows privatized information rather than the expected information. (For instance, the address is listed as Drums, PA, which is pretty far away from Seattle, WA.) Somehow ranchero.com’s info is private.

Could it be that because the domain is old (1997) it’s in some rare special-case category, and some code recognizes it as having private registration and other code — including the admin tools that customer support uses — doesn’t? And, if that’s the case, what will it take to fix it? And how long will that take?

Well, I’m being anxious without evidence. The answer is probably simpler. It may even just be a caching thing, and some patience would see it cleared up.

I note that I’m a week into this. Transferring two domains is a seemingly easy thing, and yet it’s as complex and time-consuming as I feared. My guess is that the transfers are a week away from being completely finished.

I’ll update this post if anything else happens today.

Update 10:45 am: I heard back from support just a few minutes after sending email. The issue was that private registration had been purchased using the technical contact ID rather than the primary ID.

So she turned off private registration, and it appears that whois queries are already returning the expected result.

I should be able to initiate the transfer of ranchero.com now.

In case anyone from Network Solutions is reading this: I won’t name the support person except by the initials S.H. (Since she’s not a public figure.) She deserves a gold star, a pat on the back, and a raise. She’s good.

Update 11:30 am: I initiated the transfer of ranchero.com to Hover. The Hover website says the ETA is February 2 (same as inessential.com).

The hard parts should be over — I don’t expect to have to communicate with Network Solutions support any more, though I will return to their site to see how much of my info I can delete. (The main thing to delete is any credit card info they may have saved.) (I won’t do this until after the transfer is complete.)

I’ll also have to make sure the settings for DNS servers migrate to Hover. (My domains use Dreamhost’s DNS servers.)

So I’m just waiting now.

Transferring Domains - Day 6

I heard back from Network Solutions support this morning, so I was able to login to the primary account for ranchero.com and request a transfer authorization code.

I now have two codes pending, one for each domain.

I wrote back to to the support person, thanked her for her help, and also asked if there’s any way to speed up the code generation so I don’t have to keep waiting.

She replied a few minutes later that she would try to get me the codes sooner.

I’ll update this post if anything else happens today.

Update 1:30 pm: The support person wrote back: the two codes have been emailed. I don’t have them yet, but I assume I will soon. Also: she removed the Security Transfer Locks that were automatically placed on the domains as a result of my making several changes at once.

Update 6:00 pm: Support emailed me the transfer codes.

I initiated a transfer of inessential.com. I went through the directions at Hover. It entailed what you’d expect: creating an account, making sure contact info is correct, paying ($10) with a credit card, pasting-in the transfer code. (I believe I get an additional free year with that $10, which is cool.) Easy stuff.

I also approved the transfer on the Network Solutions site. Hover helpfully provides an ETA for the transfer to be complete: February 2.

I couldn’t initiate the transfer of ranchero.com, because I couldn’t turn off private registration. The option just doesn’t appear for some reason, even though I’m logged in with the primary user ID.

So I sent another email to Network Solutions support — hopefully the last one. I expect to hear back tomorrow morning, and I should be able to initiate the ranchero.com transfer then.

My one worry is that my domain name server settings won’t transfer. (They point to Dreamhost’s DNS servers.) Hopefully I’ll be pleasantly surprised that they transfer automatically.

PS Last week a number of people asked me why I hadn’t transferred my domains away from Network Solutions just because they cost more. (Setting aside everything else.) This saga is the answer: the difference in cost is nothing compared to the cost in my time to do things like transfer domains.

I’m no fan of these kinds of tasks. While they can be necessary, and they can feel like progress, they’re not the same as making things.

PPS Moisés Chiullan:

The first guest on “Thank You For Calling!” will be domain registry trauma victim @brentsimmons.

I think this will be some time next week.

Transferring Domains - Day 3

I went back to the Network Solutions site this evening to request a transfer code for inessential.com.

(It looks like ranchero.com is on a separate account. I don’t know why I did this — it was probably not intentional. But I’m confident Network Solutions support can help me figure this out.)

I’m following the instructions provided by Hover, and I got as far as requesting a transfer authorization code. Here’s where the process stops for a few days. Network Solutions’ site says:

Your request for an Auth Code has been received and your information will be validated to ensure the security of your account. If your request is approved, you will receive your Auth Code by email in 3 days.

It’s Friday night. Hopefully this means I’ll get the code on Monday, though I can see that three days might mean three business days, in which case the code could arrive as late as Thursday.

I could wait, but I’d sure like to just get this all finished. I’ll email Network Solutions support and see if the code can be emailed to me sooner. (That might still mean Monday.)

Transferring Domains - Day 2

(I’ll add to the end of this post as things happen.)

Call from Network Solutions

I got a call from a support person at Network Solutions just as I opened the office this morning. (At 10 am Pacific. I’m not a morning person.)

I hadn’t contacted Network Solutions support, but I imagine someone there read my blog and asked support to contact me.

The support person was very nice and patient as I booted my computers. The problem, which she quickly recognized, was that I wasn’t logged-in with the primary user ID. I didn’t know how to login with the primary user ID, so she helped me with that.

(I set up these accounts so long ago that I didn’t still have login info.)

I verified that I would be able to take the next steps in transferring my domain. I thanked her. She told me to contact her if I ran into further problems, and she followed up with an email right after the call.

It was a very good customer support experience — I can’t see how it could have been better. Top marks.

Email from Hover

I had emailed Hover support last night. Once I got off the phone with Network Solutions I checked my email and there was a reply from Hover.

The Hover help person asked if I prefer email or talking on the phone (email, for me, is best), and she suggested that I might not be logged in with the right account. She offered to login with my credentials and get it straightened out.

Which is also very good support — I can’t see how Hover’s initial reply could have been better.

So: everyone’s being awesome today, and it’s not even lunch time. (And the sun is shining in Seattle. Good day.)

I replied to Hover that I think I can take it from here, since I got help from Network Solutions, but I’ll ask for help if I need to.

I realized that I could ask for Hover’s free Valet transfer service. Definitely a cool thing. But at this point I’m too curious about the process and I want to do it myself.

Transferring Domains - Day 1

I suspect this is going to be a saga.

I started by going to Hover to see if they had instructions for transferring from Network Solutions. They do.

The first section has me disabling domain privacy on the Network Solutions site. I got as far as step #4, where I would click on Turn Private Registration Off.

But, of course, that link doesn’t appear.

Were this a normal situation, I’d email Network Solutions for help. But I don’t expect that to get me anywhere, so I emailed Hover for help instead.

Since it’s after 8 pm Eastern, Hover’s help people aren’t at work (understandably), which means I’ll have to wait until tomorrow.

Network Solutions - The Resolution

Domain Name Wire reports that the WebLock program will be opt-in rather than opt-out. The report also notes that the email was sent to 49 customers.

Phone Call

I got a phone call from Network Solutions, where they acknowledged that the wording of the email wasn’t good. They’ve had meetings about the wording of that email, the caller said.

I said that I didn’t want the feature. So the person who called me had a quick script to go through where I had to acknowledge that I understood what I was declining. The phone call took about two minutes in all.

My Next Step

I’ll be transferring my domain names. Probably to Hover.

Over the past 24 hours I’ve had lots of registrars recommended to me. The upshot seems to be this: they’re all good except for GoDaddy. People recommend Namecheap, PairNIC, Gandi.net, Dreamhost, and Dynadot.

Which doesn’t give me a clear answer — until I take into account Hover’s long-time support of the podcast community. (I’m a listener and a podcaster. No, they haven’t advertised with me, and I haven’t asked them to.)

Questions

People have asked me a few questions (or had misconceptions):

Do I host my sites at Network Solutions?

No. They’re at DreamHost. (I’ve been there for about 10 years and they’ve been great. This site is fast. Of course, it doesn’t hurt that it’s a statically-rendered site.)

The name servers are also at DreamHost.

Which domains were involved?

ranchero.com and inessential.com (this blog). The email didn’t specify which domain would be getting the WebLock program. It could be both. I don’t know.

What kind of traffic do I have that would get me noticed by Network Solutions?

Domain Name Wire reported yesterday that this service was going to “approximately 1 percent of Web.com’s customers.”

I have no idea how Network Solutions would know how much traffic I get.

My stats app Analog tells me that inessential.com had 2,270,357 requests for pages in December 2013, which was a typical month. I don’t know if this counts RSS feed requests. Presumably it doesn’t count images and style sheets and similar.

(I’m sure I sound terribly old-school by now: Network Solutions, DreamHost, and Analog. But that’s just because I haven’t felt a need to make changes. Until now.)

Was I unaware that Network Solutions indulged in less-than-stellar practices?

I was not unaware. I stopped registering new domains there in 1999. But I hadn’t felt it necessary to transfer my domains. (Not least because my time is best-spent writing code.)

The Internet Machine

So what happens when something so obviously inflammatory is posted?

My initial tweet was retweeted 293 times and favorited 47 times.

My blog post had the top spot on Hacker News for hours yesterday. It also appeared on Slashdot and on Reddit’s Technology page.

This blog got 2.8 times its normal traffic. (I don’t have ads. And I’d way rather people came here to read about something cool or something I made.)

I spent some time reading comments. My favorite — because I’m a software developer — was this one: “I was really pleased with the instantaneous load of this blog.”

Lex-Sized Hole

Because Lex Friedman went to work at The Mid Roll, there’s a hole in the market the size of Lex’s old company Podlexing.

The Mid Roll works with popular and established podcasts, while Podlexing worked with smaller and newer podcasts.

It’s a business opportunity. Not for me — but I hope somebody picks this up.

I asked Lex if he minded if I blogged about this. He not only said he didn’t mind, he also added some advice for anybody who might run with this. He wrote:

The small shows should roll up together. Selling them one off doesn’t make sense, and you’re blind to pricing, and it’s hard to figure out where to price yourself vs. everyone else. Are you overcharging? Are you undercharging? Ack!

My advice is that someone should do The Syndicate for podcasts. Roll up small shows, and charge on a CPM model. (Small-reach tech shows should think $20 for pre-rolls that are shorter, and $30 for mid-rolls that are longer.) Insist that all shows measure downloads in the same way (SoundCloud?), roll-up the rates accordingly, and take a 20% cut. Pay shows on a percentage basis according to their downloads.

And feel free, unknown podcast entrepreneur, to contact me for advice.

Lex knows this business and is willing to provide advice. Go.

Network Solutions Auto-Enroll: $1,850

I got an email from Network Solutions — where I still have two domains, originally registered in the ’90s — that informed me I have been enrolled in their WebLock Program.

To help recapture the costs of maintaining this extra level of security for your account, your credit card will be billed $1,850 for the first year of service on the date your program goes live. After that you will be billed $1,350 on every subsequent year from that date. If you wish to opt out of this program you may do so by calling us at 1-888-642-0265.

(Here’s a screenshot of the email. I’ve pasted in the text at the end of this post.)

I couldn’t believe that I’d been opted-in, without my permission, to any new product — and I was stunned when I saw how much it cost. And further surprised when I saw that I would have to make a phone call to deal with all this.

I found on Twitter that Network Solutions has an account. So I asked if this was phishing. The reply: it’s real.

My next step was, of course, to post a screen shot of the email on Twitter.

@netsolcares responded by suggesting I call the security team.

@brentsimmons Give the security team a call and they can explain 1-888-642-0265 Sorry for the inconvenience. ^rr

I’m not going to call the security team. (Which I’d bet is really a sales team.) I’ve been a customer of Network Solutions since 1997. While their website was always kind of a pain, I’ve never had problems with them.

But this goes way beyond acceptable behavior for any company I do business with. It’s extreme.

So I’ll be transferring those domains elsewhere. (Folks have recommended Hover and Dynadot.)

Text of the email

Dear Brent Simmons,

Cybercriminals continue to strengthen and evolve the techniques and tools they use to assault our customers’ websites and domain names. According to the Symantec Internet Security Annual report the pace and frequency of hacking, phishing and social engineering has increased over 42% in 2013.

Compromised domain names can lead to substantial brand, reputational and financial damage. Once a domain name is compromised cybercriminals have total control of the content that appears on “your” website. In many cases objectionable content is posted or phishing sites are established whereby your customers’ private information can be exploited.

At Network Solutions we take your security very seriously. We deploy some of the most advanced security monitoring and defense mechanisms in the industry to ensure only authorized users can access your company’s domain name and name servers. Given the level of traffic to your website, we are taking another significant step to protect your domain name security.

Starting 9:00 AM EST on 2/4/2014 all of your domains will be protected via our WebLock Program. Here is how the program works:

  • In order to make changes to your Domain Name’s configuration settings you must be pre-registered as a Certified User.
  • All requests for Domain Name configuration changes must be confirmed by an outbound call we make to a pre-registered authorized phone number you establish. A unique 9 digit PIN will be required when we call.
  • A message alert will be sent to all Certified Users notifying the team which Certified User has made the request.
  • In addition WebLock enrolled customers will have access to a 24/7 NOC and rapid response team in the event of any security issues.

To establish Certified Users and pre-register authorized phone numbers and email addresses please call 1-888-642-0265 Monday to Friday between 8:00AM and 5:00PM EST. Please make sure to establish Certified Users with authorized phone numbers and email addresses before launch date. Once established, the unique 9-digit PINs for each certified user will be mailed to you within 45-days.

To help recapture the costs of maintaining this extra level of security for your account, your credit card will be billed $1,850 for the first year of service on the date your program goes live. After that you will be billed $1,350 on every subsequent year from that date. If you wish to opt out of this program you may do so by calling us at 1-888-642-0265.

We strongly encourage you to take advantage of this security program and register Certified Users before the program launch date. Thank you for helping us protect you better.

Regards
Geof Birchall

Geof Birchall
Chief Security Officer
Network Solutions

Connect With Us

Please do not reply to this email. Replying to this email will not secure your services. Please click here to unsubscribe. Please note that unsubscribing from our marketing emails will not affect important transactional correspondence such as administrative and renewal notices related to your account. Please review our Privacy Notice for any questions related thereto and please see our Services Agreement for the terms and conditions governing Network Solutions products and services.

©2014 by Network Solutions, LLC. All rights reserved.
12808 Gran Bay Parkway, West | Jacksonville, FL 32258
Network Solutions is a Web.com Group, Inc. company.

Manton’s New App

Check out Sunlit:

Sunlit isn’t for all of your photos. Just the best ones. It’s for the photos that tell a story.

Looks good. Cool idea. (And it’s from Manton Reece, so you can assume quality.)

The Record, the Numbers

Chris and I can’t think of any reason not to share download numbers for The Record.

Episode #1 was released just over a week ago, Friday Jan. 3 at 3 pm. The podcast appeared in iTunes Tuesday Jan. 7.

(The following numbers are all as of this writing, of course.)

Downloads of the audio file so far: 5,355.

Our best day is today. Our second-best day was yesterday. Our third-best day was last Friday.

Earlier today it peaked as the #2 top Tech podcast, and reached #17 in all podcasts. (In iTunes. It’s down a little from then.)

Comparing to other podcasts

Mule Radio Syndicate posts download numbers for their podcasts, so we do have something to compare to. (They have a bunch of great shows, by the way.)

My goal for The Record was to land in respectable territory.

The Big Web Show’s Dec. 19 episode has 6,777 downloads.

Let’s Make Mistakes Dec. 18 episode has 5,808 downloads.

So we’re in the same range as podcasts I admire. Good. (That is, if those numbers are actual download numbers. I assume they are, but I don’t know for sure. It’s conceivable that they’re just in-browser plays, though it’s hard to imagine that many people playing podcasts in their browser.)

Nevertheless, looking at The Talk Show’s Dec. 24 episode provides some perspective: 66,470 downloads.

Welp. That gives me a goal.

Update 6 p.m.: Daniel Jalkut says that Core Intuition gets about 10,000 downloads.

Tim on Software

Tim Bray, Software in 2014:

And I totally fucking hate having four independently-scrollable areas on the screen controlled by weird-looking JavaScript-genius-handcrafted scrollbars. And then I’ll be working with some fancy single-page app, accidentally hit the tab key and everything goes a little sideways.

The First Go

Andy Finnell’s A Postmortem of Failed Products interested me. (Via Michael Tsai.)

It reminded me of my first go at being an indie developer.

I started in 1995. I wasn’t much of a programmer, and I had zero experience designing, shipping, promoting, and selling apps. I had some indie heroes at the time — Rich Siegel, Dave Winer, Chuck Shotton, Peter Lewis, Mark Aldritt, Jim Matthews, John Norstad — and I wanted to do what they were doing. Very badly.

I was working as a secretary at a manufacturer’s representative and I was in love with the web. I quit my job.

(The company — about a dozen people, mostly in the Portland branch — sold things like toothpaste, gift wrapping, hairbrushes, and so on to drug stores. Luckily I’ve forgotten everything I knew about the business, including the brand names. Most of my job was sending faxes. We had computers but no email.)

The apps I wrote all worked with WebSTAR (the Mac HTTP server). I shipped three: SpotLight, DenyAgent, and something. I forget what the third one was called.

Total revenue: $990

SpotLight cost $99 and I sold 10 copies. The other apps sold zero copies. Zeeeeeeeero.

Since those days I’ve never stopped shipping software.

What I Learned

I learned from that first go in the mid ’90s that I was a shipper, and nothing I’ve learned since has been more important. It’s the one necessary trait of an indie developer. For me it was like a fish being introduced to water — so this is what it’s like to breathe.

My apps were no good at all and I had no idea how to make money. None of that mattered.

From reading Andy Finnell’s piece it sounded like he did better on his first go than I did. And, most importantly, he’s learned that he’s a shipper. He can’t stop.

What I did next was to go work for UserLand Software (Dave Winer’s company), and I helped shipped a lot of software in those next six years, and I learned about the industry, about software, about how to treat people, about what works and doesn’t work. The experience I gained there is still paying off, and it’s what allowed my second go at being indie in the early ’00s — when I shipped NetNewsWire and MarsEdit — to be successful.

Note to Andy, and everyone else in a similar spot: take heart. You’re a shipper. Keep learning and trying and everything else will follow.

UITextView - The Solution

Before posting I’d been all over Apple’s developer forums and Stack Overflow, and I’d emailed with people who had appeared to solve my UITextView problem in their apps.

Nothing worked — or, rather, a bunch of things worked somewhat, but they didn’t solve my problem entirely.

So I went through all the help I got on Twitter and tried different things. The only things that worked reliably were the solutions that involved adding a delay before scrolling.

The delay appears to allow UITextView to catch up to reality, to complete pending calculations.

You can download my solution. (Super-small project.)

This Is a Hack

Nobody (I hope) feels comfortable working around a bug this way. Almost every time you’re performing code after a delay you know something’s going wrong, and you’re just guessing and hoping that it works.

But here’s the thing: something has gone wrong and I am just guessing and hoping it works.

Given that it’s a hack, I wanted to use the least amount of code possible.

I ended up adapting Tanmay’s solution. (I haven’t downloaded his app Write yet, but it looks pretty cool based on the website. Thanks, Tanmay.)

How it works

In shouldChangeTextInRange it checks to see if the text is equal to @"\n" or @"". If it is, it calls scrollToShowSelection after a delay of 0.1.

And then scrollToShowSelection checks to see if the selection is at the end of the text. If it is, it sets the contentOffset (animated).

That’s it. Pretty simple. And it’s a minimal amount of code, which means it will be easy to rip out once the bug is fixed in iOS. (Or, rather, I’ll leave the code in but have it run only on older versions of iOS. And rip it out eventually.)

It Really Is a Hack

So this is an opportunity to talk about when to use hacks like this. The short answer is never. I hate doing things like this and I can go years in between.

But the important thing is the quality of the user experience. Nothing else matters.

It’s up to me to do this in the smartest way possible — and to test to make sure it’s solid, and to pay attention to iOS updates to make sure it still works, and to make the code not run at the earliest date possible, once the bug is fixed.

Until that day, sleep will be a little more toss-and-turn-ier than normal. (Obligatory: this is why Daddy drinks.)

PS If I saw this in your code, I’d tell you that you’re screwing up. It’s quite okay if you say that to me.

PPS Doug reminds me to cancel previous performs. He’s right.

UITextView Scroll-to-Typing Bug

As I’ve said many times, I’m a huge fan of Text Kit. It’s a big deal for Vesper. Among other things, it lets us do bolding/un-bolding in a way that didn’t work reliably or efficiently in iOS 6.

But with Text Kit came a new UITextView. The old one was based on WebView, and this one isn’t. That makes it a 1.0 version of UITextView, since it’s a new thing. And it has some bugs. (Not surprisingly for a 1.0.)

I’ve been trying to figure out work-arounds for these. I’m making progress.

Set the frame, not the contentInset

People Who Know(tm) (Greg Pierce, for one) have advised me not to set the contentInset of the UITextView when the keyboard appears and disappears. Instead change the frame. In my testing this makes a big difference.

It means you don’t get the blurred-out UITextView underneath the keyboard, which is too bad, but that trade-off is easy to live with.

Scrolling to show typing

I have this almost working. Like a bottle of wine I just can’t manage to un-cork.

From Greg Pierce (again), author of Drafts, I have this code:

- (void)textViewDid​ChangeSelection:​(UITextView *)textView {
 
  [textView layoutIfNeeded];

  CGRect caretRect = [textView caretRectForPosition:​textView.selectedTextRange.end];
  NSLog(@"y %f", caretRect.origin.y);
  caretRect.size.height += textView.textContainerInset.bottom;
 
  [textView scrollRectToVisible:caretRect animated:NO];
}

You can download a super-simple sample project with this code.

The one place it fails:

  1. Tap at the end of the text.
  2. Tap Return.

The caret is hidden. Type any other key and it un-hides. But I really, really want the caret to be not hidden right then.

If you look in the console you’ll note that caretRect.origin.y is just plain incorrect when you tap Return.

You can tap Return again and then backspace and see the same thing — only caretRect.origin.y will be wrong in a different direction.

So close. I can almost taste the wine. If you have any ideas, please let me know. I’ve tried a bunch of things and I’m willing to try more.

My Letterpress rules

I have just two:

When I win, I pass my first turn on the rematch. It gives my opponent a chance to go first, since there’s an advantage to going first in Letterpress.

I try hard to avoid doing a prefix or suffix variation of my opponent’s last word. Sometimes it’s the best possible play and I do it anyway. But in general I try not to.

Xcoders: Ken Case and John Chaffee

It should be a good one. The next meeting is this Thursday.

Ken Case from the Omni Group will talk about the challenge of providing upgrade discounts through the App Store: why upgrade discounts are important, why the traditional approach to upgrade pricing doesn’t work in the App Store, and how Omni is providing discounted upgrades in their latest app release.

John Chaffee from BusyMac will present tips and tricks for distributing apps on the Mac App Store including sandboxing, Mac App Store receipts, in-app update notifications, pricing, volume licenses, upgrades, affiliate revenue, and the controversial Rate This App dialog.

My Feeds

I wish there were an OPML sharing service. There isn’t. (That I know of.) In the absence of that, just for jazz, here are my feeds. (The feeds I personally subscribe to, that is. You may need to right-click and download to disk.)

Introducing The Record - Season One, Episode One

The Record, a new podcast, brings you the stories you should know about the Mac and Cocoa development community. Chris Parrish and I are the hosts and producers.

In case you don’t know Chris: Chris and Guy English are Aged & Distilled. They make Napkin. Chris used to be at Rogue Sheep, where he worked on (among other things) the Apple-Design-Award-winning Postage.

How The Record Got Started

Here’s where I was lucky: I went to college in Olympia in the ’80s when Nirvana was playing dorm parties. In those days there was no tradition of Olympia bands, or even Seattle bands, making it big. (Heart and Jimi Hendrix aside.)

At the time I didn’t think anything special was happening. Nirvana didn’t stand out for me — they weren’t any better (yet) than a bunch of other bands.

And then — extreme fast-forward — a couple years ago I went to the Nirvana exhibit at the Experience Music Project. There I saw a playbill that listed a band that included two of my roommates. There were photos of people and places I knew. And the various artifacts — stickered-up guitar cases, handwritten mix tape inserts, all these mundane things — had been transformed, under the museum’s lights, into a history worthy of attention.

The exhibit was about a band, but it was also about a time and a place — a time and place that I remember.

I started to think about everything that had been missed. Shows that weren’t taped. Letters gone missing. Stories forgotten.

Our Community

I’d been thinking about this podcast since before seeing that exhibit, but seeing the Nirvana exhibit pushed me into deciding to do it.

Our community reminds me a little of the early Seattle music scene, and more than a little of the early days of television. Apps are still a new medium, and these are the early days. It’s my theory that future people will want to be able to look back at what we’re doing today.

We already have Folklore.org for early Macintosh stories. And we have the Computer History Museum in Mountain View. So there is some precedent for the idea that we’re creating a history worth remembering.

I’m concentrating on the part that I know about: the Mac and Cocoa development community. (I leave it to other people to cover other communities.)

So I finally started talking about the idea — after Xcoders meetings, at the Cyclops, naturally — and Chris agreed to produce it with me. Perfect.

We started recording in the spring of 2013.

Since we’re still in the thick of things, maybe we’re in time to capture the stories worth remembering. Many of them, anyway.

Seasons and Themes

The first season, Seattle before the iPhone, will be nine episodes. We’ve already started recording the second season.

We’re not limited to Seattle, but we’re starting there, because that’s where we live and we have a great community here.

We’re not being totally strict. At least one of our guests lives here now but didn’t live here then. Another lives here part time. Not every guest is a programmer, because we’re interested in the wider community.

And we’re taking care to record people you haven’t heard from before. There will be some veteran podcasters, but most won’t be. (The most talkative among us don’t have a monopoly on stories.)

Finally, all of our episodes so far have been recorded in person. We think they turn out better that way. We may not be able to keep it up indefinitely, but we’ll record in person as often as we can.

Thanks

Thanks to the Omni Group for providing recording space for eight of the first nine episodes. And for feeding us!

Thanks go to Chris for doing the hard work of recording and editing. I get to just assume it will sound good, and Chris actually makes it sound good. No small job.

And special thanks go, of course, to all of our guests. The first one is Luke Adamson — who you may not know, but you should. (Wait till you hear how he funded his first NeXT box.) Go listen.

Vesper Sync Diary #7 - Audibles

I described the plan in earlier sync diaries. And then I started writing code.

You know how it goes: things look one way when you’re in the huddle, and quite another way at the line of scrimmage.

Attachment Metadata

(Attachment metadata is unique ID, size in bytes, MIME type, and height and width.)

To recap: the sync code supports multiple attachments per note, whether we ever use that feature or not.

So, unsurprisingly, I decided that there should be a database table for attachment metadata (on both client and server), and each note would have a to-many relationship to its attachments. (The inverse relationship is to-one: an attachment belongs to a single note).

That’s how you’d do it; that’s the right way to do it.

But there’s a cost to this approach. Either:

Notes and attachment metadata are synced separately, which means that a client could have an incomplete object graph (it might have a note minus its attachment metadata).

Or…

Notes and attachment metadata are synced at the same time, but the server code is more complex and includes more database hits than I would like.

Incomplete object graphs are a major pain to deal with and they make for a bad user experience. So I ruled out the first option.

I didn’t like the second option either, for two reasons:

  1. It’s very important to make the sync code as simple as possible, so that bugs have nowhere to hide. (Syncing is difficult, so I’ve adopted an extreme committment to simplicity.)

  2. It’s very important to make syncing as fast and efficient as possible, so that the app provides the best possible user experience.

So I decided to do what is arguably the wrong thing, but is the right thing in this context.

What I Did

Database people are already gasping for air, because they know what’s coming. Instead of creating a separate table for attachment metadata, I created an attachments column in the notes table and just encoded the attachment metadata there.

On iOS it uses Core Data’s built-in object archiving feature. On the server it’s stored as JSON.

This is wrong, surely; it’s not how to do this. Except, in this case, it is. Incomplete object graphs are wrong; inefficient and slower syncing with more complex server-side code is also wrong.

This is less wrong than the alternatives.

With this change, a note always has its attachment metadata. Fetching notes always includes that data, on both client and server. They’re inseparable. And it means just one database hit to fetch a set of notes.

Some of you are gasping for air anyway. I know.

What I Gave Up

With this configuration it’s more difficult to do a query against attachment metadata. Not impossible, but more difficult, and it would probably involve some filtering in code. That’s not great.

But the app doesn’t make any queries like that, and we don’t have any features on the horizon that need that.

Still, I could have insisted on planning for that contingency. After all, I’m already planning for the possibility of multiple attachments per note. What makes one contingency different from another?

I look at it this way: supporting multiple attachments is a more obvious feature than some unknown feature that requires queries against attachment metadata. I don’t even know what that feature would be. And if it hasn’t come up in the first six months, there’s an excellent chance it would never come up.

Or, put another way: is planning for that remote contingency worth degrading user experience? Is my notion of database-correctness more important than simpler code and fast and efficient syncing?

Nope.

But what if it does come up some day? Well, it’s just software, and I’ll make it work by doing the smartest things I can think of. Like always.

Making Things

Rands on The Builder’s High:

Is there a Facebook update that compares to building a thing? No, but I’d argue that 82 Facebook updates, 312 tweets, and all those delicious Instagram updates are giving you the same chemical impression that you’ve accomplished something of value. Whether it’s all the consumption or the sense of feeling busy, these micro-highs will never equal the high when you’ve actually built.