Challenge Ch22 2nd Edition

Hi, this is my solution, feedback is welcome:

BNRPortfolio.h

[code]#import <Foundation/Foundation.h>
@class BNRStockHolding;

@interface BNRPortfolio : NSObject
@property (nonatomic, copy) NSArray *holdings;

  • (void)addHolding:(BNRStockHolding *)s;
  • (void)removeHolding:(unsigned int)i;
  • (float)totalValue;

@end[/code]

BNRPortfolio.m

- (void)setHoldings:(NSArray *)h
{
    _holdings = [h mutableCopy];
}

- (NSArray *)holdings
{
    return [_holdings copy];
}

- (void)addHolding:(BNRStockHolding *)s
{
    if (!_holdings)
    {
        _holdings = [[NSMutableArray alloc] init];
    }
    [_holdings addObject:s];
}

- (void)removeHolding:(unsigned int)i
{
    if (i < _holdings.count)
        {
            [_holdings removeObjectAtIndex:i];
        }
        else {
            NSLog(@"Index out of range or no holdings available");
        }
    
}

- (float)totalValue
{
    float sum = 0;
    
    for (BNRStockHolding *s in _holdings)
    {
        sum += [s valueInDollars];
    }
    return sum;
}

- (NSString *)description
{
    return [NSString stringWithFormat:@"<Portfolio value: %.02f>", self.totalValue];
}

@end

Here is my solution:

BNFPortfolio.h

[code]#import <Foundation/Foundation.h>
#import “BNRStockHolding.h”
#import “BNRForeignStockHolding.h”

@interface BNRPortfolio : NSObject

@property (nonatomic) float portfolioValue;
@property (nonatomic) NSArray *portfolio;

  • (void)addStock:(BNRStockHolding *)s;
  • (void)removeStock:(unsigned int)i;
  • (float)valueOfPortfolio;
  • (unsigned long)getCount;
  • (void) portfolioInfo;

@end[/code]

BNRPortfolio.m

[code]#import “BNRPortfolio.h”

@interface BNRPortfolio ()
{
NSMutableArray *_portfolio;
}

@end

@implementation BNRPortfolio

  • (void)setPortfolio:(NSArray *)p;
    {
    _portfolio = [p mutableCopy];
    }

-(NSArray *)portfolio
{
return [_portfolio copy];
}

  • (float) valueOfPortfolio
    {
    // sum up the value of the stocks in the portfolio
    float sum = 0.0;
    for (BNRStockHolding *s in _portfolio)
    {
    sum += [s valueInDollars];
    }
    return sum;
    }

  • (void)addStock:(BNRStockHolding *)s
    {
    // Is portfolio nil?
    if(!_portfolio)
    {
    // Create the array
    _portfolio = [[NSMutableArray alloc] init];
    }
    [_portfolio addObject:s];
    }

  • (void)removeStock:(unsigned int)i
    {
    [_portfolio removeObjectAtIndex:i];
    }

  • (unsigned long)getCount
    {
    unsigned long l = [_portfolio count];
    return l;
    }

  • (void)portfolioInfo
    {
    for (BNRStockHolding *s in _portfolio)
    {
    NSLog (@"%@ - Purchase Price = %.2f and Current Value = %.2f\n", [s symbol], [s costInDollars], [s valueInDollars]);
    }
    }

@end
[/code]

BNRForeignStockHolding.h

#import <Foundation/Foundation.h>
#import "BNRStockHolding.h"

@interface BNRForeignStockHolding : BNRStockHolding

@property (nonatomic) float conversionRate;

@end

BNRForeignStockHolding.m

#import "BNRForeignStockHolding.h"

@implementation BNRForeignStockHolding

- (float)costInDollars
{
    float foreignCostInDollars = [super costInDollars];
    return foreignCostInDollars * [self conversionRate]; // _conversionRate;
}

- (float) valueInDollars
{
    float foreignValueInDollars = [super valueInDollars];
    return foreignValueInDollars * [self conversionRate]; // _conversionRate;
}
@end

BNRStockHolding.h

[code]#import <Foundation/Foundation.h>
@class BNRPortfolio;

