【问题标题】:Global variable NSMuteableArray using Singleton Class使用单例类的全局变量 NSMuteableArray
【发布时间】:2011-04-26 20:22:10
【问题描述】:

我在创建一种将集合传递给不同视图控制器的好方法时遇到了麻烦。例如,我创建了一个名为 Message 的自定义类,其中包含一堆属性。我想要一个全局的 NSMutableArray 存储在一个名为消息的全局变量中,我可以添加到任何地方或从任何地方获取。 Stackoverflow 上的每个人都说不要使用你的 delagate 类来存储全局变量,所以我创建了一个名为 Shared 的单例类。在那里,我为 NSMutableArray 创建了一个名为 messages 的属性,如下所示:


@interface Shared : NSObject {

}

@property (nonatomic, retain) NSMutableArray *messages;

+(Shared *) sharedInstance;

@end

而我的 .h 文件是(重要的部分):


#import "Shared.h"
static Shared* sharedInstance;

@implementation Shared

@synthesize messages;

static Shared *sharedInstance = nil;

-(id) init {
    self = [super init];
    if (self != nil){

    }
    return self;
}

-(void) initializeSharedInstance {

}

+ (Shared *) sharedInstance{
    @synchronized(self) {
        if (sharedInstance == nil){
            sharedInstance = [[self alloc] init];
            [sharedInstance initializeSharedInstance];

        }
        return (sharedInstance);
    }
}

在我的另一个视图控制器中,我首先导入“Shared.h”,然后试试这个:


[[Shared sharedInstance].messages addObject:m];

NSLog([NSString stringWithFormat:@"Shared messages = %@", [Shared sharedInstance].messages]);

它一直打印 null 而不是 m 个对象的集合。有什么想法吗?

【问题讨论】:

  • 你在哪里初始化消息?我认为@synthesize 不会初始化变量。
  • 也许人们因为不推荐全局变量而说不要使用app delegate来存储全局变量?用户默认设置或在创建视图控制器时传递数据也可以。
  • Matt,我刚刚添加了 init,以便您可以看到该部分。特里,好点子。如果我不能以这种方式解决问题,我可能最终会走那条路。出于理智考虑,如果可能的话,我想解决这个问题。
  • 马特,我想我误解了你的问题。我展示了我的 init 函数,但我可能必须从我第一次使用它的其他类中实际调用 init。

标签: objective-c ios ios4


【解决方案1】:

你需要有一个静态变量。

在.h中:

@interface Shared : NSObject
{
    NSMutableArray *messages;
}

@property (nonatomic, retain) NSMutableArray *messages;

+ (Shared*)sharedInstance;

@end

在.m:

static Shared* sharedInstance;

@implementation Shared

@synthesize messages;


+ (Shared*)sharedInstance
{
    if ( !sharedInstance)
    {
        sharedInstance = [[Shared alloc] init];

    }
    return sharedInstance;
}

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

【讨论】:

  • 在您的应用委托类中存储全局变量确实不是什么大罪,尤其是在您的情况下,因为它只是一个数组。
  • 约瑟夫,我刚刚按照建议添加了静态变量。不过似乎仍然给出了 null 。
  • 如何从其他类初始化我的数组?我试过 [[Shared sharedInstance].messages init];但这似乎没有做到。在处理来自另一个类的静态变量时,我可能只是在使用 init 语法。
  • Jody,不要从其他类初始化。该类不知道消息是否已在使用中。相反,您的 Shared 类的 init 方法应该分配/初始化您的数组(就像在约瑟夫的回答中一样)。这样一来,一旦创建 Shared 的实例,它就会得到一个已初始化的数组,可用于任何其他类。
【解决方案2】:

一个想法:

@synthesize 生成 setter 和 getter 方法,它不会初始化您的变量。你在哪里做?我在您发布的摘录中看不到它。

【讨论】:

  • 我想也许就是这样。我不确定如何从另一个类初始化变量。我试过 [[Shared sharedInstance].messages init];
  • +sharedInstance 是返回类实例的类方法。如果还没有实例存在,它通过调用 -init 方法创建实例(它检查静态变量是否存在现有实例)。在 -init 方法中,您应该按照 Joseph Lin 的示例初始化您的数组。如果数组尚未初始化,则有可能为零。由于可以在 objective-c 中向 nil 发送消息,因此不会返回错误,尽管数组的行为不会像预期的那样 - 例如,您将无法在其中存储值。
  • P.S.:在您当前的实现中,方法 -initializeSharedInstance 没有用,我会考虑删除它。
  • 沃尔夫冈,你是对的。我忽略了 Joseph Lin 示例的 init 部分。我希望我能给你们两个功劳!
【解决方案3】:

以下不是对您的问题的回答,而是对(在我看来)使用中“更清洁”的替代方法的建议。

使用单例存储应用程序范围的替代方法是定义一个具有类方法的类,该类方法从 NSUserDefaults 检索值。此类可以导入到前缀标头 (*.pch) 中,以便您可以从项目中的每个其他类访问它。

该类中的方法可能如下所示:

Settings.h 内:

// for this example I'll use the prefix for a fictional company called SimpleSoft (SS)
extern NSString *kSSUserLoginNameKey;

+ (NSString *)userLoginName;
+ (void)setUserLoginName:(NSString *)userLoginName; 

Settings.m 内:

kSSUserLoginNameKey = @"SSUserLoginNameKey";

+ (NSString *)userLoginName 
{
    return [[NSUserDefaults standardUserDefaults] valueForKey:kSSUserLoginNameKey];
}

+ (void)setUserLoginName:(NSString *)userLoginName 
{
    [[NSUserDefaults standardUserDefaults] setValue:userLoginName forKey:kSSUserLoginNameKey];
    [[NSUserDefaults standardUserDefaults] synthesize];
}

当然,在这样的设置中,NSUserDefaults 是通过便利类访问的单例。此类充当 NSUserDefaults 单例的包装器。可以像这样访问值:

NSString userLoginName = [Settings userLoginName];
[Settings setUserLoginName:@"Bob"];

其他对象——比如数组——可以以几乎相同的方式访问。需要注意的一件事(与您当前的方法非常相似)是注意不要从其他所有类访问这样的类。旨在可重用的组件应该传递值,因此应用程序的组件不会与设置类过于紧密地耦合。

【讨论】:

  • 这将是很多工作,因为我正在编写一组自定义对象。序列化这可能是很多工作。
  • 视情况而定,您可以将数组存储在 NSUserDefaults 中(使用 +objectForKey:+setObject:forKey: 方法),因为它是NSObject - 您不必将数组中的每个单独值存储在不同的变量中,您可以只存储整个数组。
  • 也许你也应该看看这篇文章,以防你的数组包含自定义对象:stackoverflow.com/questions/4197246/…
猜你喜欢
  • 2017-04-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-09
相关资源
最近更新 更多