0

問題の説明

StdString ShowLockScreen()この関数には、ユーザーがPINを入力する必要があるUIを表示する関数を呼び出します。関数を呼び出しactivateViewControllerた直後に、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];、その後[theLockunlock]を呼び出します。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];

しかし、これを私のコードでどのように使用するのですか?

4

3 に答える 3

1

問題への回答

を使用してスレッドをロックできますNSLockが、状況によっては、これは当てはまらないようです。その理由は、データが複数のスレッドからアクセスされるときに、ロックは主にスレッドセーフを提供するために使用されるためです。求めているのはドメインレベルのロックです。これにより、ユーザーはPINを入力しない限りアプリケーションを使用できなくなります。これらの2つの概念は「ロック」という言葉を共有していますが、実装はまったく異なります。とそれに関連する対応物を使用する場合はNSLock、純粋にユーザーの操作をブロックするために実装を個別のスレッドに強制し、プロジェクトを複雑にし、デバッグに苦労するリスクがあります(デッドロックが多いですか?)。

推奨される解決策

概念はドメインレベルのロックメカニズムであるため、実装のためにこの方法を維持することをお勧めします。Androidに類似させたい場合は、他のすべてがクエリする「SharedObject」の独自の概念を作成する必要があります。このオブジェクトが「ユーザーがアプリケーションのロックを解除していない」と言った場合、何も処理されません。これにより、スレッドを手動で管理する必要がなくなり、スレッドを本当に必要なときに解放します(たとえば、非同期処理)。

このオブジェクトを実装するにUserContextは、シングルトンとして使用できるをと呼びましょう。このsharedInstanceを実装する方法は、ここで確認できます

それができたら、アプリケーション全体でグローバルなさまざまなプロパティを追加できます(名前の提案により、特定のユーザーに属するすべてのグローバルプロパティがあります)。これらのプロパティの1つは、ユーザーがアプリをロックしているかどうかです。

[[UserContext sharedInstance] isLocked] // Returns BOOL

これをアプリケーション全体で使用すると、メソッドが何かを計算できるかどうかを(ドメインの概念レベルで)制御できます(当然、UserContextいつでもどこでもクエリできるため、スレッドセーフにする必要があります)。コードを読んでいる開発者には、ユーザーがアプリのロックを解除しない限り、特定のメソッドでは何もできないことが明らかになります。止まる

サイドノート

コードを停止してから呼び出し、UIから[theLock lock];呼び出した後、コードは実行を継続します。[theLock unlock];

いかなる状況でも、UIスレッドをロックしないでください。公開されたアプリでは、ウォッチドッグがアプリを強制終了し、事実上クラッシュします。

于 2012-11-26T13:44:39.663 に答える
0

ViTo、私がNSLockに関心を持っているのと同じように、特定のスレッドをロックし、ロックを解除しないまで、他のスレッドがアクティブになったり、必要なタスクを実行したりしないマルチスレッドの場合に使用します。したがって、最初にすべてのプロセスをスレッドの観点から開始し、UIを開こうとしたときに「ロック」と呼び、ユーザーがテキストを入力した後にボタンを押したときに、私たちができることかもしれません-ボックスの場合、「ロック解除」と呼びます。ただし、このためには、このスレッドの優先度が高いことを確認する必要があります。それは私が今考えていることですが、実際に私のサンプルコードでこれを試してみて、それに応じて更新します。

コードのその部分を確認してください。

+(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];
}

必要なものが得られるログを確認してください。願わくば、それはあなたが必要とするものです。心配なことは、私を怒鳴りつけてください。

于 2012-11-26T12:21:06.200 に答える
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]!!!")
}
于 2012-11-27T08:19:06.060 に答える