Tuesday, October 27, 2009

Why does 'cd' work differently for drives and paths?

This has been a frustrating pet peeve of mine for a while.

When I hope my Windows command line, it starts me out on a network drive, specifically "H:", which of course I rarely have a need to be in. My first instinct, which is always wrong, is to type:
  • H:>cd c:
in an attempt to get to "C:" drive. I may even have include a path like this: "c:\path\to\my\folder".

This always fails, because what Windows expects you to do is this:
  • H:>c:
which will nicely give you the C:> prompt from which you can then navigate.

Why? Is there a way around this? My main problem is that I don't use the Windows command line that often, so I forget the nuance of switching between drives as opposed to switching paths.

Friday, October 23, 2009

Automated Zipping in Xcode

I like to automate everything. I'm a firm believer in the "one-click, build-all, distribute-all" type of solution.

Per Apple's recommendations, after you generate your .app file, you need to compress it by right clicking on the file and selecting, conveniently enough, "Compress." Not exactly automated. After doing some searching, I found this little gem:
  • ditto -c -k --sequesterRsrc --keepParent "$PRODUCT_NAME.app" "$PRODUCT_NAME$revnum.zip"
Which, when I ran it on the command line (with $PRODUCT_NAME appropriately filled in), generated a perfectly acceptable zip file that I could submit to itunesconnect. But when I put the same command in my post-build script, I got an invalid zip file that itunesconnect would not accept. Ouch! The two files had different sizes; I'm really not sure what could have caused the problem (something in the bash shell, maybe?)

Luckily, I found an alternate gem:
  • zip -r -T -y "$PRODUCT_NAME$revnum.zip" "$PRODUCT_NAME.app"
Now, I originally tried using zip before and it didn't work. the '-y' option is the key, as it preserves the symlinks. I won't pretend to understand exactly why that makes the difference, but the script does indeed now generate a valid zip file. Fantastic!

Tuesday, October 20, 2009

I forget where I found this, but it's been useful to me:

Error:
"svn: Can't move '.svn/tmp/entries' to '.svn/entries': Operation not permitted" (in Terminal, when trying to check-in or update the repository)

Fix:
Use 'chflags -R nouchg .' on the command line. Note '.' at the end. It is not optional.

Here is what the options do:

-R: "Change the file flags for the file hierarchies rooted in the files instead of just the files themselves."

'nouchg' is the negated form of: "uchg, uchange, uimmutable set the user immutable flag (owner or super-user only)"

Friday, October 9, 2009

While trying to add UIWebView. Have the IBOutlet connected and it compiles, but I'm missing something:
2009-10-09 16:04:38.035 Green Splash Theme[2529:20b] *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[ setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key myWebView.'
What am I missing?

Tried:

  1. Link the UIWebView's delegate to the file owner;
  2. Make the UIViewController a as well.
  3. Ah-ha! The class that was controlling the UIWebView was a sub-class of another class. In my call to instantiate my new UIWebView class, I used the parent class instead. Changing it to the more specific class made it work.
That is, I had:
vcCtrl = [[ParentDialog alloc] initWithNibName:@"WebDialog" bundle:nil];

when it should have been:
vcCtrl = [[WebDialog alloc] initWithNibName:@"WebDialog" bundle:nil];

where WebDialog inherited from ParentDialog. Inheritance is a tricky little bugger if you're not paying attention.

View Outlet Not Set Error

Here's another interesting one:
2009-10-09 10:20:36.845 MyApp[329:20b] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[UIViewController _loadViewFromNibNamed:bundle:] loaded the "MayAppView" nib but the view outlet was not set.'
Make sure that you connect the View in the nib file to the file's owner. (I'll try to explain it better at another time.)

Thursday, October 8, 2009

Unrecognized Selector Error

In case you get this:

2009-10-08 17:26:29.125 MyApp[5487:20b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[HowToPlayViewController setDelegate:]: unrecognized selector sent to instance 0xd3dae0'

Remember to synthesize the property in question (in this case 'Delegate', which would require a 'setDelegate' selector if I were to hand-code the property). I like Objective-C overall so far, but there are a few quirks that bug me. The property + synthesize issue is one of them. You don't have to call @synthesize if you make the getter/setters yourself, but failure to do either thing should generate an error, not a warning like it does during compilation. I totally missed it.

Moving onto the Interface Builder

My student has been sick all week, so I haven't had an opportunity to continue on with lessons, which is great, since I didn't finish writing up all that he and I had talked about last time.

This time we'll talk about the Interface Builder (IB). The IB is an entirely separate application from Xcode and is used to visually create the user interface (whereas you would normally have to do it through code). The IB creates the .nib/.xib files mentioned last time and though IB is a separate app, you typically end up launching it by clicking on the .xib files that are in your Xcode project. In the case of a simple project, it's typically called MainWindow.xib.

Once in IB, you have four primary windows to worry about (sometimes more).

1) The nib list window -- this contains a summary of all the components of your UI.
2) Inspector window -- this contains the details of the particular component you're looking at. It has four tabs on it.
3) Library window -- this is were all the UI components come from.
4) The user interface window -- this is where you drag items from the library onto.

For the moment, I'm not going to go into intimate details. Each item will take a bit to get into. Try this, however. Drag some Library items (like buttons, labels, etc.) to the UI window. In particular, add a UIImageView item. Initially, it's a blank rectangle. But if you highlight the view and go into the Inspector window -> Attributes, you should see a drop down box called: Image.


You may not have anything listed in the drop down. In that case, return to Xcode and add a png or jpg file to your project (the Resources group is a nice place to put it), then relaunch IB. It should show up then. Select it from the list and you should then see the image in the UI window. You may need to play around with other attributes and the sizing of the window to get the image to look right.

If you go back to Xcode and run the app (assuming you created a basic Windows-based app), then image should show up. Fantastic!

Getting an image to display is trivial, as you can see. Adding buttons and labels is also quick and easy. However, getting them to respond to a user's touch is a different beast altogether. We will need to talk about IBOutlets and IBActions at that point, and those topics are for another day.