4 Warnings, can't figure it out


#1

Hi guys,

I am working through the 2nd Chapter code for “Possessions” and I am getting 4 warnings and am not able to compile the code. I am including the Possession.h and Possession.m files here. I have commented out (in CAPS) the 4 warnings I am getting on the Possession.m file. Any help is appreciated…

Possession.h

#import <Foundation/Foundation.h>


@interface Possession : NSObject
{
    NSString *possessionName;
    NSString *serialNumber;
    int valueInDollars;
    NSDate *dateCreated;
}

@property (nonatomic, copy) NSString *possessionName;
@property (nonatomic, copy) NSString *serialNumber;
@property (nonatomic) int valueInDollars;
@property (nonatomic, readonly) NSDate *dateCreated;

+ (id) randomPossession;

- (id)initWithPossessionName: (NSString *)name
              valueInDollars: (int)value
                serialNumber: (NSString *)sNumber;

-(id)initWithPossessionName:(NSString *)name;


@end

and here is the Possession.m file with the warnings…

#import "Possession.h"

@implementation Possession  //INCOMPLETE IMPLEMENTATION

- (id)init

{
    return [self initWithPossessionName:@"Possession"
                         valueInDollars:0
                           serialNumber:@""];
}

@synthesize possessionName, serialNumber, valueInDollars, dateCreated;


- (id)initWithPossessionName:(NSString *)name
valueInDollars:(int)value
serialNumber:(NSString *)sNumber

{
    // Call the superclass's designated initializer
    self =[super init];
    
    // Did the supeclass's designated initializer fail?
    if (!self) 
        return nil;
        
    
    
    
    // Give the instance variable initial values
    [self setPossessionName:name];
    [self setSerialNumber:sNumber];
    [self setValueInDollars:value];
    dateCreated = [[NSDate alloc] init];
    
    //Return the address of the newly initialized object
    
    return self;
                            
}

- (NSString *) description
{
    NSString * descriptionString =
    [[NSString alloc] initWithFormat:@"%@ (%@): Worth $%d, Recorded on %@", 
     possessionName,
     serialNumber,
     valueInDollars,
     dateCreated];
    
    return descriptionString;
}



+ (id) randomPossession

{
    // Create two arrays with a list of possible adjectives and nouns
    // Note: When using NSArray's arrayWithObjects:, you can pass as many
    // objects as you like.  At the end of that list, you put nil to
    // signifify that there are no more objects - otherwise you will crash.
    // The nil value is not added to the array, but is used by the method
    // to determine the end of the list.
    
    NSArray *randomAdjectiveList = [NSArray arrayWithObjects:@"Fluffy",
                                    @"Rusty",
                                    @"Shiny", nil];
    NSArray *randomNounList = [NSArray arrayWithObjects:@"Bear",
                               @"Spork",
                               @"Mac", nil];
    
    // Get the index of a random adjective/noun from the lists
    // Note: The % operator, called the modulo operator, gives
    // you the remainder.  So adjectiveIndex is a random number
    // from 0 to 2 inclusive, in this case.
    
    int adjectiveIndex =random() % [randomAdjectiveList count];  //IMPLICIT CONVERSION LOSES INTEGER PRECISION: 'UNSIGNED LONG' TO 'INT'
    int nounIndex = random() % [randomNounList count];           //IMPLICIT CONVERSION LOSES INTEGER PRECISION: 'UNSIGNED LONG' TO 'INT'    
    NSString *randomName = [NSString stringWithFormat:@"%@ %@",
                            [randomAdjectiveList objectAtIndex:adjectiveIndex],
                            [randomNounList objectAtIndex:nounIndex]];
    
    int randomValue = random() % 100;                           //IMPLICIT CONVERSION LOSES INTEGER PRECISION: 'UNSIGNED LONG' TO 'INT'    
    NSString *randomSerialNumber = [NSString stringWithFormat:@"%c%c%c%c%c",
                                    '0' + random() % 10,
                                    'A' + random() % 26,
                                    '0' + random() % 10,
                                    'A' + random() % 26,
                                    '0' + random() % 10];
    
    //Once again, ignore the memory problems with this method
    // We use "self" instead of the name of the class in class methods...
    // Keep reading to find out why
    
    Possession *newPossession =
    [[self alloc] initWithPossessionName:randomName
                          valueInDollars:randomValue
                            serialNumber:randomSerialNumber];
    return newPossession;
    
    
    
}

@end

#2
  1. It’s nicer if the @synthesize compiler command comes right after @implementation

  2. “INCOMPLETE IMPLEMENTATION” means the header file promised that specific methods would be implemented but the @implementation section did not include the promised method signatures. In this case, -initWithPossessionName: is missing; see the middle of page 38.

