February 21, 2009

Bypassing code signing to test your app on the iPhone device

Apple requires apps to be signed with a signing identity before you run them on device or distributing them to App Store. To get a valid signing identity (code signing certificate + private key), you must apply for Apple's iPhone developer program and pay them $99.

It is possible to run and test your app on your jailbroken iPhone without the need to pay (you'll still have to pay if you wish to publish your app on the App Store anyway). This process is often referred to as bypassing code signing.

Open Cydia on your iPhone, in the home page, scroll down and tap Bypassing Code Signature in the Developer section, you'll see instructions to bypass code signing. There are 3 options. Option #1 is what I tried. You can find detailed instructions for the other options on the internet.

Option #1: The verification check in the iPhone OS has been hacked so you can sign your code with any self-signing certificate and iPhone will let you pass. If you want the most integrated and smooth development experience with Xcode (Build and Go and debug on the device), this is the option for you.
You need to do two things.
The first is to bypass the Xcode verification.

  1. Create a self signing certificate named iPhone Developer following the instructions by Apple Obtaning a Signing Identity .
  2. in Xcode - > project - > edit project setting -> Add User - Defined Setting
    PROVISIONING_PROFILE_ALLOWED : NO
    PROVISIONING_PROFILE_REQUIRED : NO
    (there seems to be a way in which you don't have to add these settings on a per project basis but I haven't tried. see Developing Application for iPhone OS)
  3. add in info.plist - > SignerIdentity : Apple iPhone OS Application Signing
    (from http://forums.macrumors.com/showthread.php?t=640341 )
Now you should be able to choose device targets and build your app. Try clean if you see code signing related errors.
You'll probably get a device verification error if your iPhone's Mobile Installation files haven't been patched yet. So the second thing to do is to compromise the verification on the iPhone.
  1. add http://cydia.hackulo.us to your Cydia sources
  2. install miPatch in Cydia
  3. reboot your iPhone (I didn't reboot and it worked IIRC)
Done.

see Developing Application for iPhone OS for more information.

Option #2: Just build your app and scp it to your iPhone and run ldid -S yourapp. ldid (Link Identity Editor ) is a command line package available in cydia. see http://www.ipodtouchfans.com/forums/showthread.php?t=104884

Now I can debug on my device live - tap a button and stop at a breakpoint set in Xcode. I wouldn't want to write any iPhone app without a real Mac!

Legal Notice: I don't live in a country where this kind of notice is favoured. But for completeness, please know that bypassing Apple's restrictions is usually illegal. However, $99 is too much for a curious guy who just wants to test his Hello World.

February 17, 2009

Private methods in Objective-C

Private method in Objective-C

Objective-C doesn't have the concept of private methods although you can use @private, @public, @protected to specify visibility scope for variables of a class.
One way to simulate private methods is to use category.


// in MyClass.m, before the main @implementation block
@interface MyClass (Private)
- (void)privateMethod;
@end

// you won't get warnings if this block is missing
@implementation MyClass (Private)
- (void)privateMethod {
//do sth...
}
@end


Note that it's a good practice to write an @implementation block for the category as soon as you finish the category @interface declaration. If the @implementation block for the category is missing, the compiler won't warn you about any missing method implementations.


// in MyClass.m, before the main @implementation block
@interface MyClass ()
- (void)privateMethod;
@end

@implementation MyClass
- (void)privateMethod {
//do sth...
}
@end


You can also leave the category name blank to use an extension. If you do so, you must implement the methods in the main @implementation block. The compiler will always issue warnings when implementations for the methods are missing.

References
  1. http://developer.apple.com/documentation/Cocoa/Conceptual/ObjectiveC/Articles/chapter_6_section_1.html#//apple_ref/doc/uid/TP30001163-CH20-SW1
  2. http://www.otierney.net/objective-c.html#categories
  3. Best way to define private methods for a class in Objective-C

January 27, 2009

marquee generates swarms of scroll events in Webkit

The non-standard marquee tag, first introduced in early versions of IE, can be useful to create scrolling effects. Though deprecated, all major browsers today seem to support it.


sample scrolling text in marquee

One thing you should be aware of is that in Webkit (used by Appla Safari and Google Chrome), marquee generates a steady stream of scroll events. If you have listeners to the scroll event on the document, watch out for these events which bubble up to the document! You may want to filter out them by checking event.target. For example:



$(document).bind('scroll', function(event) {
//filter out scroll events of marquees in Webkit
if (event.target != document) return;
//documrent scroll...
});

August 27, 2007

Screen scraping with jQuery

A test case in my work requires a complete list of HTML elements and a list of self-closing elements (e.g. <br/>).

The W3C Index of HTML 4 Elements lists all defined elements in a table. For each row with an "E" in the Empty column, the corresponding element doesn't need a closing tag (and thus is self-closing).

With two lines of jQuery code in the Firebug console, I got the lists I wanted. Here is how:

To get all elements

$.map($('table tr:gt(0) a'), function(e) {return $.trim($(e).text());})

To get all self-closing elements (formatted for readability)

$.map(
$('table tr:gt(0)').filter(function() {
return $(this).find('td:nth-child(4)').text() == 'E';
}),
function(e){return $.trim($(e).find('td:first-child').text());});
$.trim() is needed because the HTML source contains \n in the Name column.
This demonstrates a handy usage of jQuery as a hacking tool. Another excellent demonstration can be found here.
You can add jQuery to the current page using the jQuerify bookmarklet.
Happy jQuerifying!

July 26, 2007

Ruby code: Finding the closest point

We want to fetch an avatar of specific size. How to find the closest size from all available sizes? Suppose available sizes are 16, 48 and 96.

An obvious version is

  def closest_size(size)
case
when size < 32
16
when size < 72
48
else
96
end
end

The value used in comparison tests is the average of two neighboring candidate sizes. The problem is that when our available sizes change, we need to add or remove when clauses and recalculate average values.


Here is a smarter way

def closest_size(size)
points = [16, 48, 96]
distances = points.map {|a| (size - a).abs}
points[distances.index(distances.min)]
end

It finds the point with shortest distance to the given size. Now if we want to change candidate sizes, we only need to change the array literal. Further, we can even pass the candidate array as an argument.

Rails: Error calling Dispatcher.dispatch...

I ran into a strange issue with one of my rails projects today - the browser displayed html source code in plain text instead of rendering. Nothing is listed in Firebug's net tab. Strange! Later I found the server was always sending back HTTP 404 with Content-type: text/plain. In the log, there were many lines of "Error calling Dispatcher.dispatch #<NameError: cannot remove Object::Handler>".

Finally, I found out that in a controller, someone has put include xxx at file level and in that module he defined class Handler. So that was it. After moving include xxx into the controller class definition, everything went well.

File level include (include outside class/module definition) actually affects Object - the mother of all ruby elves. So it's something we should definitely avoid in real world projects.

Never include outside class/module definition.

BTW, Rails is notoriously good at giving error messages unrelated to the cause of the problem. This is largely due to the dynamic nature of Ruby.

May 6, 2007

Ubuntu 7.04/8.04 and Mouse Wheel

I've just installed unbuntu 7.04 in VMWare. Everything is cool except that the mouse wheel stops working.

sudo gedit /etc/X11/xorg.conf

Find the mouse section which may look like

Section "InputDevice"
Identifier "Configured Mouse"
Driver "mouse"
Option "CorePointer"
Option "Device" "/dev/input/mice"
Option "Protocol" "ps/2"
Option "ZAxisMapping" "4 5"
Option "Emulate3Buttons" "true"
EndSection

Change Options "Protocol" "ps/2" to Option "Protocol" "IMPS/2"

Save the file and restart X (ctrl + alt + backspace).

It works for me. Happy scrolling!

UPDATE: 2008-8-18

Now with Ubuntu 8.04 running in VMWare Workstation 6.04 on Windows Server 2008...

The working config for me is as below:

Section "InputDevice"
Identifier "Configured Mouse"
Driver "vmmouse"
Option "CorePointer"
Option "Device" "/dev/input/mice"
Option "Protocol" "ImPS/2"
Option "ZAxisMapping" "4 5"
EndSection

The mouse cursor moves very smoothly crosses hosting and virtual machine seamlessly.