Recent Games

Powered by Squarespace
Search Site

Tag Cloud

Administrivia Television BookReview OSX Photography Programming D&D Politics WordPress Cats Humor iPhone Microsoft Games Heisenberg iOS Blu-Ray Lost Spam ThingAWeek Windows Diabetes Gaming PS3 RPG Video Wii Xbox360 Apple Automator DirecTV Fiction iPod Music Netflix Photoshop ScienceFiction Slack Twitter Web Zune Amazon Backups BattlestarGalactica Blog Comments Cornerstone Drawing Election Email HabeasCorpus Harmony HDTV HomeRepair JonathanCoulton JungleDisk Kindle Logitech Lorax MacBookPro Muppets NaNoWriMo Office Passwords PatternRecognition PAX PennyArcade Pixelmator Playstation Podcast PSP Remote Restaurants RSS SanFrancisco Software Sony SpaceTravel SpookCountry StandingDesk Subversion TheBigLebowski TiVo TV TweetCloud Upgrade Versions VideoGames WiFi WilliamGibson YouTube ZeroHistory 1Password 2010 Acorn Adobe AdvanceWars AndyIhnatko Animation Aperture Archives AreYouFuckingKiddingMe? AttackOfTheGenos Babble Backup Battleboard Beaker Blender Blizzard BlizzCon BluWave BohemianRhapsody Borderlands Boxee California CallOfDuty Camera Capitola CaptainArcolier Cartography Catch22 CGI ChannelMaster4228 CharacterBuilder CharlesStross CharlieStross Cocoa copyright CoryDoctorow Coverville CustomerService DavidPogue Development Dice Dining DNS Dogs Drinks DriveImageXML DRM DS DVD Earthcomber Economy EFF Encryption Escapist Exercise Flickr FlightoftheConchords Flip Flowers Flying Fringe GeorgeRRMartin GlobalWarming GMail GoldenGatePark Google GrandTheftAuto Grill H&RBlock Hacked Hacker'sDiet HaltingState HawkeyeSPECS HDR Heroes HeyLookThat'sUs Hitchhiker'sGuideToTheGalaxy HomestarRunner HowTo Hulu Idiocy Illness InsomniaX iPad IraGlass ISS iWork JeffBerry JetBlue JosephHeller JossWhedon KeithLoutit Keychain KineticTypography Kubacon KurtVonnegut Labels LadiesoftheWorld LaundryFiles Left4Dead LittleBrother MacMini Map MarioSluggers Mars MassEffect MasterBedroom

Entries in iOS (6)

Wednesday
Feb222012

Oh no you didn't VoiceOver

