次のように作成されたシグナルをサブスクライブします。
RACSignal *signal = [[RACSignal createSignal:^(... subscriber) {
for (int i = 0; i < 100; i++) {
[subscriber sendNext:[[RACSignal createSignal:^(... subscriber2) {
NSString *string = someFunctionThatTakesALongTime(i);
[subscriber2 sendNext:string];
[subscriber2 sendComplete];
return nil;
}] setNameWithFormat:@"inside signal"]];
}
[subscriber sendComplete];
return nil;
}] setNameWithFormat:@"outside signal"];
int n = 4;
[[signal flatten:n] subscribeNext:^(NSString *string) { ... }];
シグナルを並行し-flatten:
てサブスクライブしたい。n
「内部信号」を試し-startLazilyWithScheduler:block:
てみ[RACScheduler scheduler]
ましたが、コンピューターが停止します。Instrumentsでは、シグナルごとに新しいスレッドを作成しているようです。
このコードの以前のバージョンは、NSOperations として NSOperationQueue に追加され、n
操作を並行して実行するように設定されています。それは機能しますが、RAC を使用して簡単にフォローできるようにすることができます。
内部シグナルがそれぞれ同じスレッド-flatten:
n
で実行されるように、シグナルのシグナルから一度にシグナルを送信するにはどうすればよいですか?n
=====================================
更新:私は間違ったツリーを吠えていました。私のパフォーマンスの問題は、物理 RAM の不足によるものでした。一部のオブジェクトの寿命が長すぎて、メモリの問題が発生したと思います。RAC をより頻繁に使用するようにリファクタリングしているときに、ある時点でメモリ使用量の問題を偶然解決しました。人々が私のコードを見ることで恩恵を受けるかどうかはわかりませんが、ここにあります:
私はこのコードで外側の信号を消費することから抜け出しました:
[[[self drawRects] flatten:self.maxProcesses] subscribeNext:^(NSDictionary *result) {
@strongify(self);
NSString *keyString = result[kDrawRectsResultsKeyKey];
self.imagesByLocation[keyString] = result[kDrawRectsResultsImageKey];
self.repsByLocation[keyString] = result[kDrawRectsResultsRepKey];
[self setNeedsDisplayInRect:[result[kDrawRectsResultsRectKey] rectValue]];
}];
代わりに、より多くの RAC 操作を使用するには (同じクラスの他の命令型コードも置き換えます):
// Get the latest zoomed drawing bounds and get the latest imageProvider's latest imagesByLocation
// Skip one of each signal to avoid firing immediately
RACSignal *zoomedDrawingBounds = [RACChannelTo(self, zoomedDrawingBounds) skip:1];
RACSignal *imagesFromImageProvider = [[[RACChannelTo(self, imageProvider) skip:1]
map:^(id<PTWImageProvider> imageProvider) {
return RACChannelTo(imageProvider, imagesByLocation);
}]
switchToLatest];
// Lift the drawing method, getting a signal of signals on each call
RACSignal *drawingSignals = [[self rac_liftSelector:@selector(drawingSignalsForRect:givenImagesByLocations:)
withSignalsFromArray:@[ zoomedDrawingBounds, imagesFromImageProvider, ]]
switchToLatest];
@weakify(self);
// Lift flatten: using maxProcesses so that if maxProcesses changes, the number of signals being
// flatten:ed can change almost immediately.
RACSignal *drawnRectanglesZoomed = [[[[drawingSignals
rac_liftSelector:@selector(flatten:) withSignalsFromArray:@[ RACChannelTo(self, maxProcesses) ]]
switchToLatest]
doNext:^(NSDictionary *result) {
@strongify(self);
// side effects! store the rendered image and its associated image rep
NSString *keyString = result[kDrawRectsResultsKeyKey];
self.imagesByLocation[keyString] = result[kDrawRectsResultsImageKey];
self.repsByLocation[keyString] = result[kDrawRectsResultsRepKey];
}]
map:^(NSDictionary *result) {
// Extract the drawn rect from the results
return result[kDrawRectsResultsRectKey];
}];
RACSignal *drawnRectangles = [[drawnRectanglesZoomed
combineLatestWith:RACChannelTo(self, zoomLevel)]
map:^(RACTuple *tuple) {
// Convert between zoomed and unzoomed coordinates
CGRect zoomedRect = [[tuple first] rectValue];
CGFloat zoomLevel = [[tuple second] floatValue];
CGAffineTransform zoomTransform = CGAffineTransformMakeScale(zoomLevel, zoomLevel);
return [NSValue valueWithRect:CGRectApplyAffineTransform(zoomedRect, zoomTransform)];
}];
// Lift setNeedsDisplayInRect: with results from the drawing signals, so setNeedsDisplayInRect: is called
// as tiles are rendered.
[self rac_liftSelector:@selector(setNeedsDisplayInRect:)
withSignalsFromArray:@[ [drawnRectangles deliverOn:[RACScheduler mainThreadScheduler]] ]];
バックグラウンド スケジューラでコールド シグナルを返すように作業メソッドを更新すると、flatten:
問題なく複数のシグナルが一度に実行されます。
RACSignal *signal = [[RACSignal createSignal:^(... subscriber) {
for (int i = 0; i < 100; i++) {
[subscriber sendNext:[[RACSignal startLazilyWithScheduler:[RACScheduler scheduler] block:^(... subscriber2) {
NSString *string = someFunctionThatTakesALongTime(i);
[subscriber2 sendNext:string];
[subscriber2 sendComplete];
}] setNameWithFormat:@"inside signal"]];
}
[subscriber sendComplete];
return nil;
}] setNameWithFormat:@"outside signal"];