2013-01-23 15 views
0

我有一个iOS应用程序,带有一个tabbar和3个不同的UIViewControllers,每个标签一个。该应用程序使用SudzC与C# .NET webservice接口从数据库中提取数据。控制从多个UIViewControllers访问webservice方法

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

我试图通过在每个viewControllerAppDelegate限定NSLock,然后执行下面的代码来解决这个问题:

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锁已经难倒了。

回答

0

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

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

与使用NSOperationQueue类似,另一种可能性是创建一个私有的GC​​D串行队列,并再次入队所有Web服务请求(包装在一个块中)。虽然GCD串行队列比NSOperationQueues(IMHO)更直接,但它们不具备可观察性和取消操作的可能性。

0

如果它只是你想要1次浏览一次访问Web服务。你可以使用Singleton类。 下面是网络上众多例子之一的链接。 http://www.galloway.me.uk/tutorials/singleton-classes/

你也可以使用NSUserDefaults来存储一个布尔值来通知你一个视图是否使用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 
} 

我希望这可以帮助你。快乐编码。

+0

我想NSUSerDefaults解决方案中会存在各种各样的竞争条件。 Singleton解决方案可能会工作,但需要对SudzC库进行一些修改。感谢您的建议,但我一定会考虑辛格尔顿方法。 –

+0

欢迎您!只是不要忘记在这里提到什么对你有用,什么没有。因为这可能会在未来帮助一些同行的编码人员。干杯!! –