Stuck on Page 148 How to Print from Enum, Typedef Constants?


#1

Can someone explain to me how to create the enum code to run and print on page 148-149 from chapter 22?
I couldn’t get it to print. I don’t understand why the setSpeed returns a void, how will we be able to print out the constant if setSpeed method returns a void?

Instead I used a non-enum way to print it. Please help. Thanks.

main.m
________
#import <Foundation/Foundation.h>
#import "Blender.h"

int main(int argc, const char * argv[])
{

    @autoreleasepool {
        NSLog(@"\u03c0 is %f", M_PI);
        NSLog(@"%d is larger", MAX(10,12));
        
        NSLocale *here = [NSLocale currentLocale];
        NSString *currency = [here objectForKey:NSLocaleCurrencyCode];
        NSLog(@"Money is %@", currency);
        
        Blender *JambaBlender = [[Blender alloc] init];
        
        
        int rangeLow = 1;
        int rangeHigh = 5;
        int num = arc4random() % (rangeHigh-rangeLow+1) + rangeLow;
        //int num = SSRandomIntBetween(1 , 5) returns same number everytime
        //int num  = rand() % 5; incorrectly returns same number everytime
        NSLog(@"%d-%@ is the blender speed.", num, [JambaBlender setSpeed:num]);
               
    }
    return 0;
}
blender.h
_________
#import <Foundation/Foundation.h>

enum BlenderSpeed{
    Stir = 0,
    Chop = 2,
    Liquify = 3,
    Pulse = 4,
    Crush = 5
};

@interface Blender: NSObject
{
    //Speed must be one of the five speeds;
    enum BlenderSpeed speed;
}

//SetSpeed: expects one of the five speeds
-(NSString *)setSpeed:(int)x;


//Book's Way to SetSpeed: expects one of the five speeds
//- (void)setSpeed:(enum BlenderSpeed)x;


@end
blender.m
_____________

#import "Blender.h"


@implementation Blender


-(NSString *)setSpeed:(int)x
{
    if (x == 1) {
        return @"Stir";
    } else if (x == 2) {
        return @"Chop";
    } else if (x == 3) {
        return @"Liquify";
    } else if (x == 4) {
        return @"Pulse";
    } else if (x == 5) {
        return @"Crush";
    }
}


//Book's Way to SetSpeed: expects one of the five speeds
//- (void)setSpeed:(enum BlenderSpeed)x
//{

//}

@end

#2

You are quite intrepid, but you should follow the standards. You should also read the The Objective-C Programming Language guide.

This is a nonstandard way of declaring a setter in Objective-C:

-(NSString *)setSpeed:(int)x;

This is the standard way of declaring a setter and a getter for an attribute named speed:

-(void)setSpeed:(enum BlenderSpeed)x;
-(enum BlenderSpeed)speed;

Also, override the description method to return the currently set speed of the blender

- (NSString *)description;

Method definitions:

@implementation Blender

-(void)setSpeed:(enum BlenderSpeed)x
{
   // complete the rest ... of assert
   assert (x == Stir || x == Chop || x == ...);
   speed = x;
}

-(enum BlenderSpeed)speed
{
    return speed;
}

- (NSString *)description
{
    NSString *str = nil;
    switch ([self speed])
    {
          default:
                 str = @"Undefined";
                 break;
          case Stir:
                 str =  @"Stir";
                 break;
          case Chop:
                 str = @"Chop";
                 break;
          ...
    }
    return [NSString stringWithFormat:@"BlenderSpeed: %@", str];
}
@end

Printing blender’s speed:

...
Blender *blender = [[Blender alloc] init];
[blender setSpeed:Chop];
NSLog (@"%@", blender);
...

#3

Thank you ibex. The code works now. I’m not really that bold and creative, just stupid and a neophyte to coding.

Can you explain how the code can use (void)setSpeed:(enum BlenderSpeed)x when it returns void?
Is it because the part (enum BlenderSpeed)x is really using the method (enum BlenderSpeed)speed to return the speed, so it is returning the speed value
via the (enum BlenderSpeed)x portion?

I can’t seem to follow which part calls which first?
I know you also provided an answer to my other question too with the need to add the (NSString *)description method.
How can I tell in which situations would I need this description method?
I want to really learn this by understanding how it works. How does the whole code flow? So which method is called first and then which and then how does the enum plays a part?

Sorry if these questions are stupid and obvious. Thanks for responding and helping out a newbie. :slight_smile:


#4

A method does not have to return a value in order for it (the method) to be used.

Setter methods, by convention, don’t return any value; that’s why they are declared like this:

- (void)setFoo:(some_type)v;

They are meant to cause some change, usually in the object they are invoked on.

That’s why the Blender’s setSpeed method is defined like this:

@implementation Blender

// Set the new speed
-(void)setSpeed:(enum BlenderSpeed)newSpeed
{
   // complete the rest ... of assert
   assert (x == Stir || x == Chop || x == ...);
   speed = newSpeed;
}
@end

To use a setter method, you invoke it on its object:

Blender *B1 = [[Blender alloc] init];
Blender *B2 = [[Blender alloc] init];
[B1 setSpeed:Chop];
[B2 setSpeed:Stir];
...
if ([B1 speed] !== [B2 speed])
{
     [B1 setSpeed:[B2 speed]];
}

But these are all explained in the book, including the use of description method.

To reinforce your understanding of the basic concepts, you should read the following guides in Xcode’s Organizer’s Documentation:

  • Learning Objective-C: A Primer
  • The Objective-C Programming Language

#5

Thanks ibex.