OK, let's say you're making an iOS app. And it's new so you go to use storyboards because they are awesome and you can target iOS 5.x. Swell. And you're going to use UITableViews and storyboards have that hot new prototype thing where you can lay out your cell right there in the UITableView and you're guaranteed you'll always get a cell from dequeueReusableCellWithIdentifier. Awesome! Well not so fast partner. Go read this Radar and this Radar. Yeah, that sucks. Short version is that works fantastically unless your user has turned on VoiceOver, at which point you don't get a cell at all. The stub code Xcode generates at that point will create a generic UITableViewCell with none of your custom layout. If you're lucky you'll get a blank cell. If you're unlucky your code assumed it got a custom cell type and crashes on some property access or method call. So what do you need to do? You have to old school it and just ignore the new layout feature. You can't require your users to turn off VoiceOver, that's not reasonable. You can leave the prototypes in and they will work in the VoiceOver off case but as far as I can tell there is no way to load a prototype cell from a storyboard. I suspect that you might just be able to rummage around in the nib and find a prototype but I don't see a proper way to do that. In the VoiceOver case you have to provide code that will load a cell from a nib file. You can leave the prototype cells in and that will work in the non-VoiceOver case but now you've got two cell prototypes and that's a bad idea. I do recommend leaving the call to dequeueReusableCellWithIdentifier in place though. Even with VoiceOver on the table can recycle old cells so if you do all of the cell identifier stuff then after a while your view can get a working set of cells that it just reuses on a scroll. Here's a code snippet that rolls this all up. It's not revolutionary but it gets the job done.
TripTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// That call is supposed to always work, but it doesn't if the user has VoiceOver on. If they do, we'll engage le hack below
if (cell == nil) {
[[NSBundle mainBundle] loadNibNamed:@"TripTableViewCell" owner:self options:nil];
// The above will load our blankCell field with a new TripTableViewCell.
cell = blankCell;

With this code you make a nib that contains your custom cell. Then in the view controller you make an IBOutlet like so:
@property (nonatomic, retain) IBOutlet TripTableViewCell* blankCell;
In the nib you set the File's Owner to the controller and connect blankCell to the cell. Like I said, nothing shocking here just some old-school-ness in the new storyboard world …
Wednesday
Feb082012

iOS Beta Testers Wanted!

I'm putting the last few VoiceOver accessibility labels in my iOS app (RoadTrip) and then it's basically done. I want to take a stab at putting some custom textures in and I'm sure I'll find some new bugs once I turn off VoiceOver and go back to the iPad version but the end of the project is visible from here. If I know you in real life, you have a iOS 5.0 device available, and you're willing to do some beta testing for me I'd appreciate it. Get in touch with me! I'm hoping to release a beta version by the weekend.
Wednesday
Oct122011

iOS 5.0 Recommendations

I just wrote an email to my immediate family laying out my thoughts about iOS 5.0 and what they should do about upgrading and using iCloud and the like. I realized as I sent it that it might be interesting to more people so I'm going to post it here. It's worth noting a few things about the perspective. I've been running iOS 5.0 on an iPhone 3GS and WiFi iPad 2 for a bit over a month and on a fourth generation iPod Touch since June (although I don't do anything other than software debugging on the touch). So I don't have any experience with 5.0 on an iPhone 4. I suspect it's fine but I haven't tried it personally. I've been running the gold master for the week it has been available. The folks I was sending the email to have a WiFi iPad 1 and a 3GS.

Anyway, here's what I wrote:

1) You'll need iTunes 10.5. I suspect iTunes will ask about upgrading sometime today. That should be fine but be aware it will take a little time so don't do it if you're in a hurry.

2 ) The next time you sync your iPad or iPhone to the computer after the iTunes update it's likely to ask you if you want to upgrade. If you do be prepared: it will take a while to update and restore. My phone (which has more files on it than my iPad) takes about an hour to restore after a system upgrade. It's all pretty seamless but it takes a while because iTunes first backs up the phone, then downloads the system update, then wipes the device, then installs the update, then puts all of your files back from that backup.

3 ) I haven't run iOS 5.0 on an iPad 1, but I suspect it's a fine thing to install. I still would not recommend installing iOS 5.0 on a 3GS phone. I've been running the "Gold Master" released version for a week and it's faster than the betas were but the phone is still very sluggish compared to how it was on 4.3. I still feel playing real-time games on the 3GS is ugly with the quasi-random freezes. Also be aware if you install 5.0 it may be difficult or impossible to go back to 4.3 (the new version usually updates the cellular baseband firmware in ways incompatible with earlier OSes, so to roll back you have to do tricky re-flashing of very low-level chips.) I ordered a new iPhone 4S that I'm getting on Friday, but the only thing that's made running 5.0 on my 3GS acceptable was knowing it was a short-term solution. If they follow the pattern you may find that the inevitable 5.1 works better on a 3GS than 5.0 does. I would suggest waiting at least a week or two and see what shakes out with the 3GS/5.0 situation. And you have to be careful with that because iTunes will encourage you to upgrade. If you just click things without reading you'll get an upgrade.

