单例对象的奇怪行为

时间:2012-01-12 14:42:12

标签: iphone objective-c singleton

我真的很奇怪。我创建了一个名为“Profile like this:

”的类的单一对象
static Profile *currentProfile;

+ (Profile *)currentProfile
{
@synchronized(self)
{
    if (currentProfile == nil)
        currentProfile = [[Profile alloc] init];
}

return currentProfile;
}

- (id)init
{
self = [super init];
if (self)
 {
    // Initialization code here.
    isChecked = [[[NSUserDefaults standardUserDefaults] objectForKey:@"isChecked"] boolValue];       

     if (isChecked)
     {
         NSLog(@"isChecked block is called");
         NSData *data = [[NSUserDefaults standardUserDefaults] objectForKey:@"myEncodedObjectKey"];
         self         = (Profile *) [NSKeyedUnarchiver unarchiveObjectWithData:data];
         [self retain];

         for (int i = 0; i < self.avatar.count; i++)
             [self.avatar replaceObjectAtIndex:i withObject:[UIImage imageWithData:[self.avatar objectAtIndex:i]]]; 
     }

     else
     {
         password  = @""; 
         pfefferID = @"";
         email     = @"";
         avatar    = [[NSMutableArray alloc] initWithObjects:
                     [UIImage imageNamed:@"empty_image.png"], 
                     [UIImage imageNamed:@"empty_image.png"],
                     [UIImage imageNamed:@"empty_image.png"],
                     [UIImage imageNamed:@"empty_image.png"],
                     [UIImage imageNamed:@"empty_image.png"],nil];
         isBoy     = YES;
         friends   = [[NSMutableDictionary alloc] init]; 
         rating    = 0; 
     }
  }

return self;
}

在init方法中,我使用名为“isChecked”的BOOL变量检查存储在NSUserDefaults中的某个条件。 isChecked等于YES,一切正常。但是......我在AppDelegate文件中创建这个Profile对象,就像这样

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
 {
users                         = [[NSMutableDictionary alloc] init];
usersForLeaderboardFromServer = [[NSMutableDictionary alloc] init];
listOfFriendsFromServer       = [[NSMutableDictionary alloc] init];
currentProfile                = [Profile currentProfile];
sessionID                     = 0;

if (!currentProfile.isChecked)//why????
    NSLog(@"not checked");

if (currentProfile.isChecked)
{
    [self getUsersForLeaderboardFromServer];

    MainMenuView *mainMenu = [[[MainMenuView alloc] init] autorelease];
    [self.navigationController pushViewController:mainMenu animated:YES]; 
}
}

所以同样的isChecked变量,当通过点访问它时,在应用程序didFinishLaunchingWithOptions方法中使用时,片刻(实际上远不到一刻)等于YES等于NO。这是怎么回事?我能够处理它,但我只是对这种情况感到好奇。你知道它有什么问题吗?

1 个答案:

答案 0 :(得分:2)

您在init中重新分配self,因此您将返回新对象而不是您设置isChecked的对象。看到这段代码:

self         = (Profile *) [NSKeyedUnarchiver unarchiveObjectWithData:data];
[self retain];

做你喜欢的事情有点尴尬 - 我肯定不会建议你用你的方式替换它。首先,当您重新分配currentProfile时,您设置为静态self的值不会更新,因此仍然是旧版本。而且,当你重新分配时,你也不会发布旧的self

要解决此问题,您可以执行以下操作:

id newSelf         = (Profile *) [NSKeyedUnarchiver unarchiveObjectWithData:data];
newSelf.isChecked = isChecked;
[self release];
self = [newSelf retain];

但我个人并不真正提倡这一点。我建议您从归档中加载对象,然后继续使用它更新自己,而不是重新分配自己。