Developing for a jailbroken iPhone, A to Z (iPhone 3.0)

30rockin
Rockin 3.0

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.

  1. 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.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.
  3. (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:

  1. Open a terminal.
  2. type cd ~/Desktop (enter)
  3. type vi script (enter)
  4. tap i on your keyboard (to enter “insert” mode in vi).
  5. 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
  6. type ESC, then : x (colon,x) (enter). This saves and exits in vi.
  7. type chmod 777 script (enter)
  8. 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:

  1. mkdir /Developer/iphoneentitlements30
  2. cd /Developer/iphoneentitlements30
  3. curl -O http://www.alexwhittemore.com/iphone/gen_entitlements.txt
  4. mv gen_entitlements.txt gen_entitlements.py
  5. 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.

274 Comments

  1. July 18, 2009

    My obvious advice is to simply redo it and make a cert called “iPhone Developer”. That way you know everything will work as expected. That said, your other option is to look through each step carefully and change the name where it appears. There are two reasons I don’t recommend this: 1. it’s a pain – I may or may not be able to catch them all, and I wrote (or at least repeatedly tested in some cases) all these steps. 2. I have a couple more guides that are still in the works that generally revolve about this convention. You never know where codesigning will come up, but you do know that if you keep things consistent, it won’t be a problem.

    That said, did you restart your computer and iPhone? It can sometimes be a problem if you don’t.

  2. July 18, 2009

    Sorry to anyone who just tried the new step – I realized it was buggy when I tried to verify something for my next post. Everything should be all set now, repeat it as above if you ran into trouble.

  3. Zahangir Alam
    July 19, 2009

    Hi,

    Hi I am new into the iphone development. I need your help if possible.

    I have done jailbreaking part for my iPod. I want to build and run a sample application into my ipod using xcode.

    I have done your provided steps for Xcode 3.1.3 and iPhone OS 3.0. I have seen the following success message.

    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)

    Then I have added “Project > New Build Phase > New Run Script Build Phase” with your shell script. After than when I build the project I got the following error still now.

    ‘Code sign error: a valid provision file………………………’

    Here I have used ‘iPhone developer’ self signing identity.

    Let me know how can I get rid from it.

  4. alex
    July 19, 2009

    My obvious advice is to simply redo it and make a cert called “iPhone Developer”. That way you know everything will work as expected. That said, your other option is to look through each step carefully and change the name where it appears. There are two reasons I don’t recommend this: 1. it’s a pain – I may or may not be able to catch them all, and I wrote (or at least repeatedly tested in some cases) all these steps. 2. I have a couple more guides that are still in the works that generally revolve about this convention. You never know where codesigning will come up, but you do know that if you keep things consistent, it won’t be a problem.

    That said, did you restart your computer and iPhone? It can sometimes be a problem if you don’t.

    I’ve made a cert called “iPhone Developer”, redo all actions, result – same! Restarted computer and Iphone – same! Try to compile without connected Iphone – same, kill me please =( This error called before compiling..

  5. alex
    July 19, 2009

    Sorry, tag quote did not work

  6. July 19, 2009

    Zahangir: First, make sure you did step 3 under Procedure above, and Second, make sure you’ve restarted Xcode. Restarting often fixes the issue. A lot of people have been reporting that trouble, though, so I’ll try rerunning ALL my steps from scratch on a different install later today.

    Alex: Same deal, I’ll try repeating all my steps to track down the source of the problem.

  7. alex
    July 19, 2009

    sorry, looked at folder in sdk which called as “3.0 (7A238j)”, its f..ing beta!
    two days without work due to my own stupidity =((

  8. July 19, 2009

    Alex: Wait, so the problem was that you tried to do all this using the SDK 3.0 beta? That’s weird, since it still should have worked. Did you update to the full release and test again?

  9. alex
    July 20, 2009

    nope, Don’t have dev acc for downloading release SDK, today will find. When try will write about my luck =)

  10. July 20, 2009

    Gotcha. Keep in mind that a dev account is free, you only have to pay once you want to do things like provision your phone, submit to app store, use push notifications, and so on.

  11. July 20, 2009

    Hi, i use the trick and it works well! but there is two problem:
    1. when i try to exit the app in iPhone debugging won’t stop and Xcode say : “…broken pipe”
    2. I try to use break point, heh… did not work at all (on device debugging!)

    what should i do?

  12. July 20, 2009

    There’s a new step at the bottom. You have to add a custom run script build phase which generates entitlements for the binary and uses them to psuedosign it before shipping to the phone. On a 2.2 device, this also manifests itself as the binary simply not launching. You could actually accomplish the same goal by signing the binary with ldid on the phone, or on the computer using the OSX binary before your app binary is loaded, but of course, this still has to be a build phase anyway or it won’t happen before the debugger needs it to.

    Bottom line is, do that last step, and you should be good. Also note, the second part of it (actually adding the build phase) has to be done per every project.

  13. mars
    July 20, 2009

    alex, this new extra step you are talking about (from zim if i recall correctly), the build phase script, is for allowing debugging on the iphone? i have sdk3.0 with xcode 3.1.3, do i need to do this as well, or is it just for 2.2?

  14. July 20, 2009

    Exactly correct. It used to be that we told Xcode that it didn’t need a provisioning profile – that didn’t break the fact that it still codesigned the binary before sending it to the phone. This new hack totally kills all codesigning functions, meaning it loads an unsigned binary to the device. On 3.0, apparently the Installd patch is comprehensive enough that that’s not a problem – it still launches, but debugging is broken. On 2.2, the binary simply cannot launch, springboard prevents it.

    So yes, you need this step for both 3.0 devices and 2.2 devices. I haven’t tested it with 3.0 3GS, but I suspect it’s the same.

  15. mars
    July 20, 2009

    ok, so im new to objC and iphone coding. isnt the application delegate the same thing as subclassing really? Im reading the iphone app prog guide (IAPG) and it says the delegate is a design pattern used to avoide subclassing complex objects such as the UIApplication object, but really thats what its doing. It says “Instead of subclassing, you use the complex object itself and put any custom code inside a second object, which is the delegate object.” So really you are creating an object of the UIApplication object. I guess the difference is that you are not forced to “physically” create a new object in memory but rather just give the existing one a “new protocol”, no?

  16. mars
    July 20, 2009

    one other thing, im getting confused with properties that look like methods of an object. for ex, the idleDisabledTimer property of the UIApplication object, oh ok, its a property because it doesnt send a message to any object or alter data, it just sets a key/value pair to something. whereas a method would actually calculate stuff and return values like a function?

  17. July 20, 2009

    Mars: This is relatively off topic, but hey, I don’t see a better place to ask the question. Delegation accomplishes all of the same goals as subclassing, insofar as that modifiable behavior that’s already built into the class you’re concerned with. Really, the advantage of it is that it supports the “Model, View, Controller” methodology by allowing you to separate your control code into something apart from either the model code or the view code (which is probably what the class you’re subclassing represents).

    It’s somewhat difficult to follow until you get used to it and start to like it. Imagine, for example, that I have a bunch of views that show, say, a user’s profile. I could either subclass the UIView class to say “when you’ve finished loading, grab this data from the web”, or I could give it a controller that puts that code in the “viewDidLoad” method. In this case, the UIView is delegating responsibility for that post-load initialization code to a UIViewControler. In this case, the delegation is more portable and reusable than just making a subclass, because, say you have a different type of profile display somewhere else. This new profile view does pretty much everything the same as the first one, except one thing is different – say you want to delay a while before loading it or something. You can use the same delegate for both, instead of having to rewrite the customization code for both versions of your subclass.

    Basically, all it is is a step to make code more reusable. Only code that truely customizes an object in a unique way with no need to repeat gets subclassed. Does that sort of make sense? It’s got much less to do with memory requirements (for the most part, I think they’re theoretically about the same) and much more to do with your experience as a developer. It’s just something to get used to, and eventually you’ll begin to really like it.

    As for properties, I can see your confusion. In a Matlab class, for example, you can have a class called foo, a property of it called bar, and a method called printstuff (let’s say it just echos something).

    I can instantiate a foo and say something like myfoo.bar = 3;
    myfoo.printstuff;
    //some output here

    and if I try to do myfoo.printstuff = 3, it’ll say I can’t do it since that’s a method.

    In Objective-C, this is different: I can’t directly access a property from outside of the instance at all, I think ever (though I could be wrong, regardless, it’s definitely not normal).

    That is, if I set up that same class in Obj-C and I tried myfoo.bar = 3, it’d complain about there not being any method called bar.

    You might be getting confused because the current language spec allows for @synthesize, @property, and dot syntax.

    Normally, if I had a property called bar, I’d have to make a setter:
    – setBar(input){//code to set the value based on what was passed as an argumet}
    and a complementary getter
    – bar{//code to return value of bar}

    Note that I omitted lots of critical things for the sake of example, not the least of which is typing.

    Anyway, that looks an awful lot like the old foo.bar. In fact, with dot syntax, something like

    foo.bar = 3;

    is automatically expanded by the compiler to the full message

    [foo setBar:3];

    which is confusing because what you’re REALLY doing is not accessing the property, but using the getter and setter method automatically without necessarily knowing it.

    Hopefully that clears things up. I will say, though, that those documents can be confusing if you’re just starting. I had to reread a few times to get the drift, whereas watching the CS193P videos on iTunesU from Stanford’s class on iPhone programming, I picked it up very quickly. I highly recommend you take a few hours and just watch the first few (or all) lectures here: http://www.stanford.edu/class/cs193p/cgi-bin/index.php

    I’ll also recommend that you download all the materials from that site and from iTunes U as soon as possible, since it will soon be cleared in preparation for next semester’s class.

  18. apmadz
    July 21, 2009

    Yes!!! Works great! Thank mr. whittemore, your’e my hero!

    A “hello world” never looked so beautiful in my life before. :)))

  19. mars
    July 21, 2009

    alex today i tried to upload a new app to my phone and i get a “no provisioned iphone is connected” error? 🙁 i have already successfully uploaded an app before, i havent made any changes

  20. mars
    July 21, 2009

    nevermind alex, i rebooted xcode and iphone. one question, does the script file created in vi script need to reside permanently in the directory where it was first saved and ran? cause thats the only thing i changed, i moved that file to the documents folder because it was on my desktop.

  21. July 21, 2009

    Mars1: Actually, that error is nice because it’s the easiest to debug. In fact, it almost always means that you don’t have a provisioned device plugged in :). I actually get it all the time, particularly when Xcode conflicts with iTunes for control of the device. For example, when iTunes makes the device sync. The easiest way to never see it is to open the Organizer (I believe window>organizer), which shows you a dashboard of all your devices (among other things). If you see an orange circle or a red circle next to your device, or if it doesn’t show up, unplug it and plug it back in and that usually fixes everything.

    Mars2: Actually, that script can get deleted entirely, you only needed it that once. The only script that you always need to keep around is the gen_entitlements.py one, which my instructions nestle away in /Developer for you. In fact, I should probably make my instructions delete the first one once it’s done to save the confusion.

  22. alex
    July 21, 2009

    installed last SDK – everything works perfectly

  23. July 21, 2009

    Well, hey, good to know the beta was the problem!

  24. Zahangir Alam
    July 22, 2009

    Hi Alex,

    Thanks alex, my version now is working with this solution. Problem was: I did not restart the computer.

    I have created a sample application and deployed into my ipod.

    Thanks buddy, good solution for OS 3.0

    Regards,
    Zahangir Alam

  25. MertenNor
    July 22, 2009

    I get Error:

    iPhone developer: ambiguous (matches “iPhone Developer” in /Library/Keychains/System.keychain and “iPhone Developer” in /Users/Morten/Library/Keychains/login.keychain)

    Any help.. ??

    send me a Mail on: [email protected]

    Tanks

    MertenNor

  26. July 22, 2009

    I think I know what the problem is, anyway: You tell Xcode to sign your code using the identity “iPhone Developer” It looks in your keychain for that. The problem is, you have two keychains – the system one, and the user one (one applies to all users, one only applies to you). I think the problem is that you’ve tried these or similar steps at least twice, once opting to put the certificate in your user keychain (default) and once opting to put it in the system keychain (non default). The answer should be to launch /Applications/Utilities/Keychain Access.app, find the cert in the system keychain, and delete it. If that doesn’t work, find and delete BOTH, then redo the first step 2 above, accepting defaults except where noted.

    That should do the trick.

  27. Falk
    July 22, 2009

    Hi Alex,

    running the build script failed:

    ” […]/Release-iphoneos/rhorunner.app/ResourceRules.plist: cannot read resources
    Command /bin/sh failed with exit code 1″

    What does that mean?

  28. July 22, 2009

    I haven’t got a clue! You’re running the release version of SDK 3.0 right? Some people have had issues.

  29. Krit
    July 22, 2009

    Alex, thank you for publishing this procedure. I followed your instructions step by step and I’m getting two pop-up boxes stating “The identity used to sign the executable is no longer valid.” . I have managed to make it work a couple of months back with 2.2.1 – I’m not sure if there are any leftovers from that procedure that are interfering. Any suggestions?

  30. July 23, 2009

    If I had to make a guess as to why that’s happening, I’d wonder if maybe you’re using the same iPhone Developer codesigning identity this round that you used the first time you tried any of these procedures and I’d wonder if maybe, for some reason, it’s actually been long enough for it to expire.

    My suggestion is to open Keychain Access (in /Applications/Utilities) and delete all the iPhone Developer certs you may have, then redo step 2 above where you make a new one.

    Hopefully that should do it.

  31. asda
    July 23, 2009

    hi,thanks for this article. I did according to the step, everything works well until installing app on my iphone, it’s pop up a prompt said: “The application could not be verified”. and failed to install. I don’t know why. any suggestions? thanks

  32. July 23, 2009

    You remembered to install Installd Patch, right? That sounds like the error you’d get if you didn’t.

  33. Krit
    July 23, 2009

    I checked that, and the certificate was set to expire in 2019. I did delete anything relevant to the iphone developer certificate and recreated it though; I get the same error.

  34. July 23, 2009

    I’d google a bit first, and let me know if you figure it out, but you’ve got me stumped: The sure-fire (pain in the butt) way to fix it should be to completely uninstall Xcode, delete /Developer, and start over.

  35. Krit
    July 23, 2009

    I couldn’t find anything, so I tried what you suggested. Reinstalling xcode didn’t fix the problem but it lead me to realize my dumb mistake. I omitted the Installd part, don’t ask how or why.

    My apologies for troubling you, thanks again for the precious post. At least now know what the problem is when someone gets “The identity used to sign the executable is no longer valid.”!

  36. July 23, 2009

    No, by all means, as long as the question gets answered eventually, it’s helpful to have posted it. For example, I’d never have expected you to get that error as a result of not installing Installd Patch, but now it’s here for anyone else who gets it to find via google 🙂

  37. mars
    July 24, 2009

    Alex, id like to know if i can post a question to you, perhaps in a new thread since i think this is really way off topic. i started here because i needed to be able to upload apps to my iphone without the devportal fee$99 not because of the money, but because im not ready for primetime, heck, not even a 5second PBS segment 🙂 in reference to programming in objC. my background is limited ASP. Some C. Im reading the iphone programming guide, objC and cocoa fundamentals from apple dev center side by side (kinda cookoo already). so i decided to refresh some C. Found cocoa dev central by scott stevenson and went thru the simple 3 document c series and just have 1 question. Here is the link. At the end they talk about moving between slots in an array-like memory block and about arrays of strings. there are 2 C programs there that id like to understand the use, not so much the code. i get the logic, i just dont understand why they do the whole pointer to original slot, move it up by one, then back to the original slot then again add 1 etc…http://theocacao.com/document.page/234

  38. July 24, 2009

    I think they’re only trying to illustrate the point, not that you’d ever practically have to do that.

    I find, however, that I rarely need to deal with memory management concepts like that in Obj-C besides just making sure that I always balance retains and therefore don’t leak memory. You get pretty used pretty fast to the idea that you just always declare things as NSString *mystring = @”foo” (which is a pointer to an NSString object). I never really think about the fact that I’m passing around pointers and not actual objects, because you don’t really have to.

  39. mars
    July 24, 2009

    ok, thats actually my next question, retains and release in malloc. release i understand, but retain?

  40. July 24, 2009

    Retain is the conjugate of release. So, first of all, there’s never really any “malloc.” In Objective-C and cocoa, every object has an “alloc” method that handles all of the allocation for that object, and you never directly call “malloc” yourself.

    Let’s say I have an object with an instance variable called “name”. In order to set name, I have to use my object’s setter method to pass in an NSString object. It might look something like this:

    //I’m going to make my object!
    MyClass *myClassInstance = [[MyClass alloc] init];
    //I just created an object of type MyClass by telling the MyClass class to allocate some memory and initiate an instance of itself

    //Now, to set its name!
    NSString *nameString = @”Name”;
    //We use NSStrings like candy, so apple built in a convenient syntactic way to make them: @”stuff” is a function that returns a fully allocated and initiated NSString with contents “stuff”. We didn’t even need to declare a new string, we could have just passed the next object the message @”Name” but that wouldn’t have been obvious

    [myClassInstance setName:nameString];

    Now here’s where it gets interesting. You can have different methods for your class to hold onto the string you just passed it. When you declare the Name property in MyClass.h, you can declare it as “copy” or “retain” (among other, less common things). How you declare this property is important, because it decides what you do next. Well, in these two cases, you do the same thing.

    If you declared it as copy, your myClassInstance instance makes a NEW NSString object out of the NSString you pass it, nameString. It holds on to this elsewhere and you don’t need to worry about it.

    If you declared it as retain, your myClassInstance instance calls [nameString retain]. This increments an integer value called the “retain count” for that object. When you [[myobject alloc] init] an object, its retain count starts at one, meaning that the runtime won’t call [myobject dealloc] on that object next time through the run loop.

    However, you can call [myobject release], decrementing the retain count, and once the retain count hits zero, the object will be intelligently dealloc’d next time through the run loop.

    So, in order to avoid memory leaks, the next thing we do is call

    [nameString release];

    In the first situation, the retain count goes from 1 to 0, meaning that the object will then be intelligently dealloc’d sometime soon. This is ok, because myClassInstance made a copy of the string and we don’t need the original anymore.

    Similarly, in the second situation, the retain count goes from 2 to 1 (remember, myClassInstance retained it when we set the name property), meaning that when myClassInstance is done with it, the retain count will go to 0 and the memory will be freed.

    NOTE: When does myClassInstance release this thing?! Every object has a dealloc method, and you need to make sure to call

    [ivar release];

    in that method for every instance variable you’ve defined for the object. If you look at example code with custom objects, you’ll always see this (or the code has memory leaks, which is bad).

    Hopefully that makes more sense now, but I’m by no means an expert and I may have gotten some of that wrong. I STRONGLY recommend that you go to http://www.stanford.edu/class/cs193p/cgi-bin/index.php watch the videos and do the homework. I strongly recommend also that you download all the materials FAST, as that website will be erased in prep for next semester’s class.

  41. mars
    July 24, 2009

    i downlaoded it all, but im also going thru the app docs and this cocoa cause i wanted to refresh some C and cocoadevcentral has some C and some cocoa and some objC. ok, let me see if i get the essence from this with an example i found in apple dev objC example using views.

    1. i create a UIWindow object and alloc it.
    2. i create a red square and then a UIView object and alloc/init with that red square
    3. i create a blue square just the same as above
    4. i add the previous 2 subviews to the main UIWindow created as the parent view
    5. then i release the red and blue UIView to avoid the extra retain count on each of them?

    This means those red and blue views have been placed inside the other object UIWindow, so they no longer need to existe by themselves? Basically there is a red and blue square objects inside the UIWindow allocated memory space and a red/blue square objects occupying their separate allocated memory space elsewhere, so the original ones can be discarded leaving their instances inside the UIWindow object?

  42. July 24, 2009

    1. rather, you [[UIWindow alloc] init], which IS creating a UI window object.
    2 – 4. In reality, what you’re probably doing is subclassing UIView and editing its – drawrect method to draw the red square. Then you’re adding the instance of your subclass to the window with
    [myWindow addSubView:myRedSquareView]
    but yeah.
    5. Right, because you’re either using the same object and its retain count is already upped by one, or you’ve copied it and you don’t need the original anymore.

    Yes, your understanding is more or less correct at this point. Perhaps an NSString was a bad example object to use because NSStrings are autoreleased (if there’s nothing still using them at the end of the run loop, they’re dealloc’d automatically) but you can still explicitly manage them, which I usually find is good for the mind.

  43. mars
    July 24, 2009

    so when i create the uiwindow object, its count=1.
    then the redsquare, its count=1
    then the redview with redsquare inside, redview=1
    then the bluview with blusquare inside, bluview=1
    then when i add redview to uiwindow object, redview=2?
    same with blue, when i add it to uiwinobject, bluview=2?

  44. July 24, 2009

    Correct, which is why you then [redview release]; and [blueview release];

    That will bring the retain counts both to 1, which is good, since the window is still using them. Unless [window addSubView:redview/blueview]; makes copies of them, in which case it didn’t retain them and the retain counts both go to zero, removing them, which is ok since thie window is using a different copy.

  45. mars
    July 24, 2009

    Thx! One more thing, whats the best practice for db in iphone? I wanna create an app that reads strings from a database, simple database with 2 fields, nothing cmplex. or should i use a dictionary or something instead for memory purposes?

  46. July 24, 2009

    Actually, you were right the first time. Your storage options on-phone (ignoring the internet) are .plist files and sqlight. Plists are super ultra easy – basically, objects can have methods built in to persist to disk, that is, save themselves as flat files. It basically means you can save an object for later and wake it up when you need it, like after app relaunch. It’s super convenient since many objects (dictionaries, for one) have this method built in and it’s literally one message to save it and one to read it back in.

    The problem with plists is that it’s all or nothing – if you save a dictionary to a plist and want to read data from it again, you have to load the whole thing back in, which is bad if you’re storing a lot of data. Say I have a bunch of images, I wouldn’t want to save them in Plists (even though I could) because to read one would mean loading ALL of them back into memory (and with something like an image, that’s not always even technically possible).

    Sqlight is the harder, but more memory-rewarding way to do things. If you have a bigass long list of strings, like 10k entries long, then it will pay highly to use sqlight. If you have, say, a couple of preferences, then you should be fine (in fact, NSUserDefaults exists for this exact reason, look it up in the documentation).

  47. mars
    July 25, 2009

    im going thru the stanford class material and i cant even get past assignment 1, where im asked to create a command line tool displaying the home directory path info, process info, bookmark and introspection info. im actually bogged down at the very first one. i have this:
    NSLog(@”Hello, World!”);
    NSString*path = @”~”;
    NSLog(@”%@”, path);
    but i just get hello world and in the next line the ~

  48. mars
    July 25, 2009

    nevermind, figured out the problem. yes basically that was correct, but then i had to use the NSArray components to get the components and then cycle thru them.

  49. mars
    July 26, 2009

    alex, i just ran into this code in the API doc help of xcode since im going thru assignment 1b from the stanford material:

    When an entry is removed from a mutable dictionary, the key and value objects that make up the entry receive release messages. If there are no further references to the objects, they’re deallocated. Note that if your program keeps a reference to such an object, the reference will become invalid unless you remember to send the object a retain message before it’s removed from the dictionary. For example, the third statement below would result in a runtime error if anObject was not retained before it was removed:

    id anObject = [[aDictionary objectForKey:theKey] retain];

    [aDictionary removeObjectForKey:theKey];
    [anObject someMessage];

    I guess its an example of retain/release from reference count. the anObject is created and assigned a key from a dictionary. the object is retained. then the key is removed from the dictionary. then the object is sent a message.

    is this correct?

Leave a Reply

Your email address will not be published. Required fields are marked *