I got to play a few songs as a Conditional Breakpoint! It was a total thrill for me. Check out the Breakpoints album on iTunes if you haven’t already.
Sometimes days are like this:
Our testers — who are great — report a regression I caused but that I didn’t notice. Why is sub-pixel anti-aliasing not working in this view? The text looks bad. (Note to self: test with a non-retina display before comitting.)
I investigate, and find, to nobody’s surprise, that the culprit is a layer-backed ancestor scroll view. I turn off layer-backing — I just uncheck that particular box.
Then run the app. It’s good to see sub-pixel anti-aliasing back. But look at how things have gone wonky.
Wonky? Let’s be precise: the layout inside outline view cells is incorrect. If I check the box (turn layer-backing back on), then layout is fixed. Uncheck it, and layout is broken.
(This all sounds straightforward, but I’m glossing over a bunch of things I tried and researched. The above is a couple hours of work.)
The wonky view uses auto layout, but it’s not entirely constraint-driven: there’s a manual
-layout method. When an ancestor is layer-backed, then that method is called at the appropriate times. When it’s not, then that method isn’t called often enough, or not at all the right times.
Or… but it also looks like something else might be moving those views, giving them a zero origin when it shouldn’t be. Exactly as if it’s doing constraint-based layout and not calling the
-layout method. Sometimes.
I click around a while, add NSLogs and breakpoints and all the usual things. I can’t figure out what’s happening. I bring in
resizeSubviewsWithOldSize: (the old friend). I accidentally introduce an infinite loop at one point.
To reassure myself, I check that checkbox again (turning on layer-backing) — and layout works again as expected.
Time to get pragmatic.
If it seems as if those views are sometimes getting laid-out by their constraints, and
-layout isn’t getting called, then maybe that’s really what’s happening. So one possible solution is to give all the views their necessary constraints, so that
-layout isn’t needed at all.
I tried it. Success! (I think. At least so far.)
And that was a day of work. In the end I don’t know why there was a problem, but I have a solution. I should probably file a Radar, but it seems like exactly the kind of thing that will be hard to duplicate in a simple case (though I could be wrong).
There’s nothing wrong with days like that. In the end the thing is solvable. What worries me is when I have too many days like that strung together, when I have too many Radars to file.
I’m still the newest person here. Make that not true anymore.
For one of my projects I’m working with NSVisualEffectView and behind-window blending.
I’ve found a few things that could help people doing the same thing:
Reminder: don’t forget that its subview should respond YES to
If it’s in an NSSplitView, make sure the NSSplitView is not layer-backed. rdar://18585148
Make sure the effect view’s superview is not the first layer-backed view. rdar://18587102
There may be other gotchas, of course, but these are what I’ve found so far.
On Twitter, Martin Johnson asks:
How long until a crit mass of users get burnt one to many times and simply avoid indie products altogether?
I don’t think people outside our industry use the word “indie” to describe any software developers. They may think “probably small” or “never heard of them” or “not Apple or Google or Microsoft” when they think at all about a company.
I don’t think that product failure is a problem specific to indies. VC-backed apps and companies fail all the time. Large services fail too — you can’t dial in to America OnLine any more. Google has turned off so many services that there’s a Google Graveyard. Apple has retired lots of things too.
The beauty of indie software is that many apps don’t make financial sense for a larger company, but they make great sense for a small shop. So you can have sustainable apps such as Capo, Acorn, and MarsEdit that you wouldn’t get without indies. And you can also be sure those apps won’t get shut down on some manager’s whim.
Going with indie software can be safer than the alternatives.
But relying on any software or service, from anybody, is a risk. Always. The best way to minimize that risk is to pay money, because it’s money that keeps things going.
Justin Williams on Glassboard closing at the end of this month:
Over the last year we have tried a variety of different methods of converting Glassboard into a sustainable business. The reality is that we failed to do that.
I have some idea of what he went through — before it was Justin’s, Glassboard was Sepia Labs’s product. That was a team of six, including me, so I know the challenges of turning Glassboard into a business. We at Sepia Labs couldn’t do it, but we all hoped Justin would be able to.
Glassboard, or something just like it, is so needed. An app where you can communicate with persistent groups of people, where you control who’s in a group — and do so privately (for real) and with no ads — seems like it should be a basic service. Something everybody would use.
But since it’s social it needs to be free to get people on board, because it’s not useful without people.
But then how do you make enough money? I don’t know.
It’s easy to look at this as part of the indie-life-is-tough story. And certainly conditions are tougher right now than I’ve ever seen. But an app like Glassboard — with the social network app’s dilemma — is going to be a challenge no matter what.
* * *
I’m proud of the work we at Sepia Labs did, and I’m proud of Justin for all his great work and all the energy he put into this. I thought he had a real shot at turning this into a business, but I suspect I underestimated the difficulty.
At any rate: I want to say thank you to my co-workers at Sepia Labs — Walker, Brian, Jenny, Nick Harris, and Nick Bradbury — and also to Justin for taking this on and working so hard at it, and to all the people who used Glassboard. Thank you so much.
You can download the test case.
Launch using the iPhone 6+ simulator.
Rotate to landscape.
Tap the Show Popover button.
Rotate to portrait.
Note the message in the console, which will be something like: “Unbalanced calls to begin/end appearance transitions for <UITableViewController: 0x7fbb02346170>.”
As bugs go, a message isn’t a serious thing. But it could be indicative of a more serious bug, and so it’s worth reporting.
* * *
There’s very little code in the test case. The action is in TableViewController.m, which presents a view controller as a popover with an adaptive presentation style (full-screen).
I have a folder at
~/Projects/Bugs/ where I create test cases that get attached to Radars.
It’s a good practice. Assume you’ll have to do this sometimes, and assume you’ll want to keep those test cases. (You’ll want to keep them so you have an easy way to find out if they’ve been fixed in later releases.)
Sometimes in the process of creating a test case I find out it’s my bug. Sometimes. Either way, it’s a good exercise, because at least I find out one way or another.
(I’m procrastinating writing a test case right now. Hence the blog post.)
In the old days, programmers spent hours and days and weeks working very hard, and sometimes brilliantly, on difficult things that no one had ever done before.
These days, programmers spend hours and days and weeks working very hard, and usually unsatisfactorily, on getting around bugs in their platform.
Most SDKs are just capturing and streaming data — and what’s being collected and streamed is usually redundant.
Furthermore, the challenges of the app business extend beyond just sending data to an analytics partner or two. You also need to invest in user acquisition and in tools such as push notification and email to keep users engaged (which also require SDKs).
With mParticle, app developers can solve both sides of the equation using a single, lightweight SDK. App developers can not only stream data to any service such as analytics, push, crash, and so on, they can also segment and send data to Facebook, Twitter, Mailchimp, and similar to increase engagement and retention.
- Less time integrating. More time innovating.
- Eliminate SDK updates and code changes required.
- Reduce costs paid to reporting services through data filters.
- Improve app stability, security, and user privacy.
Sign up free today. No credit card required.
1995 was the year the internet went mainstream. That’s the year when it seemed like everybody got email accounts and web browsers.
It was funny watching TV back then, because the announcers always said "aitch tea tea pea colon forward-slash forward-slash double-you double-you double-you period…” (These days you just get a hashtag. One day we’ll look back on that and laugh.)
In 1995 I was 27 years old. Nobody had ever tried to scam me (at least, not that I noticed). Here’s the thing: though TV and movies made it seem otherwise, most people didn’t run into actual con men. Cons were rare.
And now, by my estimation, people have tried to scam me 693,500 times via email. (Assume an average of 100 scams a day for the last 19 years. These days it’s closer to 200 a day.)
Grifters used to have to work hard for a living. I miss that.
* * *
The immorality that inflames me is when people prey on vulnerable people.
“Vulnerable” could mean desperate, overly-trusting, poorly educated, forgetful, less-abled physically, less-privileged, less-well-connected, and so on.
And it’s my extreme good fortune to be less vulnerable than most everybody else on the planet in the history of the world.
But I know two things: that position could change on any very bad day, and that position will change in the future. (The problems of aging get to everybody lucky enough to make it that far.)
Knowing that one day I will be more vulnerable to predators than I am now doesn’t make me any more sympathetic to the people who are already more vulnerable than I am. I’m very sympathetic.
But it’s not a bad reminder, either. Sometimes I look at a piece of email and wonder how I’ll figure out if it’s really my bank when I’m 80 years old. And I’m not sure I’ll succeed 100% of the time, and it really needs to be 100% of the time.
Which reminds me that there are people all over having a hell of a time right now. Today.
Cartography is a Swift project on GitHub that gives you the ability to “set up your Auto Layout constraints declaratively and without any stringly typing.”
Dave Winer, Are the silos winning?:
People get all comfy and bored in their little nests, and then boom, everyone goes somewhere else. If it’s yet another boring and nesty silo, only a few people will go there. But if it’s open, eventually, everyone is there.
Just ask America OnLine.
Feedback about blog engines was mixed.
And Santiago Valdarrama suggested I should stick with my current homegrown blog engine.
The Requirements, again
I could rule out almost all of these right away.
Many of these suggestions would just replace what I have today — but with less functionality. My current system at least works with MarsEdit running locally, but many of these don’t. MarsEdit (MetaWeblog API support) is not optional.
I wanted something that runs on a server that allows me to post from an iPhone and iPad when I’m away from home. Ideally there would be a native app with a sharing extension, but I could be flexible on that.
WordPress was the obvious best fit. (Works with MarsEdit and has a native app.)
The Work Involved
WordPress deserves top billing in a hypothetical web app hall of fame. It’s a remarkable achievement, and I have nothing but respect for the good folks at Automattic.
But I started thinking about importing my blog into WordPress and making sure the content and the URLs all remained the same. I thought about editing a theme to get it to match the current look of the site. And it started to seem like work, and not the kind of work that’s much fun (to me).
So I went back to thinking about what I have now. Which is:
- A static blog generation system written in Ruby. It’s fast and bug-free.
- A CGI script that implements the MetaWeblog API, so that the blog generator works with MarsEdit.
What separates this system from the system that I want? Two things: it doesn’t run on a server, and there’s no app or browser-based UI for posting from iOS.
The first one is fairly easily solved: I could put it on a server. The CGI script, perhaps converted to a Sinatra app, would run on some port other than 80, while Nginx serves the static pages that the system generates. I’d also have to deal with Mercurial — the copy of the blog on the server would have to be the parent repository. None of this is difficult, and it feels like less work than moving to WordPress.
That leaves the issue of posting from iOS. I could do a browser-based UI, or — here’s where this starts sounding fun — I could write an iOS app just for me.
So that’s what I’ll do: I’ll write an iOS app with an audience of one.
It will give me the chance to work with some technology where I need practice: auto layout and size classes, adaptive UI, storyboards, Core Data, sharing extensions, and Swift.
And then I’ll be able to post from anywhere, any time, which is exactly what I want.
PS I mentioned that my static blog generator is fast. It takes about 10 seconds on my MacBook Air to generate this entire site, which goes back to 1999. (And I have ideas on speeding that up a bit. The generator has some features that I’ve never used, that I could remove and get a performance boost.)
PPS My friend Jake Savin has been writing about moving his Manila blog to WordPress. Here’s part one and part two. (My blog — this blog, inessential.com — also started out as Manila blog back in 1999. Originally it was just for developing Manila’s static-rendering feature, which I was writing. And then I kept the blog going. Of course, I felt at the time like I was late to blogging.)
I’ve been at Omni four days so far — and it reminds me a little of the first episode of Red Dwarf. (I love that show. Because of Cat.)
Remember how when Dave Lister came out of stasis after a million years and everyone was dead? Holly (ship’s computer) kept answering Lister’s question: “He’s dead. They’re all dead. Everybody’s dead, Dave.”
It’s like that at Omni, except that everything’s nice.
Are the people nice?
They’re all nice, Brent.
Is this chair nice?
The chair is nice. Everything’s nice, Brent.
Is the food nice?
The food’s nice, the chair is nice, everyone is nice. It’s all nice, Brent.
Is the view nice?
The view’s nice. Everything. Is. Nice. Brent.
* * *
I’ve actually committed a little bit of code (to OmniFocus for Mac), but mainly I’m nibbling around the edges as I learn a new-to-me codebase. I haven’t been through an experience like this since learning the Frontier kernel in the late ’90s. (I’m eager to contribute more substantially.)
You can get a taste of Omni’s code by looking at the open source frameworks on GitHub. There’s a ton of stuff there, and Omni’s open source frameworks are one of the many reasons I’ve been a long-time admirer.
Another part of my learning curve is learning the app. I’ve been a happy OmniFocus user (on Mac, iPhone, and iPad) since pretty much the beginning, but I’m not a power user. I pretty much ignored contexts, never made folders, never flagged things, never did reviews, etc. I’m learning quickly. (It’s a great app.)
* * *
I’ve given myself this week to adapt to my new schedule. It’s a big enough change that I shouldn’t try and get everything perfect all at once.
So I’m eating as much of the (wonderful) food as I want and I haven’t figured out when I’m going to go for my normal jog. (Probably it’ll be first thing in the morning before work.)
I have a nice commute in the morning (the 40 from Ballard) and a crappy commute going home. I think my mistake is the classic rookie mistake — I’m commuting at the end of rush hour. I should wait just a bit.
* * *
My office is still sparse. I’ve brought in a couple things and I have a plant. It’s a big blank canvas right now, waiting for me to turn it into something that feels like me. The last time I had this experience was 1999 when I moved into my current house. (I might have to go shopping.)
And I’ve never had my own office out in the working world. I’ve literally never programmed while other people besides my wife were around, other than a few trips to Dave Winer’s office in the ’90s. This is very new to me. People can see me.
* * *
I’ve also given myself the week off from blogging and from working on Vesper while I adjust. But I didn’t even manage to go a whole week without blogging, and it’s a cinch I’ll be working on Vesper tomorrow night and on the weekend.
* * *
My job is awesome. I am happy. I’ve earned it.
PS Seattle Xcoders is a week from tonight. At Omni’s theater. I’ll see you there, or afterward at Cyclops. :)
This blog is powered currently by a home-grown Ruby thing — which is super-fast and wonderful, but has the disadvantage of needing a computer. And I’m mobile these days.
(I’ve been working on syncing and mobile apps for years now, but I never actually needed that stuff for myself since I’m always at home in front of a Mac. Until now. Nowadays I actually leave the house. There are all these things happening in the world. I had no idea.)
I could take my current engine and put it on a server and make it work in that context. Probably a few evenings of work.
But I kinda don’t wanna.
I’m thinking that somebody else could write this thing for me. And someone probably has.
What should it be? Which system?
Requirements: can stand up to extremely busy days. (Think of Daring-Fireball-and-Hacker-News-links-at-the-same-time kind of traffic.)
I must be able to post from Mac, iPhone, and iPad. The ideal native app has a sharing extension so I can initiate a post from another app (Twitter client, Unread, etc.).
I have to be able to make it look like my current site, and I need to be able to preserve the URLs I have now. (So there must be a way to import existing pages.)
And I need to be able to host it myself.
Got recommendations? Find me on Twitter.
PS This blog has existed since 1999, and it’s always been powered by something that I wrote. (It’s on its third blog engine.) And I admit that part of my head is still stuck in the ’90s — real bloggers write their own thing. But I think it’s probably okay to let that thought go.