如何在iOS应用程序中锁定代码执行

时间:2012-11-26 11:40:39

标签: c++ ios cocoa-touch locking nslock

问题描述

我在这个函数中有一个函数StdString ShowLockScreen()我调用了activateViewController函数,它显示了一些用户必须输入PIN的UI,只需在调用activateViewController函数后我想锁定所有进程直到用户将输入他的PIN并在打开的UI上按OK按钮。您可以在下面看到我尝试的代码

iOS中的源代码

StdString ShowLockScreen() 
{
    // Create a lock.
    NSLock* theLock = [[NSLock alloc] init];
    // Create a UI in which user must enter his PIN.
    PinLockController* controller = [[PinLockController alloc] initWithStyle:PinLockTypeSet];
    // Set delegate. 
    controller.delegate = m_Context;

    // !!! Here I show a UI and just after that I lock my lock in order code stop executing there.
    [controller activateViewController:nil];

    @synchronized(theLock) {
        [theLock lock];
    }

    NSLog(@"User in UI unlock the lock");
}

我希望我的代码停止然后我调用[theLock lock];然后我会调用[theLock unlock];从我的UI和代码将继续执行。但它在我的情况下不起作用。

Android中的源代码

我在Android中编写了类似的应用程序,这里是代码。我想在iOS中编写相同但我可以找到解决方案

Intent intent = new Intent(mCtx, SoftPinActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

SharedObject lock = new SharedObject("");
int lockId = SharedObject.acquireLockId(lock);
Logger.i(TAG, "lockId = " + lockId);
intent.putExtra(SharedObject.LOCK_ID, lockId);
intent.putExtra(SoftPinActivity.UI_ID, style);

synchronized (lock) {
   mCtx.startActivity(intent);
   try {
          Logger.i(TAG, "lock.wait()...");
          lock.wait();
   } catch (InterruptedException e) {
          e.printStackTrace();
          Logger.i(TAG, "InterruptedException");
   }
}
Logger.i(TAG, "lock.wait()...done");
SharedObject.releaseLockId(lockId);

String pin = lock.object();

研究

我想我必须使用

NSCondition* condLock = [[NSCondition alloc] init];
[condLock wait];

[condLock signal];

但如何在我的代码中使用它?

3 个答案:

答案 0 :(得分:1)

回答问题

您可以使用NSLock锁定线程,但在您的情况下,这似乎不适用。原因是锁定主要用于在从多个线程访问数据时提供线程安全性。你要求的是域级锁定,它阻止用户使用该应用程序,除非他们输入了他们的PIN。这两个概念共享“锁定”这个词,但它们的实现完全不同。如果您要使用NSLock及其相关的对应物,那么您强制将您的实现强制转换为单独的线程以阻止用户交互,并且会使您的项目变得复杂并且调试时会遇到麻烦(死锁很多?)。

建议的解决方案

由于这个概念是一个域级锁定机制,我建议我们保持这种方式来实现它。如果您希望它类似于Android,那么您需要创建自己的“共享对象”概念,以便其他所有查询。如果这个对象是“用户没有解锁应用程序”,那么什么都不会处理。这使您远离手动管理线程,并在最需要它们时释放线程(例如,异步处理)。

要实现此对象,我们可以将其称为UserContext,它可以作为单例使用。如何实现此sharedInstance can be seen here

一旦你拥有了它,你就可以为它添加各种属性,这些属性在整个应用程序中是全局的(并且通过名称的建议,具有属于特定用户的所有全局属性)。其中一个属性是用户是否已锁定应用程序:

[[UserContext sharedInstance] isLocked] // Returns BOOL

在整个应用程序中使用它,然后您可以控制(在域概念级别),方法是否可以计算某些东西(当然,您需要使UserContext线程安全,因为它可能是任何时候任何地方查询)。对于阅读代码的开发人员来说,除非用户已解锁应用程序,否则某个方法无法执行任何操作。停止

旁注

  

我希望我的代码停止,然后我调用[theLock lock];,之后我将从我的UI调用[theLock unlock];,代码将继续执行。

在任何情况下都不要锁定UI线程。在已发布的应用中,看门狗会终止你的应用,它会有效崩溃。

答案 1 :(得分:0)

ViTo,我和NSLock一样关注,我们在多线程的情况下使用它,在这种情况下我们锁定一个特定的线程并强制执行不解锁,没有其他线程变为活动或执行他所需的任务。 所以,我们可以做的就是首先我们以线程的方式开始你的所有进程,当你尝试打开你的UI时我们称之为'lock',当用户在输入文本后按下按钮时 - 然后我们称之为“解锁”。 但是,为此,我们确定该线程具有高优先级。 这就是我现在正在考虑的问题,但我真的尝试使用我的示例代码并相应地更新。

检查代码的一部分:

+(void)aMethod:(id)param{
 int x;
 for(x=0;x<50;++x)
 {enter code here
 [lock lock];
 printf("Object Thread says x is %i\n",x);
 usleep(1);
 [lock unlock];
 }
}

- (void)viewDidLoad
{    
 int x;
 lock = [[NSLock alloc] init];
 [NSThread detachNewThreadSelector:@selector(aMethod:) toTarget:[MViewController class] withObject:nil]; 
 for(x=0;x<50;++x)
 {
 [lock lock];
 printf("Main thread says x is %i\n",x);
 usleep(10000);
 printf("Main thread lets go %i\n",x);
[lock unlock];
 usleep(100);
 }
 printf("Now getting the process");
[super viewDidLoad];
}

检查日志,你会得到你想要的。 希望,这就是你所需要的。如果有任何顾虑,请大声喊叫。

答案 2 :(得分:0)

好的,我找到了解决这个问题的方法,下面你可以看到实现的功能和逐行描述。

StdString ShowLockScreen() 
{
    // Create NSCondition lock object.
    NSCondition* conditionLock = [[NSCondition alloc] init];

    // Here I create my UI which must ask user to enter PIN.
    PinLockController* controller = [[PinLockController alloc] initWithStyle:PinLockTypeSet];
    controller.delegate = m_Context;

    // Here I lock the thread but not main thread (this is very important) I start
    // ShowLockScreen function in new thread and lock it.
    [conditionLock lock];

    dispatch_sync(dispatch_get_main_queue(), ^{
        // I call function which shows my UI in main thread as UI can be shown 
        // only in MAIN THREAD. (This is important too.)
        [controller ShowLockController:conditionLock];
    });

    // Then I set lock to wait, how you can see I pass conditionLock as an 
    // argument to ShowLockController function in that function when user
    // enter his PIN and press okay button I call [conditionLock signal];
    // and my code code here after wait and continue executing.
    [conditionLock wait];

    NSLog(@"Come here then I call [conditionLock signal]!!!")
}