Is iOS 5 Beta Live?

June 6, 2011

Currently, Apple’s iOS Developer page is down, while the iOS 5 Beta is being posted. Here’s a quick Perl script that checks every 5 seconds to see if the page is back yet:


#!/usr/bin/perl
use LWP::Simple;
$url = "http://developer.apple.com/devcenter/ios/index.action";
$size = length(get($url));
while( $size == length(get($url)) ) {
print "Not ready! time = " . time . "\n";
sleep 5;
}
print "Ready!\n";

UPDATE: or you can just pull up this web page.


Delegates, Protocols, and Optional Methods

June 5, 2011

In my iOS app, I have a lot of places where I show a modal view, and that view needs to have access to the view that opened it. To implement this connection, I’m using the concept of “delegates,” where one object has another object that it can call methods on. I created a protocol called ModalDelegate that defined the methods that these modals could call on their parent views. However, the way I implemented this caused a lot of compiler warnings. I just now figured out how to fix these, but the answers were difficult for me to find, so I figured I’d post them here.

First, it was my understanding that using id as a variable type was the standard Objective-C way to keep a reference to an object that can be of any class–the equivalent of the Java class Object, but more widespread in use. However, when I stored my delegate as an id, then tried to call a method on it, I received a warning that that method might not be defined. I could have cast the id to the appropriate type, but that seemed like it shouldn’t be necessary.

So, instead, I changed the type of the variable from id to ModalDelegate, the name of the protocol I created. This seemed intuitive to me from the way Java interfaces are used, and the compiler didn’t reject that variable naming. However, I got a similar warning: that method might not be defined. When I looked into it, I discovered that wasn’t the right syntax to use for a protocol at all. The right type for the variable was id <ModalDelegate>–in other words, an object of any type, but one that conforms to the ModalDelegate protocol. Also, instead of referring to @class ModalDelegate; in my header file, I needed to refer to @protocol ModalDelegate;.

The one remaining warning I was getting after this was that my classes weren’t implementing all the methods on the ModalDelegate protocol. The reason for this was that different views needed to have different methods called on them, and I didn’t want to have a separate delegate definition for each. So there were lots of methods in ModalDelegate, and each class that conformed to the protocol only implemented some of them. Of course, this isn’t how protocols are meant to work, but I didn’t see an alternative. But finally I found it: optional methods on protocols. I just add an @optional above all the methods that I want to be optional, and then the warnings went away. For my protocol, I actually wanted all the methods to be optional.

I don’t think this is a violation of the concept of the protocol, precisely because it removes all the warnings I had above. My modal view can call methods on its delegate without compiler warnings, because it knows it should have an id and that it may have a method of the appropriate type. The alternative would be to simply have an id and accept the warnings, or else use performSelector:withObject:, but those seem like overkill for the situation I’m in. The other alternative would be to implement each of the protocol methods and leave some of them as empty implementations. But all of these seem like overkill for my situation. With a protocol with optional methods, I’ve clearly defined for the compiler what I’m doing, and its lack of warnings assures me that I don’t have any typos.


My iOS Bookmarklets

May 17, 2011

Bookmarklets are links you can add to your browser toolbar that perform different functions based on the page you’re currently on. They’re the only option for extending the functionality of Safari on iOS.

I’ve added my favorites to a page with instructions linked below. (WordPress for iPad breaks bookmarklets, it seems.)

My iOS Bookmarklets


iOS Monospace Font Bug – A JavaScript Fix

December 20, 2010

After struggling through trying to find solutions for the iOS monospace font problem, I was able to cobble together a JavaScript fix.

To summarize the problem: in fixed-width fonts on iOS, spaces, question marks, and hyphens/dashes all display wider than letters, numbers, and other symbols. Replacing the dashes with &ndash;es fixed them, but there was no HTML entity fix for question marks or spaces (all the special spaces display either wider or narrower than regular characters).

I was experimenting with different ways to try to get the characters the same width, and I was going to try wrapping the “bad” characters in a span so I could style them differently. What I found was that characters wrapped in a span display at a different width than either the “normal” or “bad” characters not in a span, so it didn’t serve my purpose. But, I also noticed that (almost) all characters (both “normal” and “bad”) displayed at the same width when they were placed into spans!

