从多个UIViewControllers控制对webservice方法的访问

时间:2013-01-23 10:14:05

标签: ios objective-c nslock

我有一个带有标签栏和3个不同UIViewControllers的iOS应用,每个标签一个。该应用程序使用SudzC与C# .NET webservice接口以从数据库中提取数据。

从所有三个视图控制器调用一个webservice方法,但我想强制只有一个视图控制器可以在任何时间点调用该方法,并且在返回数据之前没有其他视图控制器可以调用它

我尝试通过在AppDelegate中定义NSLock,然后在每个viewController中实现以下代码来解决此问题:

if([SharedAppDelegate.loginLock lockBeforeDate:[[[NSDate alloc] init] dateByAddingTimeInterval:30.0]])
{
     // got the lock so call the webservice method
     SDZiOSWebService* webService = [SDZiOSWebService service];
     [webService Login:self action:@selector(handleRelogin:) username:userName password:password];
}
else
{
     // can't get lock so logout
     self->reloginInProgress = false;
     [SharedAppDelegate doLogout];
}

webservice返回的处理程序定义为(为清晰起见而截断)

-(void)handleRelogin: (id) result {
     SDZLoginResult *loginResult = (SDZLoginResult*)result;
     if(loginResult.Status)
     {
          SharedAppPersist.key = loginResult.key;
     }
     else
     {
          SharedAppPersist.key = @"";
     }
     [SharedAppDelegate.loginLock unlock];
}

我的理解是,第一个UIViewController将获得锁定,而其他人将阻止长达30秒等待获取锁定。但是,在极少数情况下,多个viewController同时尝试访问锁定,我立即收到以下错误:

*** -[NSLock lockBeforeDate:]: deadlock (<NSLock: 0x2085df90> '(null)')

谁能告诉我我做错了什么?我对C / C ++中的锁有很好的理解,但是这些Objective-C锁已经被困住了。

2 个答案:

答案 0 :(得分:0)

在我看来,你不应该为这个简单的案例使用锁(这是“邪恶的”)。

您可以尝试使用的是NSOperationQueue,设置为一次管理1个并发操作,然后让视图控制器将其Web服务调用入队:操作队列将保证一次只能执行一个操作执行。 操作队列的另一个优点是视图控制器可以检查队列是否为空,然后根据当前状态决定是否将其调用入队。 最后,您可以使用KVO观察队列状态,以便每个视图控制器可以在提交新请求之前检查这一点。

与使用NSOperationQueue类似,另一种可能性是创建一个私有GCD串行队列,并再次将所有Web服务请求排入队列(包含在块内)。虽然GCD串行队列比NSOperationQueues(恕我直言)更容易实现,但它们不具备可观察性和取消操作的可能性。

答案 1 :(得分:0)

如果它只是您想要一次访问Web服务的1个视图。你可以使用Singleton类。 这是网上许多例子之一的链接。 http://www.galloway.me.uk/tutorials/singleton-classes/

您也可以使用NSUserDefaults存储bool值,以通知您视图是否正在使用Web服务。 一个简单的例子是:

存储值

[[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"active_connection"];
[NSUserDefaults synchronize];

要检索

if(![[NSUserDefaults standardUserDefaults] boolForKey:@"active_connection"]) {
   [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"active_connection"];
   [NSUserDefaults synchronize];
   // Send request to web-service
}

我希望这会对你有所帮助。快乐的编码。!!