Method not recognized


#1

Hi,

I am stuck and can’t seem to find a way out. I am able to create an instance of BNRPortfolio but this instance doesn’t recognize my custom methods like “addStock”. I hope somebody can help me. I am new to OS X programming and find the book very good so far.

Here is my code of BNRPortfolio.m:

#import "BNRPortfolio.h"
#import "BNRStockHolding.h"

@implementation BNRPortfolio

- (double)currentValue:(BNRStockHolding *)holding
{
    return [holding valueInDollars] - [holding costInDollars];
}

- (void)addStock:(BNRStockHolding *)s
{
    // Do we have an array?
    if (!_portfolios) {
        // If not, create one
        _portfolios = [[NSMutableArray alloc]init];
    }
    [_portfolios addObject:s];
}
@end

BNRPortfolio.:

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

@interface BNRPortfolio : NSObject

{
    NSMutableArray *_portfolios;
}

@property (nonatomic) double currentValue;
- (void)addStock:(BNRStockHolding *)s;

@end

Main:

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

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

    @autoreleasepool {
        
        BNRStockHolding *holding1 = [[BNRStockHolding alloc] init];
        BNRStockHolding *holding2 = [[BNRStockHolding alloc] init];
        BNRStockHolding *holding3 = [[BNRStockHolding alloc] init];
        
        // Child Object of BNRStockHolding
        BNRForeignStockHolding *holding4 = [[BNRForeignStockHolding alloc] init];
        
        [holding1 setPurchaseSharePrice:2.30];
        [holding1 setCurrentSharePrice:4.50];
        [holding1 setNumberOfShares:40];
        [holding1 setNameOfHolding:@"holding1"];
        

        [holding2 setPurchaseSharePrice:12.19];
        [holding2 setCurrentSharePrice:10.55];
        [holding2 setNumberOfShares:90];
        [holding2 setNameOfHolding:@"holding2"];
        
        [holding3 setPurchaseSharePrice:45.10];
        [holding3 setCurrentSharePrice:49.51];
        [holding3 setNumberOfShares:210];
        [holding3 setNameOfHolding:@"holding3"];
        
        // Same values as holding1 but different outcome because the method is overriden and calculates Euro in Dollar
        [holding4 setPurchaseSharePrice:2.30];
        [holding4 setCurrentSharePrice:4.50];
        [holding4 setNumberOfShares:40];
        [holding4 setNameOfHolding:@"holding4"];
        
        
        
        
        NSArray *allHoldings = @[holding1, holding2, holding3, holding4];
        
        
        for (BNRStockHolding *a in allHoldings){
            NSLog(@"%@", a); // prints custom description of a holding made by me in BNRStockHolding.h
        }
        
        BNRPortfolio *portfolio = [[BNRPortfolio alloc] init];
        [portfolio addStock]; // NOT RECOGNIZED
        
    }
    return 0;
}

I get the message: No visible @interface for “BNRPortfolio” declares the selector “addStock”

But I importert the header files and also I can create an instance of BNRPortfolio. Thanks in advance!


#2

I can’t see anything wrong with your code; it builds without any errors.

Did you actually have the addStock: method declared in BNRPortfolio’s interface at the the time you had that error?

It could also be that you had something unusual with your project settings.


#3

Hi Ibex,

thanks for your answer. I didn’t have and still don’t have an addObject method declared. My code looks exactly like the code I posted and everything else runs without problems. I already struggle a day with this and don’t want just to copy/paste a solution but want to find the problem so that next time I can find the solution much quicker :slight_smile:

Do you have any more ideas? Why is that, that I can create a BNRPortfolio object but can’t access it’s method?


#4

P.S. can you create a BNRPortfolio object with my code? Because you said it builds without any errors. I still can’t so maybe the issue lays on another place (but I can build without creating that object).


#5

Oops! That should be addStock: not addObject:

Here is your code, but because I did not have the code for BNRStockHolding, I had to improvise:

//  BNRPortfolio.h

#import <Foundation/Foundation.h>

@class BNRStockHolding;

@interface BNRPortfolio : NSObject
{
    NSMutableArray *_portfolios;
}

@property (nonatomic) double currentValue;

# if 0   // exclude this method to simulate No visible @interface for ... error
         // change 0 to 1 to include
- (void)addStock:(BNRStockHolding *)s;
#endif

@end
//  BNRPortfolio.m

#import "BNRPortfolio.h"

@implementation BNRPortfolio

- (double)currentValue:(BNRStockHolding *)holding
{
    return 0;
}

- (void)addStock:(BNRStockHolding *)s
{
    // Do we have an array?
    if (!_portfolios) {
        // If not, create one
        _portfolios = [[NSMutableArray alloc]init];
    }
    [_portfolios addObject:s];
}
@end
//  main.m

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

int main (int argc, const char * argv[])
{
    @autoreleasepool {
        BNRPortfolio *portfolio = [[BNRPortfolio alloc] init];
        [portfolio addStock:[NSNull null]];
    }
    return 0;
}

Try experimenting with the # if 0 … #endif in BNRPortfolio.h


#6

Thank your for your fast support Ibex.

It’s not only the addStock method but also the currentValue method which I can’t access and they are both declared in the interface of BNRPortfolio.

How can I use the #if#endif ? what does it do? -> excuse me for my newbie questions :slight_smile:. In the past I only programmed some Java.
I guess to does, like your comments are saying, exclude the declaration, so it would be the same as commenting out right?

I tried exactly what you wrote but still and implemented [portfolio addStock:[NSNull null]]; in the main.m but still no change

Here is my code from BNRStockHolding:

#import <Foundation/Foundation.h>

@interface BNRStockHolding : NSObject

@property (nonatomic) float purchaseSharePrice;
@property (nonatomic) float currentSharePrice;
@property (nonatomic) unsigned int numberOfShares;
@property (nonatomic) NSString *nameOfHolding;


// Methods
- (float)costInDollars;
- (float)valueInDollars;


@end
#import "BNRStockHolding.h"

@implementation BNRStockHolding


// Calculation with with get methods


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

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

- (NSString *)description
{
    return [NSString stringWithFormat:@"\n Holding Name: %@\n Cost in Dollars: %.2f\n Value in Dollars: %.2f\n",
            self.nameOfHolding, self.costInDollars, self.valueInDollars];
}

@end

#7

After researching I finally found the solution.

Somehow Xcode had two .h files in the project folder. I had to select the newer one with Xcode manually and now everything builds up!

Thanks for your support Ibex!