所以我仍然是Objective-C的新手,这是我第一个正在更新的应用程序。这个想法是这样的:整个应用程序基本上是各种各样的东西。它要求API发布15个帖子,显示那些带有“加载更多”按钮的帖子。单击“加载更多”,它会加载15个,等等。加载它们的API具有内置超时的令牌系统。请求之间的时间太长,您必须获得新令牌。所以我想在我的应用程序中的任何地方使用单例,这样我就可以[APIMachine getToken]
并在幕后,它检查自上次请求以来的时间是否太长(或者这是第一个请求),如果所以,得到一个新的令牌,否则返回我们已经拥有的令牌。我正在遵循我在很多地方找到的单例模式,但每次“加载更多”按钮使用[APIMachine getToken]
时,它都会获得任何内容或完全随机的内容。我把它打印在日志中,有一次我甚至得到了一个UITableViewCell作为我的令牌。看起来变量被某种方式覆盖了。但我真的无法弄明白。
所以这是:
static PoorAPI2 *_instance;
@implementation PoorAPI2
@synthesize apiToken, timeOpened, tokenTTL;
+ (PoorAPI2*)sharedAPI
{
@synchronized(self) {
if (_instance == nil) {
_instance = [[super allocWithZone:NULL] init];
}
}
return _instance;
}
-(NSString *)API_open{
//boring code to get api token redacted
if ([doneness isEqualToString:@"success"]) {
NSDictionary *data = [json objectForKey:@"data"];
apiToken = [data objectForKey:@"api_token"];
tokenTTL = [data objectForKey:@"ttl"];
timeOpened = [NSDate date];
}else{
NSLog(@"FFFFFFFUUUUUUUUUUUU this error should be handled better.");
}
return apiToken;
}
-(BOOL)isConnectionOpen{
return ([timeOpened timeIntervalSinceNow] > tokenTTL);
}
-(NSString *)getToken{
if([self isConnectionOpen]){
return apiToken;
}else{
return [_instance API_open];
}
}
-(id)init{
if(self = [super init]){
apiToken = [[NSString alloc] initWithString:@""];
timeOpened = [[NSDate alloc] initWithTimeIntervalSinceNow:0];
tokenTTL = 0;
}
return self;
}
+ (id)allocWithZone:(NSZone *)zone
{
return [[self sharedAPI]retain];
}
- (id)copyWithZone:(NSZone *)zone
{
return self;
}
- (id)retain
{
return self;
}
- (unsigned)retainCount
{
return NSUIntegerMax; //denotes an object that cannot be released
}
- (void)release
{
//do nothing
}
- (id)autorelease
{
return self;
}
@end
我只能希望我做一些非常愚蠢的事情,这将是一个热闹的点对点笑话。然后至少我的应用程序将工作。
答案 0 :(得分:2)
在API_open
中,您将三个对象存储在实例变量中,但它们不是您拥有的对象,因此它们可能会在您需要它们时消失,并被不可预测的内容替换。你需要保留它们或使用适当的制定者。
答案 1 :(得分:0)
你的问题是:
static PoorAPI2 *_instance;
C,并且通过继承Objective-C,不要初始化变量。只需改为:
static PoorAPI2 *_instance = nil;
此外,我也是学校,添加额外的代码以防止将单例作为单个使用是完全浪费时间,并且只为您提供更多可能存在错误的代码。
所以,如果我是你,那么我会从+[PoorApi2 allocWithZone:]
中删除所有方法。 Objective-C是一种动态语言,如果客户想要实例化你的单例的第二个实例,那么尽管你浪费了额外的代码行,它仍然可以这样做。我最多会添加一个这样的日志:
-(id)init{
if (_instance) NSLog(@"WARNING: PoorAPI2 already has a shared instance.");
if(self = [super init]){
apiToken = [[NSString alloc] initWithString:@""];
timeOpened = [[NSDate alloc] initWithTimeIntervalSinceNow:0];
tokenTTL = 0;
}
return self;
}
创建单例的第二个实例是编程错误,应该在开发中捕获。不是问题,你应该添加额外的代码行来隐藏。