4 ) iOS 5.0 has iCloud for file storage and you can use iTunes Music Match to stream your music library from online storage. Music Match costs $25/year. This is going to be really cool, but I'd advise staying away from both features for a while. I've tried Music Match on my iPad and it makes a real mess out of things. I told it this morning to download all of my Talking Heads music (I have ~150 tracks from Talking Heads) and my iPad started well over 400 downloads. No idea what it's doing, but it's taking quite a while. Apple cloud things tend to get overwhelmed in the first few days after launch so I'd suggest keeping all of your contacts, calendars, and data files exactly where they are for the first couple of weeks. I turned on Music Match on my iPad because most of the time I listen to my phone - which I'm still syncing manually right now. I have some files on iCloud for testing but only stuff that has multiple backups.

5 ) Having said all of that, turning on the "Sync over WiFi" option in iTunes is pretty awesome. With that your iOS device will sync (and backup!) whenever you plug it into the charger if iTunes is running on the machine you use to connect. None of that uses iCloud in any way - it's just your device and your computer talking over the local network. I recommend turning that on as soon as you can. I've been using that for months now - but I still haven't turned on backing up to iCloud because I trust THAT a lot less.

Wednesday
Jul132011

Quick tip about localizing currency on iOS

Let's say you have a text field in your iOS app and you want to take currency values in said field. NSNumberFormatter is your friend and can happily turn a string like "$42.23" into the floating point number 42.23. It will also turn the floating point number 42.23 back in "$42.23". Even better with the German locale active it will turn 42.23 into "$42,23 €" and vice-versa (note the comma as well as the euro symbol). Sweet! However, here's a minor glitch. Sweden's currency "symbol" is in fact a string – "kr". While your formatter will turn the float 42.23 into "42,23 kr" it cannot turn "42,23 kr" back into the floating point value. What to do? What I decided to do was strip whitespace and currency symbols from the string before trying to convert the string into a float. Like so:

NSCharacterSet* costTrimmingCharacters = nil;
//OK, some settings have currency symbols that can't survive a 2-way trip. For example, Sweden's currency "symbol" is "kr"
//So what we're going to do is trim whitespace and currency symbols from the string. Also then we don't have to use the currencyFormatter and can
//simply use the decimalFormatter (since it will strip $ from US locales, for example.)
NSMutableCharacterSet* tempSet = [NSCharacterSet whitespaceCharacterSet];
[tempSet addCharactersInString:[[NSLocale autoupdatingCurrentLocale] objectForKey:NSLocaleCurrencySymbol]];
costTrimmingCharacters = [tempSet copy];
//Note in a real app you should store costTrimmingCharacters somewhere and only build it the first time you need it.

