No Visible @interface Error in the BNRPortfolio challenge


#1

I wanted to see if anyone could explain why I’m getting a particular error in the BNRPortfolio challenge. Based on my previous coding experiences with other languages, I am way more comfortable referencing instance variable via self. However, the following code gives me an error:

[code]- (void)addStock:(BNRStockHolding *)s
{
//check to see if nil
if (! self.holdings)
{
self.holdings = [[NSMutableArray alloc] init];
}

[self.holdings addObject:s];
}

[/code]

Specifically, the “[self.holdings addObject:s]” generates an error stating “no visible @interface for ‘NSArray’ declares the selector ‘addObject:’”

If I replace “[self.holdings addObject:s]” with “[_holdings addObject:s]” it works perfectly.

For reference, here is my complete BNRPortfolio.m file:

[code]//
// BNRPortfolio.m
// Stocks
//

#import “BNRPortfolio.h”
#import “BNRStockHolding.h”

@interface BNRPortfolio ()
{
NSMutableArray *_holdings;
}

@end

@implementation BNRPortfolio

  • (void)setHoldings:(NSArray *)s
    {
    _holdings = [s mutableCopy];
    }

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

  • (float)totalValue
    {
    float total = 0.0;

    for(BNRStockHolding *a in self.holdings)
    {
    total+=[a valueInDollars];
    }

    return total;
    }

  • (void)addStock:(BNRStockHolding *)s
    {
    //check to see if nil
    if (! self.holdings)
    {
    self.holdings = [[NSMutableArray alloc] init];
    }

    //[self.holdings addObject:s];
    [_holdings addObject:s];
    }

  • (void)removeStock:(NSString *)s
    {
    //check to make sure not nil
    if (self.holdings)
    {
    for (int i=0;i<[self.holdings count];i++)
    {
    BNRStockHolding *h = self.holdings[i];
    if ([h.symbol isEqualToString:s])
    {
    [_holdings removeObjectAtIndex:i];
    }
    }
    }
    else
    {
    NSLog(@“No items left to remove.”);
    }
    }

@end
[/code]

and my BNRPortfolio.h file:

[code]//
// BNRPortfolio.h
// Stocks
//

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

@interface BNRPortfolio : NSObject

  • (void)setHoldings:(NSArray *)s;
  • (NSArray *)holdings;
  • (float)totalValue;
  • (void)addStock:(BNRStockHolding *)s;
  • (void)removeStock:(NSString *)s;

@end
[/code]

As an aside, thanks C6Silver for your remove stock function. I was having a heck of a time trying to figure out how to do the same thing (it’s been so long since I last coded and Apple’s documentation leaves a little to be desired!).


#2

[quote]Specifically, the “[self.holdings addObject:s]” generates an error stating “no visible @interface for ‘NSArray’ declares the selector ‘addObject:’”

If I replace “[self.holdings addObject:s]” with “[_holdings addObject:s]” it works perfectly.

...
@interface BNRPortfolio ()
{
    NSMutableArray *_holdings;
}

@end
...

[/quote]
You could try declaring a private property:

...
@interface BNRPortfolio ()
{
    NSMutableArray *_holdings;
}
@property NSMutableArray * holdings;

@end
...

But then this would clash with the getter in the interface.

However, there is no need for this. Since _holdings is an internal object, it is simpler to access this object directly rather than through a property.


#3

Even with the @property declaration, it still gives me the same error. It does let me reference “self.holding” in other places within the same function.


#4

From what I can see, you don’t have a property declared in your header file.
Try this: @property (nonatomic, copy) NSArray *holdings;