@interface BNRStockHolding : NSObject
{
float _purchaseSharePrice;
float _currentSharePrice;
int _numberOfShares;
}

  • (float)purchaseSharePrice;
  • (void)setPurchaseSharePrice:(float)psp;
  • (float)currentSharePrice;
  • (void)setCurrentSharePrice:(float)csp;
  • (int)numberOfShares;
  • (void)setNumberOfShares:(int)nos;
  • (float)costInDollars; // purchaseSharePrice * numberOfShares
  • (float)valueInDollars; // currentSharePrice * numberOfShares
    @property (nonatomic, copy) NSString *symbol;

@end
[/code]
BNRStockHolding.m

[code]#import “BNRStockHolding.h”
#import “BNRPortfolio.h”

@implementation BNRStockHolding

  • (float)purchaseSharePrice
    {
    return _purchaseSharePrice;
    }

  • (void)setPurchaseSharePrice:(float)psp
    {
    _purchaseSharePrice = psp;
    }

  • (float)currentSharePrice
    {
    return _currentSharePrice;
    }

  • (void)setCurrentSharePrice:(float)csp
    {
    _currentSharePrice = csp;
    }

  • (int)numberOfShares
    {
    return _numberOfShares;
    }

  • (void)setNumberOfShares:(int)nos
    {
    _numberOfShares = nos;
    }

  • (float)costInDollars
    {
    // purchaseSharePrice * numberOfShares
    return [self purchaseSharePrice] * [self numberOfShares];
    }

  • (float)valueInDollars
    {
    // currentSharePrice * numberOfShares
    return [self currentSharePrice] * [self numberOfShares];
    }

@end
[/code]

main.m

[code]#import <Foundation/Foundation.h>
#import “BNRForeignStockHolding.h”
#import “BNRPortfolio.h”

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

@autoreleasepool {
    
    // Creat an array of BNRStockHolding objects
    
    //NSMutableArray *portfolio = [[NSMutableArray alloc] init];
    BNRPortfolio *holdings = [[BNRPortfolio alloc] init];
    
    BNRStockHolding *apple = [[BNRStockHolding alloc] init];
    [apple setSymbol:@"APP"];
    [apple setCurrentSharePrice:4.50];
    [apple setPurchaseSharePrice:2.30];
    [apple setNumberOfShares:40];
    [holdings addStock:apple];
    
    BNRStockHolding *microSoft = [[BNRStockHolding alloc] init];
    [microSoft setSymbol:@"MS"];
    [microSoft setCurrentSharePrice:10.56];
    [microSoft setPurchaseSharePrice:12.19];
    [microSoft setNumberOfShares:90];
    [holdings addStock:microSoft];
    
    BNRStockHolding *bestBuy = [[BNRStockHolding alloc] init];
    [bestBuy setSymbol:@"BB"];
    [bestBuy setCurrentSharePrice:49.51];
    [bestBuy setPurchaseSharePrice:45.10];
    [bestBuy setNumberOfShares:210];
    [holdings addStock:bestBuy];
    
    BNRForeignStockHolding *bestFrenchBuy = [[BNRForeignStockHolding alloc] init];
    [bestFrenchBuy setSymbol:@"BFB"];
    [bestFrenchBuy setCurrentSharePrice:49.51];
    [bestFrenchBuy setPurchaseSharePrice:45.10];
    [bestFrenchBuy setNumberOfShares:210];
    [bestFrenchBuy setConversionRate:0.50];
    [holdings addStock:bestFrenchBuy];
    
    [holdings portfolioInfo];
    
    NSLog (@"The total portfolio value is %.2f", holdings.valueOfPortfolio);
    
    [holdings removeStock:2];

    [holdings portfolioInfo];
    
    NSLog (@"The total portfolio value is %.2f", holdings.valueOfPortfolio);

    
    
}
return 0;

}

[/code]

My general comment is with the remove portion. I see a lot of people passing in the index and deleting by that; however, I think it would be more realistic to pass in the stock symbol and delete where this is found. Passing the index is really contrived as that would never happen (who would know it?).

BNRPortfolio.m:

#import "BNRPortfolio.h"

@interface BNRPortfolio()

@property (nonatomic,copy) NSMutableArray *portArray;

@end

@implementation BNRPortfolio

-(NSMutableArray *)portArray
{
    if(!_portArray)
    {
        _portArray = [[NSMutableArray alloc]init];
    }
    return _portArray;
}

