07.11
Recently I’ve been going trough the Stanford iPhone programming lessons (http://www.stanford.edu/class/cs193p/).
The lessons are great for people that have some experience in programming (C/C++) and want to learn Objective-C and how to program for the iPhone. The video lessons are available on iTunes U and the materials are posted on the class website.
For the first assignment (1A) you had to make a simple iPhone application interface in XCode’s Interface Builder. The second assignment of the first lesson (1B) was a little bit more complicated. It includes making a simple command line tool in Objective-C.
The second lecture’s assignment (2A) was based on the assignment 1B and that was also the conclusion of the command line tool.
After some trial and error, I successfully completed the assignment
Here is the code for the file “WhatATool.m”:
#import #import "PolygonShape.h" void PrintPathInfo() { NSLog(@"---------- SECTION 1 ----------"); NSString *path = @"~"; path = [path stringByExpandingTildeInPath]; NSLog(@"My home folder is at '%@'", path); NSArray *pathComponents = [path pathComponents]; NSLog(@"Path components:"); for (NSString *pathComponent in pathComponents) { NSLog(@"%@", pathComponent); } } void PrintProcessInfo() { NSLog(@"---------- SECTION 2 ----------"); NSLog(@"Process Name: '%@' Process ID: '%d'", [[NSProcessInfo processInfo] processName], [[NSProcessInfo processInfo] processIdentifier]); } void PrintBookmarkInfo() { NSLog(@"---------- SECTION 3 ----------"); NSMutableDictionary *bookmarks = [NSMutableDictionary dictionaryWithCapacity:5]; [bookmarks setObject:[NSURL URLWithString:@"http://www.stanford.edu"] forKey:@"Stanford University"]; [bookmarks setObject:[NSURL URLWithString:@"http://www.apple.com"] forKey:@"Apple"]; [bookmarks setObject:[NSURL URLWithString:@"http://cs193p.stanford.edu"] forKey:@"CS193P"]; [bookmarks setObject:[NSURL URLWithString:@"http://itunes.stanford.edu"] forKey:@"Stanford on iTunes U"]; [bookmarks setObject:[NSURL URLWithString:@"http://stanfordshop.com"] forKey:@"Stanford Mall"]; for (id key in bookmarks) { if ([key hasPrefix:@"Stanford"]) { NSLog(@"key: '%@' URL: '%@'", key, [bookmarks objectForKey:key]); } } } void PrintIntrospectionInfo() { NSLog(@"---------- SECTION 4 ----------"); NSMutableArray *warehouse = [NSMutableArray arrayWithCapacity:3]; [warehouse addObject:@"A STRING"]; [warehouse addObject:[NSURL URLWithString:@"http://www.apple.com"]]; [warehouse addObject:[NSProcessInfo processInfo]]; for (id item in warehouse) { NSLog(@"Class name: %@", [item className]); NSLog(@"Is Member of NSString: %@", ([item isMemberOfClass:[NSString class]] ? @"YES" : @"NO")); NSLog(@"Is Kind of NSString: %@", ([item isKindOfClass:[NSString class]] ? @"YES" : @"NO")); if ([item respondsToSelector:@selector(lowercaseString)]) { NSLog(@"Responds to lowercaseString: YES"); NSLog(@"lowercaseString is: %@", [item lowercaseString]); } else { NSLog(@"Responds to lowercaseString: NO"); } NSLog(@"-------------------"); } } void PrintPolygonInfo() { NSMutableArray *polygons = nil; polygons = [[NSMutableArray alloc] init]; PolygonShape *poly1 = [[PolygonShape alloc] init]; [poly1 initWithNumberOfSides:4 minimumNumberOfSides:3 maximumNumberOfSides:7]; [polygons addObject:poly1]; NSLog(@"Polygon 1 description: %@", [poly1 description]); PolygonShape *poly2 = [[PolygonShape alloc] init]; [poly2 initWithNumberOfSides:6 minimumNumberOfSides:5 maximumNumberOfSides:9]; [polygons addObject:poly2]; NSLog(@"Polygon 2 description: %@", [poly2 description]); PolygonShape *poly3 = [[PolygonShape alloc] init]; [poly3 initWithNumberOfSides:12 minimumNumberOfSides:9 maximumNumberOfSides:12]; [polygons addObject:poly3]; NSLog(@"Polygon 3 description: %@", [poly3 description]); for (id polygon in polygons) { [polygon setNumberOfSides:10]; } [poly1 release]; [poly2 release]; [poly3 release]; [polygons release]; } int main (int argc, const char * argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; PrintPathInfo(); PrintProcessInfo(); PrintBookmarkInfo(); PrintIntrospectionInfo(); PrintPolygonInfo(); [pool release]; return 0; }
“PolygonShape.h”:
#import @interface PolygonShape : NSObject { int numberOfSides; int minimumNumberOfSides; int maximumNumberOfSides; } @property int numberOfSides; @property int minimumNumberOfSides; @property int maximumNumberOfSides; @property (readonly) float angleInDegrees; @property (readonly) float angleInRadians; @property (readonly) NSString *name; @property (readonly) NSString *description; - (id)initWithNumberOfSides:(int)sides minimumNumberOfSides:(int)minSides maximumNumberOfSides:(int)maxSides; - (id)init; - (void)dealloc; @end
“PolygonShape.m”:
#import "PolygonShape.h" @implementation PolygonShape @synthesize numberOfSides; @synthesize minimumNumberOfSides; @synthesize maximumNumberOfSides; - (void)dealloc { NSLog(@"Deallocating..."); [super dealloc]; } - (id)initWithNumberOfSides:(int)sides minimumNumberOfSides:(int)min maximumNumberOfSides:(int)max { if (self = [super init]) { [self setMinimumNumberOfSides:min]; [self setMaximumNumberOfSides:max]; [self setNumberOfSides:sides]; } return self; } - (id)init { return [self initWithNumberOfSides:5 minimumNumberOfSides:3 maximumNumberOfSides:10]; } - (void)setNumberOfSides:(int)aValue { if (aValue < minimumNumberOfSides) { NSLog(@"Invalid number of sides: %d is less than the minimum of %d allowed.", aValue, minimumNumberOfSides); } else if (aValue > maximumNumberOfSides) { NSLog(@"Invalid number of sides: %d is greater than the maximum of %d allowed.", aValue, maximumNumberOfSides); } else { numberOfSides = aValue; } } - (void)setMinimumNumberOfSides:(int)aValue { if (aValue < 3) { NSLog(@"Invalid minimum number of sides: %d is less that the minimum of 3 allowed.", aValue); } else { minimumNumberOfSides = aValue; } } - (void)setMaximumNumberOfSides:(int)aValue { if (aValue > 12) { NSLog(@"Invalid maximum number of sides: %d is greater that the maxmimum of 12 allowed.", aValue); } else { maximumNumberOfSides = aValue; } } - (float)angleInDegrees { return (180 * (numberOfSides - 2) / numberOfSides); } - (float)angleInRadians { return (M_PI * (numberOfSides - 2) / numberOfSides); } - (NSString *)name { NSDictionary *names = [NSDictionary dictionaryWithObjectsAndKeys:@"Triangle", [NSNumber numberWithInt:3], @"Square", [NSNumber numberWithInt:4], @"Pentagon", [NSNumber numberWithInt:5], @"Hexagon", [NSNumber numberWithInt:6], @"Heptagon", [NSNumber numberWithInt:7], @"Octagon", [NSNumber numberWithInt:8], @"Nonagon", [NSNumber numberWithInt:9], @"Decagon", [NSNumber numberWithInt:10], @"Hendecagon", [NSNumber numberWithInt:11], @"Dodecagon", [NSNumber numberWithInt:12], nil]; return [names objectForKey:[NSNumber numberWithInt:[self numberOfSides]]]; } - (NSString *)description { return [NSString stringWithFormat:@"Hello I am a %d-sided polygon (aka a %@) with angles of %f degrees (%f radians).", [self numberOfSides], [self name], [self angleInDegrees], [self angleInRadians]]; } @end
So this is it. The entire first assignment. If you find it helpful, please leave a comment to say thanks, or if you think you can do better leave a comment too
The entire XCode project for download: WhatATool
Hey can you have a look at my code? i can’t figure out why it is not running correctly..?
twisted travels @ gmail . com
all one word
hey
Have you checked my code, line by line?
I had some trouble too and then I checked the connections in Interface Builder.
Some were missing and I connected them and that was it.
This was helpful – thanks! I got most of it, but it was good to have a sanity check.
I used a big-ass switch statement instead of the dictionary to return the shape name. The dictionary was a good idea.
I didn’t declare description or dealloc in my header file and it still worked.
I forgot to release my polygon array, so I wasn’t seeing any dealloc’s until I saw your code and changed it.
When you initialise the polygonShape instances, you call init every time (in the same line as alloc). You can call initWithNumberOfSides directly instead of init first.
Thanks again for posting.
Thanks
Will soon post the entire HelloPoly project. Just finishing it.
About the declaration in the header… You must declare something if you want to use it before you implement it, so the compiler knows it exists.
Those two declarations aren’t necessary but in case I’d implement the functions in a different order the code would still work.
About the init. Yes, you are right
I will change that in the HelloPoly app
Thanks
Got mine working, some simple errors, nothing like a break.
In reply to the user above… a switch/case was actually a good idea, if this was a large program the switch/case would be more efficient, then declaring an initialising the array everytime the name method was called.
I decided to change my original code (below) to a case/switch statement.
-(NSString *)name
{
NSMutableArray *name = [NSMutableArray arrayWithCapacity: 13];
[name addObject:@"nil"]; //0
[name addObject:@"Henagon"]; //1
[name addObject:@"Digon"]; //2
[name addObject:@"Triangle"]; //3
[name addObject:@"Quadrilateral"]; //4
[name addObject:@"Pentagon"]; //5
[name addObject:@"Hexagon"]; //6
[name addObject:@"Heptagon"]; //7
[name addObject:@"Octagon"]; //8
[name addObject:@"Enneagon"]; //9
[name addObject:@"Decagon"]; //10
[name addObject:@"Hendecagon"]; //11
[name addObject:@"Dodecagon"]; //12
return [name objectAtIndex: self.numberOfSides];
Hi Jernej,
Good to hear you’ll post the HelloPoly app too. I’m working through mine right now. Got the first part working, but I’m still working on drawing the shapes.
im going thru the assigment mself and im stuck with the 2b walkthrough. i dl a zip off the net from someone else but it was a very different app. So i wanna stick to the assignment. Ive gotten up to creating the controller in IB, connecting outlets, targets and actions, imported the polygonshape class files h/m but when i try to build it i get an error saying the its undeclared minimum number of sides when i try to set it to 3, and so on for the other variables. im doing it in the appdelegate which is where i think it should be. i can send u my code if you like.
Thanks for the help. I managed to keep some of my hair!
Also anybody care to comment on doing the init this way?
I figure if I type ’staple’ code long enough, I’ll be able to remember something
- (id)init {
if (self = [super init]) {
[self initWithNumberOfSides: 5 minimumNumberOfSides:3 maximumNumberOfSides:10];
}
return self;
}
Hey, nice work! Hope you post more assignments soon. Anyway, Xcode is telling me that I haven’t declared ‘lt’ and ‘gt’ :S what should I do?
Sorry nvm, noticed those are > and < lol, thanks anyway!
Holla Jernej,
I can’t thank you enough for posting this. My coding expertise in any flavor of C is, to put it kindly, very old and tired. Your post was like a shining beacon helping me cross some very troubled waters.
I’m currently taking the 2010 version of the course and using v3.2.1 of XCode.
Maybe that is why three lines in WhatATool.m (PrintPolygonInfo) generate an error.
you have:
NSLog(@”Polygon 1 description: %@”, [poly1 description]);
It chokes on the word description
What works is:
NSLog(@”Polygon 1 description: %@”, [poly1.description]); // note the added .
The lt and gt thing got me too until I realized it was likely WordPress was likely just playing cute. Thank goodness my WordPress chops are fresher than my Obj-C chops. lol
Again many thanks. Hope your app is proving successful and I wish you would do more of these.
Thank you
I’m currently also using the exact version of XCode and it’s working normally.
Maybe you made a simple typo? (those can be a pain in the butt, trust me)
The syntax should be:
NSLog(@”Polygon 1 description: %@”, [poly1 description]); // Without the dot
or
NSLog(@”Polygon 1 description: %@”, poly1.description); // Without the square brackets
I’d do more, but I read on the lecture website that we shouldn’t post completed assignments on the web, so I will respect that.
But if you need help, feel free to contact me
Hrmmm…
You are probably right. I suspect I subbed “()”s for that set of brackets. OTOH I’m kind of happy I came up with another way of doing it all by my lil’old self.
Re: posting assignments: I can certainly see their point. After all they are really in class and we are just doodling around with iTunes U.
But to counter the argument we have no TAs to turn to when we get totally out in the weeds. For example I now know far too much about radians than I ever wished to. Far, far too much – lol.
It’s not like one can’t find the completed assignments on the internet. But they are often times just zips of code that explain nothing, unlike what you did here.
Maybe consider posting a walkthrough after the assignments are due at Stanford. That would answer their concerns while saving people such as I (who has far too little hair) from yanking out what remains.
Finally, on an unrelated issue, I succeeded in getting the Knuth Shuffle algorithm, for “n” number of objects, up and running in XCode. Sure it may be just in the console for now but at least now I have a major code element I’ll need for a couple of projects I want to do.
So by all means takes some credit and yay me!
keep em’flying!
Hey dude,
I was wondering if you have the assigments files saved in pdf, the ones that you could get on the website, beacuse this semester they changed the content of the page, if you have them is there any chance to send them to me?
Thanks in advanced
I already got them, thanks anyway
Hi, thanks for posting this code. I was going crazy. You wrote that you weren’t going to post anything else but to contact you if we were interested. I really am, so I’d be grateful I you wrote to me. Thanks in advance.