I think Blogspot is totally outdated, including the design, the style, the layout, and even the backend.
There's no need to waste time on using it, so I moved to Tumblr few days ago. All the entries here had been moved to Tumblr, and you can still make comments over there like you used to. I won't delete this blog, but I won't update it either.
Last, the new blog's name is [digdog dig];
November 22, 2009
Moved to Tumblr
Posted by digdog at 12:44 AM 0 comments Links to this post
July 24, 2009
MapKit annotation drag and drop with callout info update

There're few samples [1][2] about creating a MapKit app for iPhone, and Apple only provides snippets of code for people who want to dig out the secret of MapKit. So I decide to create my own MapKit sample that meets my needs. The sample code is available on my GitHub, MapKitDragAndDrop, feel free to download it.
In this sample, you can:
- Use CLLocationManager to find out current location
- Use MKReverseGeocoder to convert current location coordinate to place information
- Customize annotation/pin callout info
- Update callout info when MKPlacemark is found by MKReverseGeocoder
- And finally, allow annotation/pin to be able to drag and drop
UPDATE 2
Thanks to Uffe Overgaard Koch's help, the MapKitDragAndDrop now can update callout info automatically in both 3.0 and 3.1 SDK.
UPDATE
In 3.0 SDK, the callout view info won't update unless you tap to close it and tap pin again to bring it back. But in 3.1 SDK, the bug seems fixed, the MapKit will update the callout view info automatically when DDAnnotation changed.
UIViewController
The sample works pretty straight forward, it all begins by creating CLLocationManager to update location in UIViewController's viewDidLoad:
Once CLLocationManager updates the location, we create DDAnnotation and add into the map view. Then we stop CLLocationManager from updating location again, otherwise you will see another new annotation drop on the map.
When we add newly created annotation to the map view, the MKMapViewDelegate methods take over. We prepare our own annotation view in mapView:viewForAnnotation:.
First, we avoid user's current location annotation (MKUserLocation, the blue round spot you saw on the map) use our custom annotation view. And then, we try to dequeue our annotation view from map view, if there's no existing DDAnnotationView for us to reuse, we create a new one.
Finally, the tricky part, we assign the map view to DDAnnotationView before return. This is because when later user dragging the annotation/pin to new position, we will need to use map view's convertPoint:toCoordinateFromView: to get the new coordinate.
MKAnnotationView and MKAnnotation
We create our own MKAnnotationView and MKAnnotation, and named them DDAnnotationView and DDAnnotation.
The DDAnnotation is designed to work like MKPlacemark or MKUserLocation, is a specific type of annotation that provides custom title and auto coordinate-to-placemark subtitle for DDAnnotationView, MKPinAnnotationView or other MKAnnotationView to use later.
And this is how DDAnnotation works: When you create DDAnnotation with initWithCoordinate:title:, we save the coordinate and title, and create MKReverseGeocoder to try to reverse coordinate.
Once MKReverseGeocoder converts the geocode to placemark information, MKReverseGeocoderDelegate mehod reverseGeocoder:didFindPlacemark: gets called, and we save the MKPlacemark, and post MKAnnotationCalloutInfoDidChangeNotification notification, to let the map view know about the change. Then, map view will ask DDAnnotationView to retrieve DDAnnotation's title: and subtitle: and update the callout info.
As for DDAnnotationView, this is the part we handle drag and drop events and setup callout view. The event handling code was copied from Apple's iPhone Application Programming Guide, you can check more detail from here.
But, basically, we implement all four touch event methods, which are touchesBegan: withEvent: for recording information about the initial touch event, let us know the start location of the movement, and touchesMoved:withEvent: method adjusts the position of the view by checking the new position to see if the dragging is actually happened.
When the user stops dragging an annotation view, the touchesEnded:withEvent: method takes over, we use map view's convertPoint:toCoordinateFromView: to convert new pixel point back to map coordinate value, and set the new value back to this DDAnnotationView's annotation object with DDAnnotation's changeCoordinate: method. We are doing this was because MKAnnotation's coordinate property is readonly, you are not allow to modify it by default, so we create a "setter" method to do the change.
And Lastly, the touchesCancelled:withEvent: method, this is not a optional method, if you decide to take care touch event, do not ignore this one (Apple said so). We reset the position and states here if draggin is not detected in ouchesMoved:withEvent:.
That's it. Hope you enjoy the ride on the map.
References:
[1] Craig Spitzkoff's Using MKAnnotation, MKPinAnnotationView and creating a custom MKAnnotationView in an MKMapView
[2] Gavi Narra's Playing with Map Kit series: Part 1, Part 2 and Part 3.
Posted by digdog at 6:20 PM 14 comments Links to this post
Annotation, CLLocationManager, drag, drop, iPhone, iPhone SDK, MapKit, MKAnnotation, MKAnnotationView, MKPlacemark, MKReverseGeocoder, pin
April 14, 2009
Black Cat Clock 1.0
After one week of coding and one week of waiting, the iPhone App: Black Cat Clock is available on iTunes Store now.
http://homepage.mac.com/digdog/blackcatclock
It's a simple clock app with my roommate, Lulu. Lulu was born in Sep. 2008, currently 8 months old, mixed, black cat. i love him so much that I decided to create an iPhone App for him, in honor of his handsome, vigorous and good manners.