Incidentally, spaces still didn’t display at the right width, nor did any of the special space HTML entities. (It seemed inconsistent–spaces seemed OK on iPad, but not on iPhone.) The best solution I’ve found so far (and it’s not a good one for the sake of copy-pasting text) is to replace the spaces with an underscore, and style the spaces to be non-visible.

So a solution would go through my code to output, take all the text (non-HTML) characters, and wrap each of them in a span. This was easier on the client-side than the server-side, because the browser has already parsed my document into DOM objects, so it’s easy to tell what’s plain text characters.

The JavaScript function I wrote takes a node, and iterates through its child hierarchy. Whenever it finds a text node, it splits it into characters, wraps each in a span, performs the extra steps I described above for spaces, and then inserts these spans into the DOM in place of the original text node.

Another limitation of this setup is that it can’t be used for editing text in textareas–it can only be used for displaying text.

Note: this has been tested very little! No warranty it won’t erase all your data. If you find cases where it doesn’t work, and you can make it better, let me know and I’ll post the updated version here.

Download the source, or check out an example of it in action, which allows you to see the text before and after the fix is applied.


Monospace Fonts on iOS

December 20, 2010

Today I just had what might be my biggest disappointment of the year: monospace fonts are not monospaced on iOS. Specifically, the hyphen and question mark are wider than other characters in Courier New on iOS. Of course, this completely messes up any kind of monospace-based layout you might want to do.

Here are the alternatives I’ve investigated that didn’t work:

  1. Leaving the programming industry. Unfortunately, I’m not smart enough to do anything else. On to more reasonable alternatives.
  2. Tried other installed fonts. Courier is supported, but has the same problem. Monaco isn’t supported. And that’s all the built-in font options.
  3. Web fonts. I searched through the Google Font Directory and found “Droid Sans Mono.” If that had worked, man, what a slap in the face, huh? Unfortunately, it exhibited the same problem.

Here are options that could or did work:

  1. In app store apps, custom views to lay out text. If you draw one character at a time, you can make sure they’re placed properly. Unfortunately, if you need to use this for an editor (as I do), that would mean re-implementing a ton of functionality.
  2. On the web, replace dashes with HTML entities. This works for webapps and UIWebViews. If you replace all dashes/hyphens with &ndash;, you will see an identical (in Courier New) looking dash, that is spaced properly. This works for displaying text, but wouldn’t work for editors, which are just displaying bare characters and not interpreting HTML entities. Also, this doesn’t solve the question mark problem.

Does anyone else have any suggestions?


Different CSS and JS for PC, iPad, and iPhone

October 17, 2010

I’m working on a webapp that will run on PCs, iPad, and iPhone. To get the optimum experience for each, I have some styles and JavaScript that I want to run on each, some that are only for iPad, some only iPhone, and some for a combination of the above. Here’s the patterns I’m using to implement this.

JavaScript is easy: I just use regular user agent detection to determine which platform we’re on.

function iOS() { return null != navigator.userAgent.match(/(iPad|iPhone)/i); }
function iPad() { return null != navigator.userAgent.match(/(iPad)/i); }
function iPhone() { return null != navigator.userAgent.match(/(iPhone)/i); }

CSS is a bit more complicated, but not much. I’ve found recommendations for how to target CSS specifically to iPad and iPhone. But really the iPad one is for all iOS devices, so I end up with an iOS CSS file and an iPhone CSS file:


<link rel="stylesheet" type="text/css" media="only screen and (max-device-width: 1024px)" href="iOS.css" />
<link rel="stylesheet" type="text/css" media="only screen and (max-device-width: 480px)" href="iPhone.css" />

So I put my PC styles in my standard stylesheet. Then, I fill iOS.css with styles that I want on all iOS devices or only on iPad. Then I fill iPhone.css with styles I want only on iPhone; and, if there are any styles in iOS.css that were for iPad only, I overwrite them in iPhone.css. For this to work, I have to list iOS.css before iPhone.css, as I did above.


Follow

Get every new post delivered to your Inbox.

Join 525 other followers