Providing a second choice if primary choice not found in a ReactiveCocoa signal chain

StackOverflow https://stackoverflow.com/questions/22625045

  •  20-06-2023
  •  | 
  •  

سؤال

I have the following code that runs through a series of image records, tries to find a record that's marked "primary", loads it, and assigns it to a UIImageView:

    // When there's a new image, fetch it, and set the headerView (which by default is an UIImageView)
RAC( self, imageView.image ) =

    // Return a sequence for photos
    [[[[[[self modelImagesSignal] ignore:nil] flattenMap:^RACStream *(NSDictionary *photos)
        {
        NSLog(@"Got photos: %@" , photos) ;
        return photos.rac_sequence.signal ;
        }]

    // Consider each photo
    filter:^BOOL(NSDictionary *photoDescriptor)
        {
        NSLog(@"Descriptor: %@" , photoDescriptor) ;
        return ((NSNumber *)photoDescriptor[@"primary"]).boolValue ;
        }]

    // Load the selected photo
    flattenMap:^RACStream *(NSDictionary *selectedPhotoDescriptor)
        {
        NSLog(@"selected photo desc: %@" , selectedPhotoDescriptor) ;
        return [AsyncImageFetcher imageAtURL:[NSURL URLWithString:selectedPhotoDescriptor[@"url"]] cache:YES] ; // This will -deliverOn: the main thread
        }]

    // Catch errors
    catch:^RACSignal *(NSError *error)
        {
        FLASH_REPORT_T(error.description, nil, xkFlashMessageTypeError) ;
        return [RACSignal empty] ;
        }] ;
  1. If there is no primary, I'd like to return the first record encountered, whether it's primary or not, and
  2. If there aren't any records encountered at all, I'd like to return a default image.

How can I do these?

هل كانت مفيدة؟

المحلول

  1. If there is no primary, I'd like to return the first record encountered, whether it's primary or not, and
  2. If there aren't any records encountered at all, I'd like to return a default image.

This isn't using your original code, but extracting out the basics of what you are asking for, here is one way to compose signals to get what you want:

MyImageModel *myDefaultImageModel = [self createDefaultImageModel];

RACSignal *images = [self fetchImagesOrWhatever];
RACSignal *primaryImages = [images filter:^(MyImageModel *im) { return im.isPrimary; }];
RACSignal *defaultImage = [RACSignal return:myDefaultImageModel];

// This is the line to pay attention to:
RACSignal *finalImage = [[[primaryImages concat:[images concat:defaultImage]]] take:1];

RAC(self, imageView.image) = [finalImage map:^(MyImageModel *im) {
    // Convert MyImageModel to a UIImage here, and return it.
}];

This code constructs one signal, called finalImage, that consists of the following values, in order:

  1. Every image that is marked "primary".
  2. The first image (from the same signal of images that fed #1).
  3. A default image.

and then uses -[RACSignal take:1] to take the first of these. If #1 or #2 could be empty signals (because there are no primaries or no images at all), you know that you will at least get #3.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top