8

私はここで少し混乱しています、私はキューを使用しています、そして私は私が少し失われるポイントに到達しました。

getPeopleサーバーからユーザーの写真を取得する必要があるという名前のメソッドがあります。アプリをブロックしないために、私はこれを使用しました:

 -(IBAction)seeMorePeople{
        dispatch_queue_t getPeopleQueue = dispatch_queue_create("Pinta Ocupantes", NULL);
        dispatch_async(getPeopleQueue, ^{
           [self getPeople];
        });
       dispatch_release(getPeopleQueue);
 }

前のコードは、ユーザーがボタンをタップするたびに実行されます。「このアルバムの写真をください」のように、次に「他のアルバムの写真が欲しい」をタップすると、さまざまな写真とさまざまな量の写真が表示されます。ユーザーがボタンを非常に速くタップすると、2番目のキューがすでに開始されているときに、最初のキューはデータのフェッチを終了しません。を使用するgetPeopleと、データがNSMutableArrayに格納されるため、2つのキューが同時に実行されている場合、両方が同じ配列に書き込みを行っており、範囲外の例外が原因でアプリがクラッシュします。getPeopleデータを通過する方法は次のようなものです。

-(void)getPeople:(NSDictionary *)peopleDictionary{
    //I receive an NSDictionary and I go through it
    NSArray *keys = [peopleDictionary allKeys];
    int indexOfArray = 0;
    for(NSString *key in keys){
         //Complex operation that are not important
         [peopleInArray insertObjetAtIndex:indexOfArray];//People in array is a global variable
         indexOfArray++;
    }
}

私が理解できないのは、これから抜け出す方法です。2番目のキューが入ったときに最初のキューを停止することを考えましたが、GCDにはこのオプションがありません...これを行う他の方法、できればメジャーなしでとにかく今のところ再コーディングはアイデアがないので、どんな手がかりも役に立ちます。

4

3 に答える 3

12

可能であれば、セマフォとの同期を避けることをお勧めします。GCD の設計は、それを回避することです。バックグラウンド タスクはデータを準備する必要がありますが、外部の状態には触れないでください。データが準備されると、外部状態の更新をシリアル キューにディスパッチするか、状態が GUI にバインドされている場合はメイン キューにディスパッチする必要があります。

したがって、次のようなものです。

-(void)getPeople:(NSDictionary *)peopleDictionary{
    //I receive an NSDictionary and I go through it
    NSArray *keys = [peopleDictionary allKeys];
    for(NSString *key in keys){
         //Complex operation that are not important
         dispatch_async(dispatch_get_main_queue(), ^{
             [peopleInArray addObject:<whatever>];
         });
    }
}

2 つのスレッドをインターリーブ方式で配列に追加するのではなく、配列を置き換えたい場合は、配列全体をバックグラウンドで蓄積し、設定全体をpeopleInArrayメイン キューにディスパッチします。

キャンセルが必要な場合は、フラグを使用して自分で実装するか、GCD の代わりにNSOperationandを使用することを検討する必要があります。NSOperationQueueこれらにはキャンセルの概念が組み込まれていますが、カスタム操作ではキャンセルされたかどうかを確認して動作を停止する必要があります。

于 2012-04-11T17:17:20.097 に答える
2

そうです、ディスパッチされたキューを停止する方法はありません。getPeople同時にアクセスするキューが 1 つだけであることを確認するためにできることの 1 つは、セマフォを使用することです(これはさらに興味深いかもしれません)。

ユーザーがボタンを複数回クリックするのを避けたい場合は、非同期ディスパッチで に設定され、 の最後で に設定される bool 変数stillExecutingを使用できます。作成する前に、がまだ実行されているかどうかを確認するだけです。YESNOgetPeoplegetPeopleQueuegetPeople

if(!stillExecuting) {
       dispatch_queue_t getPeopleQueue = dispatch_queue_create("Pinta Ocupantes", NULL);
        dispatch_async(getPeopleQueue, ^{
           [self getPeople];
        });
       dispatch_release(getPeopleQueue);
}
于 2012-04-11T16:06:43.053 に答える
-1

NSString *lastLoginTime =@" 前回のログイン時間";

    NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
    [dateFormat setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
    NSDate* date1 = [dateFormat lastLoginTime];
    NSDate* date2 = [dateFormat dateFromString:[NSString currentDateTime]];
    NSTimeInterval secondsSinceLastLogin = [date2 timeIntervalSinceDate:date1];
    //  NSLog(@"Seconds Since Last Login: %g", secondsSinceLastLogin);
    int hours = (int)secondsSinceLastLogin / 3600;
于 2015-05-18T08:29:36.643 に答える