If you’ve been following me, you’re aware that I’ve been working at Zynga for the past two weeks. Well, they’re still hiring more people (and not just iPhone developers). You can see the available positions at zynga.com/jobs. If you’re interested in any of them, please contact me and I’ll send your info along to the right person.
Comments Off
Last week I pushed out a major rewrite of FontLabel. This new version includes a category modeled after UIStringDrawing that enables you to draw text in custom fonts in your own drawRect: methods. It also includes accurate font metrics and uses more of the built-in UILabel properties. Contributions are welcome!
2 Comments »
My last iPhone contract app, ExecTweets for iPhone, is now on the App Store. This is the project that drove the creation of FeedParser (an open source Obj-C RSS parser). Anyway, it’s free, and if you like reading about business advice from top business execs, check it out!
Comments Off
This coming monday, I am going to stop being an iPhone contractor and start being a full-time employee of Zynga. While there, I will be working on developing iPhone games.
2 Comments »
DNS-SD Browser has finally been released on the iTunes AppStore.
DNS-SD Browser is the iPhone version of my popular desktop Bonjour Browser software. It enables you to view all of the Bonjour services on your local network as well as on wide-area Bonjour domains.
Comments Off
In this modern day, HTML entities can reference arbitrary unicode codepoints. For example, ☃ is the entity for ☃. Not surprisingly, WebKit appears uses UTF-16 internally to represent unicode strings, or at the very least when interpreting HTML entities. One of the big benefits of using UTF-16 is every character is represented by 2 bytes (the 16 in UTF-16 means 16 bits). Contrast this with UTF-8, where a single character can be represented by anywhere from 1 to 4 bytes, or UTF-32 where every character requires 4 bytes (i.e. twice as much as UTF-16). Clearly UTF-16 seems to be useful, as it’s not too much larger than UTF-8 for ASCII strings (only double the size), and you can jump to any character with a simple index into the string. However, one of the often-ignored aspects of UTF-16 is the surrogate pair. Unicode contains more than 0xFFFF bytes, and yet a single UTF-16 “character” (or unichar) can only reference up to U+FFFF. The solution to this is to take the codepoints in Unicode planes 1-16 (U+10000 - U+10FFFF) and represent them as 2 unichars. This is a surrogate pair. You can find more information on this in the wikipedia entry for UTF-16, but to put it simply, a surrogate pair uses a range of codepoints that don’t represent real characters (U+D800 - U+DFFF) and uses them in combination to represent all the characters in the other planes.
The reason this is interesting is because it exposes an interesting quirk as to how WebKit interprets HTML entities. WebKit properly converts entities that represent characters outside of plane 0 into a surrogate pair, such as 𝍧 (𝍧). This gets converted into 0xD834DF67. The quirk is if you give it the surrogate pair codepoints directly, it doesn’t realize they’re not real characters individually and passes them through unscathed, so that same character can be written as �� (). Now this doesn’t seem particularly harmful, except if you only write the first of these entities, WebKit will then get very confused. It will end up throwing away the entire rest of the line of rendered text. Interestingly, it starts displaying text again after a line break, even if it’s just an implicit line break.
The ideal behavior here is WebKit should just silently ignore any entities which reference a codepoint that’s part of a surrogate pair. The fact that it doesn’t really doesn’t hurt anything, but I thought it was worth documenting.
Update: A question was raised on twitter about how surrogate pairs affect indexing into a UTF-16 string. I didn’t know the answer, and strangely, I couldn’t find information on how to handle it with google either, so I tested empirically. NSString uses UTF-16 internally, so it was a great way to test. And what I found was that each half of a surrogate pair is counted as a separate character. The -length of the NSString is increased by 2 when you add a surrogate pair, and -substringFromIndex: will happily split up the surrogate pair for you. Of course, if you do split a surrogate pair, then attempting to convert the NSString into another encoding, even with the simple -UTF8String, will return NULL as such a conversion is illegal (when you generate a unicode stream it has to be well-formed, and so you cannot generate a stream with half of a surrogate pair - and half of a surrogate pair in UTF-16 will be converted into a single invalid 3-byte UTF-8 sequence).
Comments Off
As a PlayStation™ 3 owner and an Apple TV owner, I can’t recommend MediaLink enough. It fills the missing link in my tv/movie-watching habits. Everything in my iTunes library I can watch on my Apple TV, but I have plenty of video files that iTunes can’t handle. Until recently, I’ve been forced to watch them on my computer. But I have an HDTV for a reason, and I’d like to watch my shows there. Nullriver’s MediaLink solves this problem. Anything that I can’t watch on my Apple TV, I can watch on my PS3, and it works flawlessly. I can fast-forward and rewind smoothly, I can jump to any point in the movie (using the PS3’s Go To feature), and it handles everything. Even when my computer lost wifi briefly (the microwave interferes with my desktop’s wifi), the video stream just paused until the wifi came back and then resumed as if nothing happened. If you own a PlayStation™ 3, you should go out and purchase MediaLink right now.
Disclaimer: I have no personal stake in Nullriver or MediaLink, I am simply a happy customer.
Comments Off
Update: I've refactored the code significantly and introduced the ability to explicitly unguard methods from within specs.
One problem I find myself having when writing tests is ensuring that no execution ever leaves my little test sandbox. For example, when writing tests for github-gem I keep looking through the code to find every place a function ends up `shelling out` and it's tiresome and error-prone. I finally decided I was going about this backwards. Testing is supposed to find problems for me, right? So why not raise an error whenever `` or Kernel#system() is called and let the tests tell me what else I need to mock?
Put the following code in your spec_helper.rb file and an exception will be raised whenever `` or Kernel#system() is called during a test:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
| class Module
def metaclass
class << self;self;end
end
end
module Spec::Example::ExampleGroupSubclassMethods
def add_guard(klass, name, is_class = false)
guarded = nil # define variable now for scoping
target = (is_class ? klass.metaclass : klass)
sep = (is_class ? "." : "#")
target.class_eval do
guarded = instance_method(name)
define_method name do |*args|
raise "Testing guards violated: Cannot call #{klass}#{sep}#{name}"
end
end
@guards ||= []
@guards << [klass, name, is_class, guarded]
end
def add_class_guard(klass, name)
add_guard(klass, name, true)
end
def unguard(klass, name, is_class = false)
row = @guards.find { |(k,n,i)| k == klass and n == name and i == is_class }
raise "#{klass}#{is_class ? '.' : '#'}#{name} is not guarded" if row.nil?
(is_class ? klass.metaclass : klass).class_eval do
define_method name, row.last
end
@guards.delete row
end
def class_unguard(klass, name)
unguard(klass, name, true)
end
def unguard_all
@guards ||= []
@guards.each do |klass, name, is_class, guarded|
(is_class ? klass.metaclass : klass).class_eval do
define_method name, guarded
end
end
@guards.clear
end
end
Spec::Runner.configure do |configuration|
configuration.prepend_before(:all) do
self.class.send :include, Spec::Example::ExampleGroupSubclassMethods
end
configuration.prepend_before(:each) do
add_guard Kernel, :'`'
add_guard Kernel, :system
add_class_guard Process, :fork
add_class_guard Open3, :popen3 if defined? Open3
end
configuration.append_after(:each) do
unguard_all
end
end |
Note: if you want, you can write :` instead of :'`', but my syntax highlighter here doesn't like that.
Comments Off
I just picked up a new Flip Video and was dismayed to find out that it used a custom app to import its movies, and that this custom app was PPC. I was also dismayed to find out that iMovie ‘08 refuses to import AVIs even if you have the appropriate codec installed. So after some hacking, I put together an Automator workflow that will convert all your Flip videos into DV and import them into iMovie. You can download it here.
Update: I’ve put up a new version of the importer that has a much longer timeout when waiting for Quicktime to export each movie.
27 Comments »
Recently I was contracted to write some software, and it’s just now been released. It’s called GrabUp. Basically, the whole purpose here is for zero-click sharing of screenshots. GrabUp is a daemon that sits in the background and waits for you to take a screenshot, then it instantly uploads it to the GrabUp servers and puts the URL on your clipboard. It has a nice status item to let you know when it’s done. If you have GrabUp running and you want to share an image, just take the screenshot and then paste the URL anywhere. So far, GrabUp has been seen in TUAW and we also got a rather nice blog post reviewing it.
3 Comments »
|