【问题标题】:How do I add an Object to an array via a static(+) method?如何通过静态(+)方法将对象添加到数组中?
【发布时间】:2014-08-13 22:43:18
【问题描述】:
// 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

我已经声明了一个类方法 addItemToMarketplace,它接受一个 Item 类型的对象,并将这个 Item 添加到我在实现文件的接口中声明的 listOfItems 属性中(我不确定我是否希望其他类摆弄这个性质)。我在另一个类中使用过这种方法,例如 [Marketplace addItemToMarketplace:newItem]。我不确定如何处理在编写 [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"

任何帮助将不胜感激。

// NEW CHANGES!

在进行了一些更改并遵循我在其他网站上找到的一些建议后,以下是我目前所拥有的:

// 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

问题、cmets、疑虑?

【问题讨论】:

  • '+' 是一个类方法。 'self' 指的是类的一个实例。您的“listOfItems”变量是一个实例变量。这只有在你的班级使用 Singleton 时才有效。
  • 基本问题是属性属于对象,而不是类。如果您只想将其中一个用于类并从类方法访问它,则需要将 listOfItems 设为静态指针。
  • 您的应用中是否只有一个 marketplace 实例?如果是这样,您可以创建一个单例市场并使用此模式:[[Marketplace theMarketplace] addItem:&lt;*item*&gt;]
  • 好的,有道理。我只在本课程之外引用一次 Marketplace。这是我第一次看到 Singleton 这个词。有人可以解释或指向我的在线文章吗?
  • 单例只是意味着应用程序中只有一个类的实例。参看。 stackoverflow.com/a/5720147/210171

标签: objective-c arrays static-methods


【解决方案1】:

只有实例方法可以对实例数据进行操作。因此,您需要一个实例或将数据也更改为静态:

@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

请注意,这里没有线程安全。

【讨论】:

    【解决方案2】:

    + 前缀定义了一个类方法。在该方法中self 指的是类本身,这几乎肯定不是您想要的。该类没有listOfItems,因为这是该类的每个实例上可用的属性。

    不清楚您在这里尝试做什么。如果您来自 C/C++ 背景,那么您可能已经为此方法假设了不同的行为。您是想将项目添加到由此类的特定实例管理的列表中,还是添加到所有实例共享的列表中?

    【讨论】:

    • 我正在构建一个市场应用程序,因此我很确定我想要一个在所有实例之间共享的列表。我没有 C/C++ 背景。我对 Java 比较熟悉。
    • 那么这就引出了另一个问题,静态共享列表在这里是否合适。我怀疑您最好使用单个 Marketplace 实例,该实例可能在许多其他组件之间共享,但您仍然可以控制其生命周期。
    • 我使用单例模式创建了一个单一的市场。我对最初发布的代码进行了更改。
    • 我认为使用单例模式来获得这样的依赖是有问题的,是正常控制流的反转,并且导致难以测试和难以更改代码。但是,我希望上面的代码能够按您的意图运行。你有什么问题吗?我在想象任何需要Marketplace 的对象都应该传递给它。目前这些可能碰巧都是同一个 Marketplace 实例,但这是这些对象的创建者可以做出的决定。
    【解决方案3】:

    如果您的应用中只有一个 marketplace 实例,请考虑使用单例..

    然后您可以像这样将商品添加到单一市场:

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

    这是一种设置方法:

    @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
    

    (或在 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 }
    }
    

    【讨论】:

    • Swift 还不支持类变量——我假设你将来不需要内部 Struct 声明
    • 我刚刚用我所做的一些更改编辑了我的问题。
    猜你喜欢
    • 2014-08-11
    • 2015-07-13
    • 1970-01-01
    • 2011-05-20
    • 1970-01-01
    • 1970-01-01
    • 2020-04-09
    • 2012-05-13
    • 1970-01-01
    相关资源
    最近更新 更多