我一直坚持这一点,任何建议都会非常感激。我创建了一个名为SharedUser的单例对象,它表示当前正在使用该应用程序的用户。此SharedUser对象具有两个NSStrings(用于username和userId)和一个NSArray(用于用户所属的公司部门)。使用名为initWithUsername的方法登录时初始化用户。在此方法中,用户名用于解析用户并获取用户的唯一ID号和用户的部门。
我的问题如下:当我在应用程序中稍后让用户通过sharedUser方法时,userId字符串为空并在我尝试使用它时导致exc_bad_access错误。我知道userId字符串正在初始化,因为我在调试器中发现了这种情况。但是,奇怪的是,对于缺少userId字符串的同一对象,用户名字符串仍然存在。我很困惑如何释放userId后面的内存,而用户名仍然会挂起。
我的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_access错误。
SharedUser *user = [SharedUser sharedUser];
NSLog(@"%@", user.username);
NSLog(@"%@", user.userId);
那就是说,我的问题是userId字符串被释放后面的内存在哪里,我该怎么做才能修复它?我是堆叠溢出的新手,所以请保持温和。
答案 0 :(得分:0)
userId
。该值归personDictionary
所有,listOfPeopleDictionaries
由[responseString JSONValue]
拥有,这是userId
的自动释放返回值。清除自动释放池后,将释放整个链,包括userId = [[personDictionary objectForKey:@"id"] retain];
。
解决方案是通过执行
来保留userIdself.userId = [personDictionary objectForKey:@"id"]
或
username
initWithUserName:
有同样的问题,但可能没有崩溃,因为你在调用{{1}}的对象中坚持它。
答案 1 :(得分:0)
我可能会选择其他解决方案:“普通”类,它提供一个共享实例,而不会打扰所有内存(非)管理
我想提出新的宏观中央调度方法
@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;