Objective c objective c中的单例对象内存问题

Objective c objective c中的单例对象内存问题,objective-c,cocoa-touch,memory-management,singleton,exc-bad-access,Objective C,Cocoa Touch,Memory Management,Singleton,Exc Bad Access,我在这个问题上已经坚持了一段时间,任何建议都将不胜感激。我创建了一个名为SharedUser的单例对象,它表示当前正在使用该应用程序的用户。此SharedUser对象有两个NSString(用于用户名和用户ID)和一个NSArray(用于用户所属的公司部门)。用户在登录时使用名为initWithUsername的方法初始化。在该方法中,用户名用于解析用户并获取用户的唯一id号和用户的部门 我的问题如下:当我稍后在应用程序中通过sharedUser方法获取用户时,userId字符串为空,并在我尝试

我在这个问题上已经坚持了一段时间,任何建议都将不胜感激。我创建了一个名为SharedUser的单例对象,它表示当前正在使用该应用程序的用户。此SharedUser对象有两个NSString(用于用户名和用户ID)和一个NSArray(用于用户所属的公司部门)。用户在登录时使用名为initWithUsername的方法初始化。在该方法中,用户名用于解析用户并获取用户的唯一id号和用户的部门

我的问题如下:当我稍后在应用程序中通过sharedUser方法获取用户时,userId字符串为空,并在我尝试使用它时导致exc_bad_访问错误。我知道userId字符串正在初始化,因为我在调试器中观察到了这种情况。然而,奇怪的是,对于缺少userId字符串的同一对象,username字符串仍然存在。我很困惑userId背后的内存是如何被释放的,而username仍然挂着

我的SharedUser类如下所示:

@implementation SharedUser
@synthesize userId;
@synthesize username;
@synthesize departmentIds;

static SharedUser *sharedUser = nil;

+(SharedUser *)sharedUser {

@synchronized(self) {
        if (!sharedUser) {
            sharedUser=[[self alloc] init];
        }
    }
    return sharedUser;
}

+ (id)allocWithZone:(NSZone *)zone {
    @synchronized(self) {
        if (sharedUser == nil) {
             sharedUser = [super allocWithZone:zone];
             return sharedUser;
        }
    }

    return nil;
}

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


- (id)retain {
    return self;
}


- (unsigned)retainCount {
    return NSUIntegerMax;
}


- (oneway void)release {
    // never release
}


- (id)autorelease {
    //do nothing
}


- (id) init {
    @synchronized(self) {
        [super init];
        username = @"";
        userId = @"";
        departmentIds = nil;
        return self;
    }
}


- (void) initWithUserName:(NSString *) loginName {

    username = loginName;

    //create a request and a connection    
    NSURL *url = [NSURL URLWithString:@"http://blah.com/url/for/the/json/"];   
    ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
    [request startSynchronous];
    NSError *error = [request error];

    if (!error) { 
        NSString *responseString = [request responseString];
        NSArray *listOfPeopleDictionaries = [responseString JSONValue];

        for (NSDictionary *personDictionary in listOfPeopleDictionaries) {
             if ([loginName isEqualToString:[personDictionary  objectForKey:@"username"]]) {
                // Set the user id
                userId = [personDictionary objectForKey:@"id"];

                // Set the user's department
                NSArray *departmentsArray = [personDictionary objectForKey:@"organizations"];
                for (NSDictionary *department in departmentsArray) {
                    [departmentIds addObject:[department objectForKey:@"id"]];
                }
             }
         }
     }
     else {
        //give error
     }
 }

- (void)dealloc {
    // Should never be called
    [username release];
    [userId release];
    [departmentIds release];
    [super dealloc];
}
以下代码将导致第三行出现exc_bad_访问错误

SharedUser *user = [SharedUser sharedUser];
NSLog(@"%@", user.username);
NSLog(@"%@", user.userId);

这就是说,我的问题是,释放userId字符串背后的内存在哪里?我该如何修复它?我是stack overflow的新手,所以请温柔一点。

userId
不会被您的单身汉保留。该值归
personDictionary
所有,该值归
ListofPeopleDictionary
所有,它是从
[responseString JSONValue]
自动返回的返回值。当自动释放池被清除时,整个链被释放,包括
userId

解决方案是保留userId,或者

userId = [[personDictionary objectForKey:@"id"] retain];


username
也有同样的问题,但当您在调用
initWithUserName:
的对象中保留它时,它可能不会崩溃。我可能会使用另一个解决方案:“normal”类,它提供一个共享实例,而它不需要考虑所有的内存(非)管理

我想提出新的中央大调度方法

@implementation User
@synthesize userId;
@synthesize username;
@synthesize departmentIds;

+ (User *)sharedUser {
    static User *_sharedUser = nil;
    static dispatch_once_t oncePredicate;
    dispatch_once(&oncePredicate, ^{
        _sharedUser = [[self alloc] init…];
        //what ever is needed to get a proper shared user
    });
    return _sharedUser;
}

@end
如果您对不太严格的单例版本满意,则不需要更多

这在单元测试中也更容易处理

User *sharedUser = [User sharedUser];

若要修复代码,请重试

username = [loginName copy];  //or retain, if you use retain in ur property
而不是

username = loginName;

共享用户…听起来很有趣-就像一个开放的关系…
username = loginName;