-2
// Marketplace.h
#import <Foundation/Foundation.h>
#import "Item.h"

@interface Marketplace : NSObject

+ (void)addItemToMarketplace:(Item *)newItem; // METHOD IN QUESTION

@end

// Marketplace.m
#import "Marketplace.h"

@interface Marketplace()
@property (strong, nonatomic) NSMutableArray *listOfItems;
@end

@implementation Marketplace


+ (void)addItemToMarketplace:(Item *)newItem // METHOD IN QUESTION
{
    [self.listOfItems addObject:newItem]; // Raises 3 errors
}

@end

I have declared a class method addItemToMarketplace that takes in an object of type Item and adds this Item to the listOfItems property that I have declared in the interface of the implementation file (I am not sure that I want other classes to fiddle with this property). I have used this method in another class as such [Marketplace addItemToMarketplace:newItem]. I am not sure how to handle the three errors that are raised when I write [self.listOfItems addObject:newItem].

The 3 errors are as follows:
    1. Member reference type 'struct objc_class *' is a pointer; maybe you meant to use '->'?
    2. Definition of 'struct objc_class' must be imported from module 'ObjectiveC.runtime' before it is required
    3. No member named 'listOfItems' in 'struct objc_class'

Making the change proposed in #1, which changes self.listOfItems to self->listOfItems, raises the error "Member reference base type 'Class' is not a structure or union"

Any help would be appreciated.

// NEW CHANGES!

After making some changes and following some suggestions I found on other sites, here's what I have so far:

// Marketplace.h

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

@interface Marketplace : NSObject {}

+ (Marketplace *)sharedMarket;
- (void)addItemToMarketplace:(Item *)newItem;

@end

// Marketplace.m

#import "Marketplace.h"

@interface Marketplace()
@property (strong, nonatomic)NSMutableArray *listOfItems;
@end

static Marketplace *sharedMarketplace = nil;

@implementation Marketplace

+ (Marketplace *)sharedMarket
{
    if (sharedMarketplace == nil) {
        sharedMarketplace = [[super allocWithZone:NULL] init];
    }
return sharedMarketplace;
}


- (void)addItemToMarketplace:(Item *)newItem
{
    [self.listOfItems addObject:newItem];
}

- (id)init
{
    if ( (self = [super init]) ) {
    }
    return self;
}

+ (id)allocWithZone:(NSZone *)zone {
    return [self sharedMarket];
}

- (id)copyWithZone:(NSZone *)zone {
    return self;
}

@end

Questions, comments, concerns?

Plato1212
  • 749
  • 1
  • 5
  • 9
  • 2
    '+' is a Class method. 'self' refers to an instance of the class. Your 'listOfItems' variable is an instance variable. This will only work if you use a Singleton for your class. – Terry Wilcox Jun 23 '14 at 19:20
  • The basic problem is that properties belong to objects, not classes. You would need to make `listOfItems` a static pointer if you want to have only one of them for the class and access it from a class method. – Phillip Mills Jun 23 '14 at 19:22
  • 1
    do you just have one instance of *marketplace* in your app? If so, you could make a singleton market place and use this pattern: `[[Marketplace theMarketplace] addItem:<*item*>]` – nielsbot Jun 23 '14 at 19:24
  • Ok, that makes sense. I only reference Marketplace once outside of this class. This is the first time that I am seeing the term Singleton. Can someone explain or point me to an online article? – Plato1212 Jun 23 '14 at 19:32
  • A singleton just means there is only instance for a class in the app. cf. http://stackoverflow.com/a/5720147/210171 – nielsbot Jun 23 '14 at 20:11

3 Answers3

2

Only the instance methods can operate on instance data. So you need either an instance or change the data to static too:

@interface Marketplace()
@end

static NSMutableArray *listOfItems;  // static is implied, so not really necessary

@implementation Marketplace

+ (void)addItemToMarketplace:(Item *)newItem {

    if (!listOfItems) listOfItems = [NSMutableArray array];
    [listOfItems addObject:newItem];
}

@end

Note that there's no thread safety here.

danh
  • 62,181
  • 10
  • 95
  • 136
0

The + prefix defines a class method. Within that method self refers to the class itself which is almost certainly not what you intend. The class does not have a listOfItems as that is a property available on each instance of the class.

It is not clear what you are attempting to do here. If you are coming from a C/C++ background perhaps you have assumed a different behavior for this method. Are you trying to add an item to a list managed by a particular instance of this class or to a list shared across all instances?

Jonah
  • 17,918
  • 1
  • 43
  • 70
  • I am building a marketplace app and so, I am pretty sure that I want a list shared across all instances. I do not have a C/C++ background. I am more familiar with Java. – Plato1212 Jun 23 '14 at 19:36
  • Well then that leads to a further question of if a static shared list is appropriate here. I suspect you'll be better off with a single `Marketplace` instance which might be shared between many other components but whose lifecycle you can still control. – Jonah Jun 23 '14 at 22:34
  • I have created a single Marketplace using the Singleton pattern. I made changes to the code that I originally posted. – Plato1212 Jun 24 '14 at 14:53
  • I think use of the singleton pattern to obtain a dependency like this is problematic, an inversion of normal control flow, and leads to hard to test and hard to change code. However I would expect the code above to function as you intend. Is there some problem you are having with it? I was imagining that whichever object needs a `Marketplace` should have one passed to it. Those may happen to all be the same `Marketplace` instance for now but that's a decision the creator of those objects can make. – Jonah Jun 24 '14 at 18:24
0

If you just have one instance of marketplace in your app consider using a singleton..

You then might add items to the single marketplace like this:

[[Marketplace theMarketplace] addItem:<*item*>]

Here's one way to set this up:

@interface Marketplace : NSObject
@property ( nonatomic ) NSArray * items ;
@end

@implementation Marketplace

static Marketplace * __marketplace ;

+(void)load
{
    __marketplace = [ Marketplace new ] ;
}

+(instancetype)theMarketplace
{
    return __marketplace ;
}

-(void)addItem:(Item*)item
{
    self.items = [ ( self.items ?: @[] ) arrayByAddingObject:item ] ;
}

@end

(or in Swift)

class Marketplace
{
    struct Static
    {
        static let marketplace = Marketplace()
    }

    var items:Array<Item> = [] ;

    class func get() -> Marketplace { return Static.marketplace }

    func addItem( item: Item ) { self.items += item }
}
nielsbot
  • 15,922
  • 4
  • 48
  • 73