-(void)addStock:(BNRStockHolding *)stock
{
    [self.portArray addObject:stock];
}

-(void)removeStock:(NSString *)symbol
{
    for (int i=0;i<[self.portArray count];i++)
    {
        BNRStockHolding *holding = self.portArray[i];
        if ([holding.shareSymbol isEqualToString:symbol])
        {
            [self.portArray removeObjectAtIndex:i];
        }
    }
}

-(NSArray *)viewPortfolio
{
    return self.portArray;
}

-(float)portfolioValue;
{
    float value = 0.0;
    
    for (BNRStockHolding *s in self.portArray)
    {
        value+=[s valueIndollars]-[s costInDollars];
    }
    
    return value;
}

@end

@C6silver - I agree, passing the index is not practical

I have a question re your solution. I can see you declared a property

@property (nonatomic,copy) NSMutableArray *portArray;

I don’t really get it. Did you remove the property from the header file? What’s in your header file?

[code]#import “BNRStockHolding.h”

@interface BNRPortfolio : NSObject
@property (nonatomic) NSArray *holdings;

  • (void)addHolding: (BNRStockHolding *)h;
  • (void)removeHolding: (NSString *)symbol;
  • (unsigned int)currentPortfolioValue;

@end[/code]

Thanks!

I didn’t pass an index to remove a stock from the portfolio array. Instead, I just passed the variable for the stock that I had stored in the array which could be the ticker symbol although in my case I simply called it stock1.

Here is my method declaration:

BNRPortfolio.h

And the implementation of the method:

BNRPortfolio.m

- (void)removeStockHolding:(BNRStockHolding *)r { [_portfolio removeObject:r]; }

Then in main.m I just call the method with the following code and pass the stock1 parameter.

main.m

This seems really straightforward to me. Am I missing something.

removing stockholding using symbol string is quite a good idea and make good use of symbol placement in stock.

mine was quite same with you guys (remove method takes argument BNRStockHolding *)

but I put some protection to tell user if the stock that user is trying to remove is exist or array is still nil.

[code]-(void)removeStocks: (BNRStockHolding *)newStocks{

bool checker = false;
for (BNRStockHolding *findOne in _portfolioStocks) {
    if ([findOne isEqualTo:newStocks]) {
        checker = true;
    }
}

if (!_portfolioStocks) {
    NSLog(@"Stock is nil, didn't remove anything!");
}

else if  (checker)
    [_portfolioStocks removeObject:newStocks];

else
    NSLog(@"You are trying to remove stock that is not listed inside this stock!");

}[/code]

Hey “banjochris” if you are still around. This solution is the way I would go. But I am confused. The book says “move the property declaration for the array into a class extension”. You moved the instance variable, as I was about to do until I re-read the challenge. Do you think the book stated the challenge incorrectly? Where you able to continue through the rest of the book, or should I quit now and start learning SWIFT?

Anyway, any help you can provide, assuming you are still around, would be helpful.

[quote=“BanjoChris”]Here is my solution:

BNFPortfolio.h

[code]#import <Foundation/Foundation.h>
#import “BNRStockHolding.h”
#import “BNRForeignStockHolding.h”

@interface BNRPortfolio : NSObject

@property (nonatomic) float portfolioValue;
@property (nonatomic) NSArray *portfolio;

  • (void)addStock:(BNRStockHolding *)s;
  • (void)removeStock:(unsigned int)i;
  • (float)valueOfPortfolio;
  • (unsigned long)getCount;
  • (void) portfolioInfo;

@end[/code]

BNRPortfolio.m

[code]#import “BNRPortfolio.h”

@interface BNRPortfolio ()
{
NSMutableArray *_portfolio;
}

@end

@implementation BNRPortfolio

  • (void)setPortfolio:(NSArray *)p;
    {
    _portfolio = [p mutableCopy];
    }

