Challenge gives portfolio value of 0?


#1

Not sure why I can’t get this working?
I created what I thought was a correct solution pretty quickly but although it compiles and runs, my array of “stocks” doesn’t seem to get populated with anything!
I’ve looked at some of the other solutions and the reported working ones are very similar to mine. I am getting a warning “unused variable” which I’m certain is causing the issue but I have no idea why it is unused.
Any help would be greatly appreciated, I’m beginning to think my version of X-Code is bad :slight_smile:

//  Portfolio.h
//  Chapter17_Challenge_Stocks

#import <Foundation/Foundation.h>
@class StockHolding;
@interface Portfolio : NSObject
{
    NSMutableArray *stocksInPortfolio;
}
- (void) addStockToPortfolio:(StockHolding*) stock;
- (float) portfolioValue;
@end
//  Portfolio.m
//  Chapter17_Challenge_Stocks

#import "Portfolio.h"
#import "StockHolding.h"
@implementation Portfolio
- (void) addStockToPortfolio:(StockHolding*) stock
{
    if (!stocksInPortfolio){   
           NSMutableArray *stocksInPortfolio = [[NSMutableArray alloc]init];  // This is giving the warning "Unused variable 'stocksInPortfolio"
    [stocksInPortfolio addObject:stock];
 }
- (float) portfolioValue
{
    float value = 0;
    for (StockHolding *s in stocksInPortfolio) {
        value += [s valueInDollars];
    }
    return value;
}
@end
//  main.m
//  Chapter17_Challenge_Stocks

#import <Foundation/Foundation.h>
#import "StockHolding.h"
#import "ForeignStockHolding.h"
#import "Portfolio.h"
int main(int argc, const char * argv[])
{
    @autoreleasepool {
        StockHolding *stock1 = [[StockHolding alloc]init];
        StockHolding *stock2 = [[StockHolding alloc]init];
        StockHolding *stock3 = [[StockHolding alloc]init];
        ForeignStockHolding *fstock1 = [[ForeignStockHolding alloc]init];
        ForeignStockHolding *fstock2 = [[ForeignStockHolding alloc]init];
        
        [stock1 setPurchaseSharePrice:2.30];
        [stock1 setCurrentSharePrice:4.50];
        [stock1 setNumberOfShares:40];
        [stock2 setPurchaseSharePrice:12.19];
        [stock2 setCurrentSharePrice:10.56];
        [stock2 setNumberOfShares:90];
        [stock3 setPurchaseSharePrice:45.10];
        [stock3 setCurrentSharePrice:49.51];
        [stock3 setNumberOfShares:210];
        [fstock1 setPurchaseSharePrice:1.50];
        [fstock1 setCurrentSharePrice:9.75];
        [fstock1 setNumberOfShares:55];
        [fstock1 setConversionRate:1.5];
        [fstock2 setPurchaseSharePrice:3.25];
        [fstock2 setCurrentSharePrice:5.90];
        [fstock2 setNumberOfShares:75];
        [fstock2 setConversionRate:0.75];
        
        NSArray *myArray = [[NSArray alloc] initWithObjects:stock1,stock2,stock3,fstock1,fstock2,nil];
        for (ForeignStockHolding *h in myArray){
            NSLog(@"Stock cost %.2f, and is worth %.2f, which is a profit of %.2f",
                  [h costInDollars], [h valueInDollars], ([h valueInDollars] - [h costInDollars])); 
        }
        
    Portfolio *portfolio = [[Portfolio alloc] init];
    [portfolio addStockToPortfolio:stock1];
    [portfolio addStockToPortfolio:stock2];
    [portfolio addStockToPortfolio:stock3];
    
    NSLog(@"Value is %.2f",[portfolio portfolioValue]);
    }
    return 0;
}

#2

yes, this code has your problem:

{ if (!stocksInPortfolio){ NSMutableArray *stocksInPortfolio = [[NSMutableArray alloc]init]; // This is giving the warning "Unused variable 'stocksInPortfolio" [stocksInPortfolio addObject:stock]; }

there are a couple issues here that are masking what’s going on :slight_smile:

#1: you are either missing a closing }, or you have an extra opening { - either way, your if statement as-pasted is kind of broken - it doesn’t know where to begin and where to end. this could create a scope issue (depending on your goal), but i’m guessing this is just a copy-paste error, because your compiler would break otherwise I believe… either way, this may be hiding the true issue, which I bet is #2 below:

#2: your NSMutableArray * code is actually creating a new local variable of the same name - this is the reason for your compiler error, because local variables only exist within the scope in which they are created. in other words: it is a TOTALLY different variable than your instance variable of the same name (stocksInPortfolio).

note: if both your alloc-init code and your addObject: code were in the same scope, your compiler would throw different (and more helpful) error about duplicate names and so forth. unfortunately, as your code is now, it is giving you something more confusing on the surface :slight_smile:

so, your code could be:

{ if (!stocksInPortfolio) { stocksInPortfolio = [[NSMutableArray alloc]init]; // change #1 - make these assignments hit the instance variable stocksInPortfolio (instead of creating a new local variable inside the if-statement) } // change #2 - add a closing bracket for the if-statement :) [stocksInPortfolio addObject:stock]; }

I bet that fixes it!


#3

Thanks so much for your help!
First of all you were right about the {'s being a cut & paste error.
More importantly, you saw that I was declaring the stocksInPortfolio twice, once in the @interface section (where it should be), and then again in my method implementation!
Once I removed the unnecessary “NSMutableArray *” type definition, it worked.
Thanks again.