The clock comes with three little features:
- Analog Clock: an IKEA swiss clock in the picture, which has Lulu standing next as company.
- Meow Meow Hourly: by default, this clock will sounds the hours audibly on Lulu's meow. You can turn off this feature in the setting menu.
- Lulu's Messages: this is designed for network-connected iPhone and iPod touch users only. You can check Lulu's secret daily messages over internet.
And thanks for Brad and Hu's helps from Tokyo, this app comes with four different languages, including English, Japanese (日本語), Trad. Chinese (正體中文) and Simp. Chinese (简体中文). Hope it could satisfy all the cat lovers from these regions.
Last, it costs 99 cents, and your kindly supports can provide Lulu with better cat foods!
April 01, 2009
You can't make hacker tools on iPhone
What is Grupa Reveal
Grupa Reveal is an iPhone app decrypts the scrambled Group Password that used in Cisco's IPSec VPN Cleint.

User are allowed to input the scrambled Group Password (enc_GroupPwd) listed in .pcf file, and the app will decrypt it by using Apple's CommonCrypto library without any other infomation.
How it works
You can follow my previous posts for more detail:
- Using CommonCrypto library to recover the Cisco IPSec VPN Group Password
- Convert hex value to binary data
Where to get
The source code is available on github.
Posted by digdog at 8:16 PM 1 comments Links to this post
3DES, app, cipher, cisco, CommonCrypto, decode, decrypt, digest, github, group password, Grupa Reveal, IPSec, ObjC, SHA1, vpn
March 14, 2009
Migrate from SVN to a remote Git Repository
Before today, I was using my lovely, 3 years old, Mac mini as remote Subversion server, and checkout projects to my MacBook through command-line tools or the limited Xcode's SCM (software control management) Subversion support. And yes, I am not very satisfied with svn, and I bet you know the reason.
And Git is such a wonderful experience, if you tried GitHub. So, I was serious considering to migrate from Subversion to Git in these two days, but it's really a hard decision, especially when Xcode is not supporting Git right now, which means you will have to make a turn and back to your shell prompt. But anyway, I stepped out into the bright sunlight from the darkness of..., huh, I switched. Cleanly moved from Subversion to a remote Git repository. Here are the steps, hope this helps those who wants to do the same:
Use MacPorts to install Git
Unlike other UNIX platforms, installing Git on Mac OS X is super easy. Assuming you had latest Xcode and MacPorts installed, then simply type the command in Terminal:
$ sudo port install git-core +svn +bash_completionIt takes maybe 10 to 20 minutes, depends on your CPU power, and everything is all set. I installed it on both my Mac mini (server) and Macbook (client).
Create Remote Repository on Server
Connect to the server, and setup a new "bare" Git repository:
$ ssh mini.local
Password:
Last login: Sat Mar 14 20:44:00 2009 from macbook.local
$ cd ~/
$ mkdir ~/git/
$ mkdir ~/git/projectname.git
$ cd ~/git/projectname.git
$ git --bare init<
Initialized empty Git repository in /Users/digdog/git/projectname.git
$ exit
That's it for the server side. You just create an empty remote repository for storing deltas and binaries later from your working Git repository.
Convert Subversion to Git from Client
Back to client side, first create a Git repository, and use git-svn to fetch code from your Subversion repository on the server, then clone it to a normal Git repository that does not have stuffs for supporting git-svn, and finally, push back to remote git repository.
Here's how I did:
$ cd ~/
$ echo "digdog = digdog <digdog@my.email.address>" > user.txt
Create a text file that contains username to allow us mapping from Subversion user to Git user later.
$ cd ~/
$ mkdir svn_to_git
$ cd svn_to_git
$ git svn init svn+ssh://mini.local/Users/digdog/svn/trunk/projectname --no-metadata
$ git config svn.authorsfile ~/user.txt
$ git svn fetch
Create a temporary directory called "svn_to_git", then initialize this directory as Git repository, and point it to the SVN repository on my Mac mini server. Next, ask Git to use user.txt to map Subversion user to Git user in next command. Following the step sixth, fetch all the source code from server.
$ cd ~/
$ git clone svn_to_git temp_projectname
$ cd temp_projectname
$ git remote rm origin
$ git remote add origin ssh://mini.local/Users/digdog/git/projectname.git
$ git push origin master
In step two, clone the svn_to_git repository to a another temporary repository, which will will push back to remote repository later. And delete remote branch after cloning in step fourth. Step Five, add the remote repository to local temporary repository configuration, as a remote server called "origin". At the end, we push local master branch (in temporary repository) to the origin's master branch (on the server).
Clone from Remote Repository
So we finished, just clone it:
$ git clone ssh://mini.local/Users/digdog/git/projectname.git
and push/pull your code like a happy Git user.
References
Jon Maddox from Mustache, wrote a great and simple tutorial about how to cleanly migrate from subversion repository to git repository.
Tim Lucas, a web app developer, wrote a clear step-by-step tutorial about how to setup remote git repository.
Posted by digdog at 6:32 AM 2 comments Links to this post
March 01, 2009
Don't choke your watchdog
Your application will be terminated if wasting damn too much time in applicationDidFinishLaunching.
Posted by digdog at 8:34 PM 1 comments Links to this post
applicationDidFinishLaunching, crash, iPhone SDK, terminate, undocumented, watchdog
February 27, 2009
Emoji.plugin for Safari/WebKit Browser
Emoji.plugin is a WebKit Plug-in for Safari/WebKit browser. It will convert Emoji characters into viewable iPhone Emoji icons, if HTML has "<object type="text/x-emoji"></object>" tag.
How to test
- Install the plug-in, and open the Safari (or click "Build and Go" in Xcode project, it will open Safari too)
- Drag the test.html to Safari

How it works
When browser found HTML or XHTML content has MIME "text/x-emoji" type object, it will load this standard WebKit Plug-in.
During the plug-ing initialization, it loads a JavaScript file within the plug-in bundle, and asks current web frame to evaluate this script. The script is based on two people's work over internet, one is photar's Grease Monkey script, and the other is Johannes Schriewer's iPhone emoji image data.
The Grease Monkey script will use XPATH to grep out all the text node, and compares each characters with Emoji character codes, and replace them with <img> image element and uses the image data stored as JSON format in the script.
And browser will update the web frame with Emoji icons instantly.
Known Issues
- Your HTML/XHTML content needs "<object type="text/x-emoji"></object>" tag to let browsers load this plug-in.
- If your browser disable the plug-ins or JavaScript support in preference, this plug-in won't work.
- If your HTML/XHTML is too complex, the script could take very long time to finish the replacement.
Where to get
This plug-in is licensed under MIT license.
The source code is available on github.
Pre-build binary can be downloaded from here.
Posted by digdog at 8:26 AM 3 comments Links to this post
emoji, github, Greasemonkey, JavaScript, plug-in, plugin, script, webkit