-(NSArray *)portfolio
{
return [_portfolio copy];
}

  • (float) valueOfPortfolio
    {
    // sum up the value of the stocks in the portfolio
    float sum = 0.0;
    for (BNRStockHolding *s in _portfolio)
    {
    sum += [s valueInDollars];
    }
    return sum;
    }

  • (void)addStock:(BNRStockHolding *)s
    {
    // Is portfolio nil?
    if(!_portfolio)
    {
    // Create the array
    _portfolio = [[NSMutableArray alloc] init];
    }
    [_portfolio addObject:s];
    }

  • (void)removeStock:(unsigned int)i
    {
    [_portfolio removeObjectAtIndex:i];
    }

  • (unsigned long)getCount
    {
    unsigned long l = [_portfolio count];
    return l;
    }

  • (void)portfolioInfo
    {
    for (BNRStockHolding *s in _portfolio)
    {
    NSLog (@"%@ - Purchase Price = %.2f and Current Value = %.2f\n", [s symbol], [s costInDollars], [s valueInDollars]);
    }
    }

@end
[/code]

BNRForeignStockHolding.h

#import <Foundation/Foundation.h>
#import "BNRStockHolding.h"

@interface BNRForeignStockHolding : BNRStockHolding

@property (nonatomic) float conversionRate;

@end

BNRForeignStockHolding.m

#import "BNRForeignStockHolding.h"

@implementation BNRForeignStockHolding

- (float)costInDollars
{
    float foreignCostInDollars = [super costInDollars];
    return foreignCostInDollars * [self conversionRate]; // _conversionRate;
}

- (float) valueInDollars
{
    float foreignValueInDollars = [super valueInDollars];
    return foreignValueInDollars * [self conversionRate]; // _conversionRate;
}
@end

BNRStockHolding.h

[code]#import <Foundation/Foundation.h>
@class BNRPortfolio;

@interface BNRStockHolding : NSObject
{
float _purchaseSharePrice;
float _currentSharePrice;
int _numberOfShares;
}

  • (float)purchaseSharePrice;
  • (void)setPurchaseSharePrice:(float)psp;
  • (float)currentSharePrice;
  • (void)setCurrentSharePrice:(float)csp;
  • (int)numberOfShares;
  • (void)setNumberOfShares:(int)nos;
  • (float)costInDollars; // purchaseSharePrice * numberOfShares
  • (float)valueInDollars; // currentSharePrice * numberOfShares
    @property (nonatomic, copy) NSString *symbol;

@end
[/code]
BNRStockHolding.m

[code]#import “BNRStockHolding.h”
#import “BNRPortfolio.h”

@implementation BNRStockHolding

  • (float)purchaseSharePrice
    {
    return _purchaseSharePrice;
    }

  • (void)setPurchaseSharePrice:(float)psp
    {
    _purchaseSharePrice = psp;
    }

  • (float)currentSharePrice
    {
    return _currentSharePrice;
    }

  • (void)setCurrentSharePrice:(float)csp
    {
    _currentSharePrice = csp;
    }

  • (int)numberOfShares
    {
    return _numberOfShares;
    }

  • (void)setNumberOfShares:(int)nos
    {
    _numberOfShares = nos;
    }

  • (float)costInDollars
    {
    // purchaseSharePrice * numberOfShares
    return [self purchaseSharePrice] * [self numberOfShares];
    }

  • (float)valueInDollars
    {
    // currentSharePrice * numberOfShares
    return [self currentSharePrice] * [self numberOfShares];
    }

@end
[/code]

main.m

[code]#import <Foundation/Foundation.h>
#import “BNRForeignStockHolding.h”
#import “BNRPortfolio.h”

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