Incidentally, as an aside: Xcode isn’t as nice about aligning the colons (:slight_smile: in method definitions in the .m file as it is when calling them. You can get it to align them by typing an extra colon at the end of a line and then backspacing to remove it. So in Possession.m, instead of:

[code]

  • (id)initWithPossessionName:(NSString *)name
    valueInDollars:(int)value
    serialNumber:(NSString *)sNumber
    [/code]you can enter:
- (id)initWithPossessionName:(NSString *)name
              valueInDollars:(int)value//colon to force alignment, then backspace to delete the extra colon
                serialNumber:(NSString *)sNumber//same here
  1. It turns out that the random() function returns a long rather than an int. Since long values can be far larger than int values, the compiler warns of the possible loss of precision. (I say “can be”; they’re the same size on my machine, but that’s not guaranteed.) To eliminate the warning, we have two options. One is to tell the compiler “I know what I’m doing; change the long into an int”. This is done with a cast, a feature of C.

int adjectiveIndex = (int)( random() % [randomAdjectiveList count] ); int nounIndex = (int)( random() % [randomNounList count] ); int randomValue = (int)( random() % 100 ); This lets the operation proceed as normal, but uses a cast to force the final value to be an int.

That’s one solution. The other is to do as the 2nd edition does and use the rand() function instead. On the one hand this returns an int so we don’t have to mess with casting. On the other, rand() is an old function whose values aren’t as “random” as are those returned by random(). For the purposes of the demonstration app they’re fine and they let us focus on the Objective C parts of the code rather than the C parts.


#3

Thank you so much for the detailed response. I changed the @synthesize command location… In regards to:

I must have read that wrong, I had that typed in originally but then immediately after at the very end of pg 38/top of pg 39 I thought it read to overwrite this:

- (id)initWithPossessionName: (NSString *)name

{
    return [self initWithPossessionName:@"Possession"
                         valueInDollars:0
                           serialNumber:@""];
}

with this…(changing the init)

- (id)init

{
    return [self initWithPossessionName:@"Possession"
                         valueInDollars:0
                           serialNumber:@""];
}

Which is what I did. Is that not correct? Should I have included both of those in there instead?

As far as the int/long stuff goes I will mess around with that. Thanks for the tips, and also the tips on the double colons.


#4

Right; both should be included. (And even if -initWithPossessionName: was to be removed, it would need to be removed from the header file as well. Remember, the @interface serves in part as a promise that the methods will be present in the @implementation.)

After -initWithPossessionName:valueInDollars:serialNumber: is implemented and explained, the next paragraph begins:

If -initWithPossessionName:valueInDollars:serialNumber: is overwritten with just -init, then it couldn’t be invoked by the body of the init (because it no longer exists :wink:) and the app would crash saying it does not recognize the selector.


#5

Ahh ok, makes sense. Thank you again for your help. I have some C knowledge, but obj-C and OOP in general is new to me. I have the Obj-C programming guide by Steven Kochan and I have read some of it, maybe I should spend more time on that before I jump to iPhone Programming book. The Big Nerd guide jumps right into the app development which is great, but maybe I need to spend more time on the basics first.

Thanks again!


#6

You’re quite welcome!

The C background is good, especially as you get more into drawing or multimedia. I wonder, though, if Java programmers with no C (and thus no pointers) have an easier time of it than C programmers with no C++ or Java, just because of the OOP background. If you can get through the first eight or nine chapters of Kochan first (so you “get” classes, inheritance, and polymorphism), then I think the BNR book will make a lot more sense to you.

With your C background you might even be able to skip around and just hit chapters 3, 7, 8, and 9. (I don’t have the book myself; that’s just judging from the table of contents.)


#7

I’m stuck in the same part. I understood a little bit what you meant, but somehow I’m too confused about what happened in Chapter “38”- Initializer Chain…

So there are 3 different codes on that side - what does that mean exactly? Do I have to expand or owerwrite the

Code 1:

into Code 2:

-(id)initWithPossessionName:(NSString *)pName { return [self initWithPossessionName:pName valueInDollars:0 serialNumber:@""]; }

and later into Code 3:

- (id)init { return [self initWithPossessionName:@"Possession" valueInDollars:0 serialNumber:@""]; }

?

I’m still completely confused about what I’m supposed to do. If I expand the code with the second one, I get an red error (expected identifier; seems like it doesn’t want to be expanded with {…}-code), if I let the code the way it is like in Code1, I have the same problem like the thread starter (at least build succeeds… but it stops at some thread). Here my code:

Possession.h:

[code]#import <Foundation/Foundation.h>

@interface Possession : NSObject
{
NSString *possessionName;
NSString *serialNumber;
int valueInDollars;
NSDate *dateCreated;
}

@property (nonatomic, copy) NSString *possessionName;
@property (nonatomic, copy) NSString *serialNumber;
@property (nonatomic) int valueInDollars;
@property (nonatomic, readonly) NSDate *dateCreated;

  • (id) randomPossession;
  • (id)initWithPossessionName: (NSString *)pName
    valueInDollars: (int)value
    serialNumber: (NSString *)sNumber;

-(id)initWithPossessionName:(NSString )pName;
//right now put into “comment”, because otherwise, programm will not work…
/
{
return [self initWithPossessionName:pName
valueInDollars:0
serialNumber:@""]

*/

@end [/code]

Possession.m

[code]#import “Possession.h”

@implementation Possession
@synthesize possessionName, serialNumber, valueInDollars, dateCreated;

  • (id)initWithPossessionName:(NSString *)pName
    valueInDollars:(int)value
    serialNumber:(NSString *)sNumber
    {
    //Call the superclass’s designated initializer
    [super init];

    // Did the superclass’s designated initializer fail?
    if (!self)
    return nil;

    //Give the instance variables initial values
    [self setPossessionName:pName];
    [self setSerialNumber:sNumber];
    [self setValueInDollars:value];
    dateCreated = [[NSDate alloc] init];

    //Return the address of the newly initialized object
    return self;
    }

  • (NSString *)description {
    NSString *descriptionString = [[NSString alloc] initWithFormat:@"%@ (%@): Worth $%d, recorded on %@",
    possessionName,
    serialNumber,
    valueInDollars,
    dateCreated];
    return descriptionString;
    }

@end
[/code]

Sorry about my dumb question and thanks in advance! :slight_smile: