Tom Insam

When you buy a new phone, it’s in your pocket, but this, you’re wearing something on your face. Anyone that cares what they look like is not gonna wear Google glasses. That’s my opinion,” Madonna said. “If you are super nerdy and you like to show off that you’re in tech and smart and all those things, I can see you probably wearing Google Glasses, but you are probably in a bubble or … new. We’ve all heard all this stuff. Like, this guy moved to SF and he comes to the bar. He’s from Scottsdale and he’s using all these [tech] words. I had to stop him. I said, ‘You sound interesting and different in Phoenix, but you sound boring here. You are cliche.’

Ok, so ticking the top box keeps that data, but ticking any of the other boxes deletes that data. Except that the descriptions don’t say ‘delete’, you’re supposed to get that from the button at the bottom. Except for the top box, where there is a verb. And the cancel button doesn’t cancel that part of it, obviously.

An iOS 5/6 device can have system-level Twitter/Facebook accounts that become disassociated from the underlying service accounts. This means that the ACAccountStore framework will return you ACAccount objects that can be used to sign requests and get access tokens, but NONE OF THE REQUESTS WILL WORK and you’ll get MYSTERIOUS OAUTH ERRORS and LOTS OF SUPPORT MAIL and be GRUMPY because it WORKS FOR YOU JUST FINE.

I’m not certain how to fake this state. Changing your Facebook password and choosing to log out other devices is pretty reliable, albeit really annoying if you actually use Facebook for anything. Likewise, changing your Twitter password might work. I think restoring the phone from backup will also cause this problem, especially if it’s a iTunes-based non-encrypted backup, because the passwords aren’t saved, but the phone won’t prompt you at any point to enter them again.

When this happens to Twitter account objects, I see server responses to otherwise perfectly reasonably signed requests with the error Bad Authentication data and the error code 215. I used to get This method requires authentication when calling the old 1.0 API, because the 1.0 API interprets a bad signature as no signature (REALLY ANNOYING), but the 1.1 API is a lot stricter.

When this happens with Facebook, I see Error validating access token: The session has been invalidated because the user has changed the password and sometimes Error validating access token: Session does not match current stored session. This may be because the user changed the password since the time the session was created or Facebook has changed the session for security reasons.

The solution to this is the method on ACAccountStore:

- (void)renewCredentialsForAccount:(ACAccount*)account
                        completion:(ACAccountStoreCredentialRenewalHandler)completionHandler;

From the docs:

For Twitter and Sina Weibo accounts, this method will prompt the user to go to Settings to re-enter their password.

For Facebook accounts, if the access token has become invalid due to a regular expiration, this method will obtain a new one.

If the user has deauthorized your app, this renewal request will return ACAccountCredentialRenewResultRejected.

Calling this method on the ACAccount object you’re trying to deal with will make-or-break it. I find that the token either works afterwards, or doesn’t, but now it doesn’t work because the iOS device knows that it doesn’t have a valid token. You may still have to punt the user into the Settings app to fix it. For instance, in the case of Twitter I find that calling renewCredentialsForAccount will pop up a system dialog about the problem.

Facebook is more subtle - the ACAccount object can still be used to get an access token, but that token will fail on the server with The session has been invalidated because the user has changed the password still. However, punting them manually into Settings.app at this point will ask them for a Facebook password and things will work afterwards.

Alas, it’s asynchronous. You can work around that. Call it on the ACAccount instance before you try to do something serious with it, or do work in the callback.

I hope this helps -someone-, because it sure would have helped me 6 months ago.

After a certain number of years, programming becomes much less about correctly instructing the computer and much more about clearly expressing your intent to the humans that will read the code later—including yourself in six months.

Rules I try to adhere to when working on my personal stuff. They might not apply to you, but I have my reasons, so consider them.

  1. There should be a one-line command in the root of the checkout called run that starts the thing and does something useful. If it’s a web server it should start on some high-numbered port that’s unique to this particular project (so I can work on more than one and not care) and it should print the URL it’s running on so I can Command-double-click it and see something useful. It should also start anything else that needs to be running for the service to work. If I ctrl-C it, it should die nicely.

  2. There should be a one-line command to grab the current deployed ‘live’ database/state, or something close to it, and pull it to the local machine. That way I can debug problems that are happening to live. Ideally this command is the same for all my projects.

  3. There should be a one-line command that deploys the service to live (assuming there is a live). The service must ONLY be deployed with this command. It should do everything required to get the current version onto the live server - no multi-step fiddling. I’m not picky between “rsync local codebase” or “check out from Github to remote server” as long as what it’s doing is obvious and consistent. Again, this command should be the same for all projects.

  4. There should be a requirements.txt (Python) or a Makefile.PL (Perl) – or whatever the language I happen to be working in at the time uses as it’s local equivalent – in the local directory, and it should be an accurate and complete list of the project’s dependencies. (In fact, the deploy command from Rule 3 should use it to build the environment on every deploy.) Bootstrapping a mostly clean local environment to a working state should be a single command. This command should be the same for all projects.

  5. I’m allowed to assume a certain set of local running services. Databases and Redis and a system Python. Everything that’s peculiar to this project needs to be deployed according to Rule 4.

There’s a theme here. I don’t work on my personal stuff a lot. There are gaps between sessions of a few weeks, months sometimes. I do not want to spend time remembering how to do any of the incredibly boring boilerplate crap that is associated with coding. I want to cd into the folder, run a command that I know will be there no matter what the project is, and have it work. When I’ve fixed the problem or added a feature, I want to run a single other command and have the working code on the live server without having to remember anything fiddly about this particular setup.

Deployment is a particular bugbear of mine. I hate sysadmin stuff, so I spend a large amount of my time automating it out of existence. DEPLOYING YOUR CODEBASE SHOULD BE EASY AND CHEAP AND FOOLPROOF. Easy, so you can do it whenever you want. Cheap, so you’re never afraid to do it whenever you want. And foolproof, so you don’t leave a step out and break things.

Yes, these rules also apply to your day job projects.

No, I don’t manage them all perfectly. ASPIRE, GODDAMNIT.