@autoreleasepool {
    
    // Creat an array of BNRStockHolding objects
    
    //NSMutableArray *portfolio = [[NSMutableArray alloc] init];
    BNRPortfolio *holdings = [[BNRPortfolio alloc] init];
    
    BNRStockHolding *apple = [[BNRStockHolding alloc] init];
    [apple setSymbol:@"APP"];
    [apple setCurrentSharePrice:4.50];
    [apple setPurchaseSharePrice:2.30];
    [apple setNumberOfShares:40];
    [holdings addStock:apple];
    
    BNRStockHolding *microSoft = [[BNRStockHolding alloc] init];
    [microSoft setSymbol:@"MS"];
    [microSoft setCurrentSharePrice:10.56];
    [microSoft setPurchaseSharePrice:12.19];
    [microSoft setNumberOfShares:90];
    [holdings addStock:microSoft];
    
    BNRStockHolding *bestBuy = [[BNRStockHolding alloc] init];
    [bestBuy setSymbol:@"BB"];
    [bestBuy setCurrentSharePrice:49.51];
    [bestBuy setPurchaseSharePrice:45.10];
    [bestBuy setNumberOfShares:210];
    [holdings addStock:bestBuy];
    
    BNRForeignStockHolding *bestFrenchBuy = [[BNRForeignStockHolding alloc] init];
    [bestFrenchBuy setSymbol:@"BFB"];
    [bestFrenchBuy setCurrentSharePrice:49.51];
    [bestFrenchBuy setPurchaseSharePrice:45.10];
    [bestFrenchBuy setNumberOfShares:210];
    [bestFrenchBuy setConversionRate:0.50];
    [holdings addStock:bestFrenchBuy];
    
    [holdings portfolioInfo];
    
    NSLog (@"The total portfolio value is %.2f", holdings.valueOfPortfolio);
    
    [holdings removeStock:2];

    [holdings portfolioInfo];
    
    NSLog (@"The total portfolio value is %.2f", holdings.valueOfPortfolio);

    
    
}
return 0;

}

[/code][/quote]

@C6silver and everyone else following - not sure why people aren’t using just removeObject instead of removeObjectAtIndex? Seems it’d be really simple to just specify the object to remove? But perhaps I’m missing something…

-(void)removeStock:(NSString *)symbol
{
    for (int i=0;i<[self.portArray count];i++)
    {
        BNRStockHolding *holding = self.portArray[i];
        if ([holding.shareSymbol isEqualToString:symbol])
        {
            [self.portArray removeObject:holding];
        }
    }
}

Not sure why everyone is using removeObjectAtIndex with an int value assigned to each stock…? I found it easier just to remove the actual stock object itself.

[code]// BNRPortfolio.h

  • (void)addStock:(BNRStockHolding *)s;
  • (void)removeStock:(BNRStockHolding *)s;[/code]

[code]// BNRPortfolio.m

  • (void)addStock:(BNRPortfolio *)s {
    // if the array is not created
    if (!_stockHoldings) {
    // create it
    _stockHoldings = [[NSMutableArray alloc]init];
    }
    // add BNRPortfolio object to the array
    [_stockHoldings addObject:s];
    }

  • (void)removeStock:(BNRPortfolio *)s {
    // if the array is available / has been created
    if (_stockHoldings) {
    // remove BNRPortfolio object
    [_stockHoldings removeObject:s];
    }
    }[/code]

[code]
// main.m

    // create an instance of BNRPortfolio
    BNRPortfolio *portfolio = [[BNRPortfolio alloc]init];

    // create an instance of BNRStockHolding
    BNRStockHolding *stockOne = [[BNRStockHolding alloc]init];
    // can be assigned using dot-notaton
    stockOne.symbol = @"BNR";
    stockOne.costInDollars = 2.30;
    stockOne.valueInDollars = 4.50;
    stockOne.numberOfShares = 40;
    [portfolio addStock];
    
    // ... more stock objects

    // print details of each stock
    NSLog(@"\n%@\n%@\n%@\n%@\n%@", stockOne, stockTwo, stockThree, foreignOne, foreignTwo);

    // print net value of portfolio
    NSLog(@"%@", portfolio);

    // remove some stocks
    [portfolio removeStock];
    [portfolio removeStock:stockThree];

    // print new net value
    NSLog(@"New %@", portfolio);[/code]

[quote]Output:
2015-02-19 14:25:00.644 Stocks[23821:4004745]
Company: BNR | Number of Shares: 40 | Cost: $92.00 | Valued at: $180.00
Company: ABC | Number of Shares: 90 | Cost: $1097.10 | Valued at: $950.40
Company: XYZ | Number of Shares: 210 | Cost: $9471.00 | Valued at: $10397.10
Company: APPL | Number of Shares: 40 | Cost: $86.48 | Valued at: $169.20
Company: VLS | Number of Shares: 150 | Cost: $8511.08 | Valued at: $9673.83
2015-02-19 14:25:00.645 Stocks[23821:4004745] Portfolio has a net value of: $21370.53
2015-02-19 14:25:00.645 Stocks[23821:4004745] New Portfolio has a net value of: $10023.03[/quote]