NSNumberFormatter* currencyFormatter = [[NSNumberFormatter alloc] init];
[currencyFormatter setLocale:[NSLocale autoupdatingCurrentLocale];
[currencyFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
NSString* aggravatingString = [NSString stringFromString:@"42,23 kr"] NSString* goodString = [aggravatingString stringByTrimmingCharactersInSet:costTrimmingCharacters]; NSNumber* goodValue = [currencyFormatter numberFromString:goodString]


Full disclosure: I didn't test that exact snippet, it's frankensteined from a few pieces of code out of RoadTrip that would have just obscured the point. So there may be a syntax error somewhere due to a typo but the idea should be clear. Last two little suggestions:
  1. I use a related character set in the field delegate's shouldChangeCharactersInRange: replacementString: method so that I don't even accept illegal characters and that way you can't even enter "kr" unless you're in the Sweden locale.
  2. In the delegate's textFieldDidEndEditing: method once I've converted the string into a float I go right ahead and convert it back into a string and assign it back into the field. That means if they entered 42.23 they'll see a nice $42.23 or 42,23 € or whatever their locale specifies.
Wednesday
Jun292011

Followups

A few things to follow up from my last post.
  1. I forgot to mention that I had changed from an Apple Magic Mouse and my ancient Microsoft Natural Keyboard (which I spoke at length about here) to the Apple Wireless keyboard and trackpad. Now between that keyboard blog post from yore and the comments here where I complain bitterly about Apple mice and trackpads everywhere you might be going "What?" and you'd have justification. Lemme 'splain. On the keyboard: I wondered if having the keyboard at the right height might be what I needed and the Apple keyboard is much smaller than the MS behemoth. Also, it is wireless which is nice. I figured I'd try it and worse case, if my hands hated it I'd pull out the MS keyboard. So far it's OK. We'll see. On the trackpad: one part of this that it's clear that Lion's iOS-ification of OS X was built to require a trackpad. The other part is that multi-touch makes all the difference on a trackpad. It's maybe not as good as a mouse for pointing but it's great for gestures. I tweeted yesterday that I found out by accident that the two-finger swipe that works for back/forward in Safari does the same thing in Xcode. Man that is just bananas great. Really, really great. Three fingers swipes switch desktops so I can do what I used to do with Spaces and need no keyboard shortcuts to flip from "Development" with Xcode, Simulator, & Safari tabs to "Normal" with iTunes, OmniFocus, and email. So yeah. So far I love the trackpad+Lion combo, and I'm willing to live with the straight keyboard for a smaller footprint and no dangling wire.
  2. Lion. I wrote on Sunday that "I haven't switched over to using Lion full time yet" but Monday I copied over enough files to starting considering Lion my main OS and in fact I haven't rebooted into Snow Leopard since before writing that post. So I think it's fair to say I use it full-time now. I don't really care about Launchpad, but the instant-resume nature of everything plus the gestures … I really like it. There are a handful of apps I need that I haven't installed yet but so far it works great.
  3. iOS 5. I wrote on Sunday that I might want to look at iCloud storage for my app in the future. Well then I downloaded all of the WWDC 2011 talks and started watching them. I immediately ran into a "Oh crap, I want that for what I am working on right now" point. (Sorry to be cryptic but I think the NDA on iOS5 is more serious than the one on Lion at this point.) So I ordered an iPod Touch from Amazon and today I've been working on the simulator which can run a beta OS without fear. I finally gave up, renamed the RoadTrip codebase to RoadTrip Classic, and made a whole new project so I have a modern iOS5 project setup and UI and now I'm porting the logic from "Classic" into the new project. That's also a really nice breakpoint to switch from Subversion to Git so I did that as well.
  4. The standing desk. Blake asked me via email about the shelving units I bought from Target - what I got and whether I bought them locally or online. It's a bit of a funny story because what actually happened was convoluted. See back around Christmas time last year I had convinced Karin that we should get a PS3 to hook up to the monitor in the bedroom for the exercise bike. The reasoning was that I wanted to watch Blu-Ray discs while exercising (oh, and she could as well, naturally :-)) OK, we did that and I hooked up a couple of different choices for video switchers as I messed about and I finally got to a solution that I thought was workable. Problem was there were cables everywhere and I needed a shelving unit to corral the cables, the Mac Mini, the PS3, and the switcher. So I harassed Karin to find something she wanted and she came up with something that I guess is now discontinued but was perfect. In the meantime I had been reading a bunch about standing desks and really thinking I wanted to try it without spending $600 or more on a real piece of furniture. So when I saw this unit I thought "Hmmm. Something like that on top of my current desk would work. If I hate it then I have some shelves to put in the garage. If I like it I can eventually get something more permanent." So I bought a larger version of that cube with a vertical divider to put my monitors on, then put the version with the horizontal shelf in front of that for my keyboard, trackpad, and notepad. Cost about $110 and like I said, if I hated it I had shelves to put somewhere else! I also bought an "anti-fatigue" mat and of course I needed Mini DisplayPort and USB extensions to get the monitors that far from my Mac Pro's chassis. But all in all I was able to build a very functional "See if I like it" standing desk for under $200. And it doesn't look completely hideous. I mean the shelf units are cheap but they aren't flimsy, and it's not like the Ikea desk they are on top was all the much better. It's all particleboard but it looks decent.