0

NSMutableArrayaとaの2つのivarを持つ単純なクラスがありBOOLます。このクラスのオブジェクトは、メッセージが送信されるときに配列内の要素をシャッフルできstartShufflingます。彼らはstopShufflingメッセージを受け取るまでそうします。

これを機能させるには、startShufflingメソッドでブール値をに設定してからYES、シャッフルするコードのブロックをディスパッチします(while(self.isShuffling) { //... }並行キューで。stopShufflingブール値をNOに設定して、シャッフルプロセスが次のループターンで終了するようにします。

これがインターフェースです:

@interface MyClass : NSObject <NSCoding> {
@private
    NSMutableArray *elements_;
    __block BOOL isShuffling_;
}

@property(readonly) BOOL isShuffling;

-(void)startShuffling;
-(void)stopShuffling;

@end

そして実装:

@implementation MyClass

@synthesize isShuffling = isShuffling_;

-(void)startShuffling {
    if(self.isShuffling) {
        return;
    }

    isShuffling_ = YES;

    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_async(queue, ^{
        while(isShuffling_) {
            // code that shuffles, one element by turn
            NSUInteger elementIndex = arc4random() % [elements_ count];
            id c = [[elements_ objectAtIndex:elementIndex] retain];
            [elements_ removeObjectAtIndex:elementIndex];
            [elements_ insertObject:c atIndex:[elements_ count]];
            [c release];
        }
    });
}

-(void)stopShuffling {
    isShuffling_ = NO;
}

@end

私のクラスはNSCodingプロトコルに準拠しており、オブジェクトがシャッフルしている場合でもエンコードを中止したくありません。代わりに、オブジェクトのシャッフルを停止してから、オブジェクト自体をエンコードする必要があります。だから私はこのエンコーディングメソッドを書きました:

-(void)encodeWithCoder:(NSCoder *)aCoder {
    if(self.isShuffling) {
        [self stopShuffling];
    }
    [aCoder encodeObject:elements_ forKey:kIVPCodingKeyMyClassElements];
}

最後に、私の質問です。
シャッフルループが最後のターンを終了している間にメソッドが呼び出される可能性があると思いますencodeObject:forKey:(おそらく私は間違っていますか?)。

最後のターンでシャッフルループが終了するのを待った、メソッドを呼び出させるencodeObject:forKey:方法はありますか?

4

1 に答える 1

2

はい、encodeObject:forKey:メソッドが呼び出されたときにシャッフルコードがまだ実行されている可能性があります。

一般に、非常に長い時間、場合によっては永久に実行されるキューにランダムなブロックをディスパッチすることは望ましくありません。作業を作業のブロックに分割したいとします。そしてそこにあなたの答えがあります。

何かのようなもの:

 - (void)shuffleAndCheck
 {
    if (stillShuffling) {
         dispatch_async(globalConcurrentQueue, ^{
              dispatch_apply(shuffleQueue, ^{... shuffle one card code ...});
         });
         dispatch_async(shuffleQueue, ^{ [self shuffleAndCheck]; });
    }
 }

 - (void) startShuffling
 {
    if (stillShuffling) return;
    stillShuffling = YES;
    [self shuffleAndCheck];
 }

 - (void) stopShuffling
 {
    stillShuffling = NO;
    dispatch_async(shuffleQueue, ^{ ... encode stuff here ... });
 }

か何か。

于 2012-08-07T21:33:16.973 に答える