UPDATE: NEWGUIDE NEWGUIDE NEWGUIDE!
Vital iPhone stats for this post:
iPhone version: 3G (should work with 2G and 3GS)
iPhone OS version: 3.0 (rock the hizzouse!)
Jailbreak status: Jailbroken using Pwnage Tool.
The Goal: Get live on-device XCode debugging without being a paying ADC member. This time OS 3.0 style.
Abstract: Same deal as last round. We want to break code signing on the iPhone, and then we want to make Xcode load software into it automatically to debug. In SDK 2.2 (Xcode version 3.1.2) this was just a simple matter of editing some Plists and such to tell Xcode to ignore provisioning profiles. SDK 3.0 (Xcode version 3.1.3) broke these Plist editing tricks. For a while, all you could do was try to hack SDK 3.0 support into Xcode 3.1.2, installed with SDK 2.2. That was really very hairy, though, if you didn’t want to have to switch environments to debug (close and restart Xcode). It was also annoying to configure. Luckily, there’s a new, much less ghetto way. It’s all based on a little hack posted by <zim> in this thread (coral). Essentially, it just replaces a few bits in the Xcode plugin that actually handles the device build, which restores our build and go ability.
Procedure: things marked (2.2 STEP) will already be done if you followed my previous procedure, and you may not need to repeat them.
- Jailbreak your phone. In Cydia, add the source http://iphone.org.hk/apt/. Install the package “Installd Patch” (this used to be Mobileinstallation Patch, just a name change in OS 3.0). Thanks go to @javacom for this lovely little hack, and lots of other wonderful info on his blog. Seriously, if you’re reading this right now, you should be following him. UPDATE 8/3/09: Some are reporting that if you’re on OS 3.0.1 or possibly a 3GS (or both) Installd Patch may or may not actually install. If this is the case, or if you get weird message about your identity being no longer valid, try installing AppSync as a stand-in.
- (2.2 STEP) You will need a signing identity. We’ll break the check such that it doesn’t have to be an official ADC one, so you can make your own using this guide from apple (coral). What you are doing in this step is creating a “Self-Signing Identity.” Note that you should name the identity “iPhone Developer” EXACTLY to avoid having to change a bunch of the steps below.
- (2.2 STEP) Open your project and go to (menu) Project > Edit Project Settings. In the list of properties, find “Code Signing Identity” > “Any iPhone OS Device” and click in the empty box. Assuming there are no entries in the menu, click “Other” and type in the same name you used to generate the code signing certificate above in step (2). For example: in step 2, I used the name “iPhone Developer” and that is exactly what I put in this field. Hit OK and close that settings window. This setting should persist in future projects, and you shouldn’t have to do this again.
Add the special 3.0 sauce:
- Open a terminal.
- type
cd ~/Desktop
(enter) - type
vi script
(enter) - tap
i
on your keyboard (to enter “insert” mode in vi). - Copy/Paste (cmd-v) the following code into your terminal window:
#!/bin/bash
cd /Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Plug-ins/iPhoneOS\ Build\ System\ Support.xcplugin/Contents/MacOS/
dd if=iPhoneOS\ Build\ System\ Support of=working bs=500 count=255
printf "\x8f\x2a\x00\x00" >> working
dd if=iPhoneOS\ Build\ System\ Support of=working bs=1 skip=127504 seek=127504
/bin/mv -n iPhoneOS\ Build\ System\ Support iPhoneOS\ Build\ System\ Support.original
/bin/mv working iPhoneOS\ Build\ System\ Support
chmod a+x iPhoneOS\ Build\ System\ Support - type ESC, then
: x
(colon,x) (enter). This saves and exits in vi. - type
chmod 777 script
(enter) - type
./script
(enter) This will execute the script to patch the Xcode plugin. Assuming it completes correctly, you should be good to go, try it out!
If it executed correctly, you should see something like this:
alex-whittemores-computer:Desktop alex$ ./script
255+0 records in
255+0 records out
127500 bytes transferred in 0.035658 secs (3575647 bytes/sec)
191056+0 records in
191056+0 records out
191056 bytes transferred in 1.782819 secs (107165 bytes/sec)
And the final step (added 7/18/09, fixes the issue where debugging failed on 3.0 and where the binary would fail to launch on 2.2.1): Codesign the binary before it hits the phone (this got patched out in the new Xcode method above). In terminal:
mkdir /Developer/iphoneentitlements30
cd /Developer/iphoneentitlements30
curl -O http://www.alexwhittemore.com/iphone/gen_entitlements.txt
mv gen_entitlements.txt gen_entitlements.py
chmod 777 gen_entitlements.py
Add the build phase: in Xcode, select the menu options “Project > New Build Phase > New Run Script Build Phase”, and enter the following script:
export CODESIGN_ALLOCATE=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/codesign_allocate if [ "${PLATFORM_NAME}" == "iphoneos" ]; then /Developer/iphoneentitlements30/gen_entitlements.py "my.company.${PROJECT_NAME}" "${BUILT_PRODUCTS_DIR}/${WRAPPER_NAME}/${PROJECT_NAME}.xcent"; codesign -f -s "iPhone developer" --resource-rules "${BUILT_PRODUCTS_DIR}/${WRAPPER_NAME}/ResourceRules.plist" \ --entitlements "${BUILT_PRODUCTS_DIR}/${WRAPPER_NAME}/${PROJECT_NAME}.xcent" "${BUILT_PRODUCTS_DIR}/${WRAPPER_NAME}/" fi
NOTE: You will have to repeat this step for every project! (That is, the add build phase part, not the terminal part.) It’s a bummer, but I’m not sure there’s any way around it. I’ll try to figure out if you can persist custom build phases across projects.
Note: You may notice that a number of the steps you remembered from last time are gone now. I believe the few-byte hack above takes care of all the steps. As far as I know, there’s no need to even modify your projects with that one Plist key, everything just works. I currently have this setup working on my production machine, but just to be sure, I’m going to boot up my external disk and I’m going to test this procedure start to finish. As usual, don’t hesitate to comment if you have questions or run into trouble, and I’ll do my best to help.
Special thanks regarding the last step to zim at iPhone Dev SDK forums and to Sylvain Munaut, whose script gen_entitlements.py is used above.
Yeah: the idea is, the dictionary needs the object, so when you add an object for a key, the dictionary retains that object. When you remove the object, it’s released. Typically, you make the object, add it to the dictionary, then release it. That way, the dictionary has the only reference to the object, and you use the object by grabbing the reference from the dictionary. Then, when you’re done with it, you remove it from the dictionary, and that’s the end of it.
ok im working with sqlite instead of a dictionary for the time being. ive downloaded sqlite3 and placed it in the correct directory, ive started creating the code but as soon as i try to init a database i get an error, here is the code:
-(void) readPhrasesFromDatabase {
// setup the db object
sqlite3 *database;
// init with the phrases array
and the error is sqlite3 undeclared (first use in this function)…
i imported the libsqlite3.dylib in frameworks. dunno if this means anything but i doubleclick that file in the xcode main window and i get a Bad CPU Type in executable from a terminal window…
You have to #include sqlight3.h in the top of your controller m file (or whatever else the sqlight3 library header file is called).
dang it. i knew it was something like that. i couldnt find how the sqlframework was being imported and i thought the include must have been there. but since i coded it instead of use the online files, i must have missed it. thx!
im also working on the stanford material and i ran thru the first 3 sections perfectly but in the 4th section im getting an invalid lvalue assignment, here is my code:
NSMutableArray *variousObjects = [NSMutableArray arrayWithObjects:sa, xd, mutstrg, girlfriend, son, [NSProcessInfo processInfo], nil];
for(id obj in variousObjects) {
NSLog=(@” “); //>>>>>this is where i get the first lvalue error….
NSLog=(@”The class name for this object is: %@”, [obj className]);
sorry about that, dont know where that “=” came from…
alex, can you look at this tutorial and answer a question for me:
http://dblog.com.au/iphone-development-tutorials/iphone-sdk-tutorial-reading-data-from-a-sqlite-database/
in the end he has:
1. animal.h/.m
2. animalviewcontroller.h/.m
3. sqlitetutorial.h/.m
4. rootview controller.h/.m
why does he end up with 2 “view controllers”?
he also has:
1. mainwindow.xib
2. animalviewcontroller.xib
3. rootviewcontroller.xib
YOU Rock!! lol!!!
Mars: Every view has its own view controller. That is, in a Twitter client, you might have a timeline view controller, a profile view controller, and so on. The view controllers probably load their outlets from a nib instead of creating them manually (it’s nicer and easier to lay things out in nibs if you can get away with it, there are times when you need the dynamic control, but rarely for the most general stuff), hence the nibs. There are probably 3, because the app always loads mainwindow.xib first. That probably has something like a navigation controller that loads its view from rootviewcontroller.xib.
Does that make a little more sense?
yes, thats kinda what i had in mind, but wasnt sure. im starting to get the hang of this. im working on my first from-scratch app after looking thru examples and going thru assignments 1 and 2 from stanford. im still working on 2A, to which i found a solution online btw, and i wanted to ask you about an error i got in the polygonshape section. This is the link to the code:
http://classroomm.com/objective-c/index.php?action=printpage;topic=1181.0
but when i run this code, i get:
an invalid number of sides 12
no triangle
a square
no pentagon
a hexagon
no hepta, octo, nona, deca, hendeca nor duodecagon
then a bogus and a square again, but then this weird thing:
dealloc is being called! ~ 4 times
alex, pls edit out this previous comment…or at least the dealloc 4 times thing. i cant believe i hadnt seen that being called. i need some sleep 🙂
wow, this is cool, i just got a memory error experience, first-hand! i tried to use an array to return objects to a textlabel, and didnt allocate the memory for it, in retrospect, because the array was created on the fly, in the delegate.m without interfacing/implementing it beforehand…iphonesimulator went nuts…fixed it…still have to figure out the required layout of objC programs. Im so used to being sloppy and declaring functions anywhere in my code, that now im beginning to see the need to send the complete code to a header file and just calling it in the m file…
Trust me, that took me some getting used to too 🙂 <3 PHP.
member that memory leak i was talking about…here is my code:
– (IBAction) randomizeObjects;{
id *objects;
int r = random () % 3;
NSString *aString = @”a string”;
NSString *bString = @”b string”;
NSMutableArray *mArray = [NSMutableArray arrayWithObjects:aString,bString, nil];
NSUInteger count = [mArray count];
objects = malloc(sizeof(id *) * count * r);
[mArray getObjects:objects];
lblRandom.text = objects[r];
free(objects);
}
the idea is that the user clicks the button and with each click he randomizes an object from the array that is displayed in the lbl
These steps are well-written and easy to follow. But how do you get the app onto the phone?! Mine’s jailbroken and I’ve got Cydia working fine. Also, I still get a build error in xCode if I set the SDK to Device 3.0 instead of the Simulator. Missed something somewhere.
Ahh! Why are you malloc(ing) and free(ing) things?! There are at least a couple of ways to do exactly that without ever touching C, the only problem is that I’m not sure exactly what you’re doing. Are you trying to display a randomly picked object from the array in the label?
Oh Chetmun: the app is automatically loaded when you hit build and go, unless you have a build error. Exactly what build error are you experiencing? If you browse through the pages of comments on this post and ctrl-f for some of the text, you can probably find it.
yeah, thats the code i saw somewhere…so should i just move all that code into an object and use superalloc and dealloc?
Practicing first with an example from Apple’s site I get this when I Build and Go…
Code Sign error: a valid provisioning profile matching the application’s Identifier ‘com.yourcompany.BubbleLevel’ could not be found
Chetmun: That means you either didn’t apply the patch (Add the special 3.0 sauce above) or for some reason it failed. Make SURE you have the current 3.0 SDK (NOT the beta, some had issues with that), and repeat those steps.
Mars: In Obj-C, the design pattern is to never explicitly call dealloc at all. If I want a new object ENTIRELY of my own making, I make a new class (file>add new file>objective c class) which inherits from NSObject (the standard template does by default). That class will have a
– (void) dealloc;
method, where you should add things like
[instanceVar1 release]; and
[instanceVar2 release];
to instantiate your object, you say
MyClass *newObject = [[MyClass alloc] init];
and when you’re personally done with it, you say
[newObject release];
Using C APIs like malloc and free mean that you’re making entirely too much work for yourfelf, and in so doing, you’re leaving lots of extra room for error. It’s not that you can’t, it’s just that you’re really better off patting yourself on your back by being lazy.
ok, gotcha. so let me ask you this. i want to, for the time being, hardcode an array with string variables to then retrieve them by a buttontouch event. ive got the button touch nib setup to change the value of a label. since NSMutableArray is already a class, i can just feed an NSMutableArray instance and then get its objects, correct? i can do that inside the delegate m file directly?
If I understand you correctly, right. Your button should be set in your Nib to send its message to a method in your view controller. That method should take NSArray or NSMutableArray you like, and preform the following code
int index = (somerandomintfunction here, between 0 and length of array);
[label setText:[myArray objectAtIndex:index]];
assuming that the array is filled only with NSString objects
thanks for instruction.
I applied it on my project and it compiled fine. but when I try to upload my package to Cydia repository, install it – and when start app – it show splashscreen 1 second and then throw away to springboard (it was fine on SDK for 2.2 FW)
Do you have any idea why?
Thanks.
That sounds exactly like you never signed it with ldid. See here:
http://thebigboss.org/hosting-repository/submit-your-app/compile-for-cydia-submission/
hi Alex!
thanks for your advice.
Unfortunately it doesn’t work for me (still throw away to springboard)
So you’re saying that following the steps here, you can build and go to device without any trouble (AND debugging works) but when you try to install your app via Cydia, it doesn’t work (dies before completing launch)? Are you sure you disabled the build phase and turned off codesigning as per that link before signing with ldid and uploading?
alex: about memory management…im looking at a figure in cocoa fundamentals, page74, receiving and retaining an object. the owner allocates and inits it, [retain count 1]. the owner sends it to a client in a message who retains it [retain count 2]. the owner releases it [retain count 1] and then the client releases it [retain count 0]. my question is, if the client doesnt specify (retain) then he can still use the object and the objects retain count doesnt jump to 2, it stays at 1, correct? what would be the limitations to the client if he just uses the object without retaining it?
You are correct. The primary limitation to the client object is that even if you’re properly managing memory, the client can have the object pulled out from under its feet without knowing. In some cases, that’s not a huge problem since your object may be able to handle that, but in other cases (most cases) it’s a serious issue. The question is whether your client object wants its own version (copy) or the same instance as everyone else (retain).
sometimes i get bogged down trying to understand concepts from the 3 guides im reading (cocoa fundamentals, iphone app programming guide and obj C) plus the theory from the stanford assignments. i get anxious and try to code something like the random quote selection app im trying to build and i run into problems. i guess there is no real order to the process, cause i do all that plus look at sample code to try and understand what it does.
Alex I hereby invite you to my blog…inspired by you 🙂
type ESC, then : x (colon,x) (enter). This saves and exits in vi.
I do not understand this step when I copy and paste then press ESC and type x?
Hi Alex,
Thanks a lot for your great post !
I’ve just got a little problem on my 3GS (jailbroken by redsn0w 0.8), Installd didn’t work for me, I’d to use AppSync by hackulos.
I Buid my Test App nut so errors
[quote]
line 4: /Users/youruser/bin/gen_entitlements.py: No such file or directory
Command /bin/sh failed with exit code 1
[quote]
pls help me ! thanks !
[IMG]http://upanh.com/uploads/30-July-2009/fzgpjs46yjmhw5kzpcfq.png[/IMG]
hi Alex!
great thanks for your help.
Now everything is working.
I puted script direct on xcode and can’t saw any errors. When I try to start ldid manually – it give error:
codesign_allocate: unknown architecture specification flag: -a armv6 ….
I find solution here
Pikachu: When you’re in the vi text editor in insert mode (typing stuff), you exit by first hitting the esc key (to get to command mode), then typing colon-x (the command to exit, it’ll pop up in the bottom left corner), enter.
Ckuron: So you’re saying AppSync does the same job as Installd Patch?
Pikachu: There was a list of commands to copy and paste one-by-one on the command line to download that script and put it in the right place. Redo “And the final step…” on.
Venture: Thanks for the info!
Alex, i had an app that used an button to change the value of a label. i decided to add a UITextView control to replace the label, so i could expand the strings passed to it to longer sentences. I disconnected the Files Owner outlet from the label and set the new programmatically added IBOutlet to the textview control. But in xcode, the IBOUtlet for the label, which i havent erased shows its var name in green whereas the new UITextView var is in black. does this mean anything?
I’m not exactly sure. You’ll probably find out when you run it and it explodes 🙂
I GOT IT WORKING! YEAY! i invited you to my blog and forgot to send you the address DUH….cocoa has got me coocoo for cocoapuffs…. quique123.wordpress.com
That’s true, although you made it your website link in that post. Congratulations!
I think there is another step which is worth adding to your guide (especially for complete novices like me). I mean setting connected iPhone as a development device in Xcode organizer 🙂
alex, xcode is buggy…i add to project an h and m file and when i compile it says they dont exist. they are right there, im looking at them. any ideas? ive closed and reopened and re-added the files.
Alexander: That’s true, although I rarely think about it. The first time you plug a phone in with Xcode open, it automatically asks :).
Mars: Xcode IS buggy, that’s true, although I’m not sure what’s up in your case. The files show up in the bar on the left, and you’ve properly included the headers in the appropriate places? You might try cleaning the build output and rebuilding to see where that gets you.
can i email you the app folder?
sure, [email protected]
Why “Project > New Build Phase > ” is gray could not be checkable?
And the final step is required or optional?
I directly edit the “Bundle identifier” to “iPhone Developer” and HelloWorld app lanuched.
So the final step is required after read the gen_entitlements.py
Xiangzhai: It is definitely requied (or all sorts of stuff breaks) and I usually find that it’s greyed out if I don’t have a project file in the left explorer bar highlighted. Try clicking on one of your project files, it should come back.
Hi,
Trying to follow the instructions, but I am getting an error when I try to install the app on the iPhone: “The identity used to sign the executable is no longer valid.” I’ve spent several days trying to create and recreate the self-signed certs with no luck. Anyone run into this?
Yep: http://www.alexwhittemore.com/?p=270&cpage=2#comment-353
You probably either forgot or for some reason failed without realizing to install Installd Patch on your phone.
Sorry, missed that post (I tried to scan for it, I swear!). I definitely installed it – well, at least I clicked the install button on Cydia. Perhaps it failed? Any issues with 3GS and installd? Not really sure where to go from here.