ioswatchkitwkinterfaceimage

WatchKit: image not shown


Here are the codes:

@interface InterfaceController()
@property (nonatomic, weak) IBOutlet WKInterfaceImage *qrImage;
@property (nonatomic, weak) IBOutlet WKInterfaceLabel *label;
@end

@implementation InterfaceController
- (void)awakeWithContext:(id)context {
    [super awakeWithContext:context];
    [self.label setText: @"Welcome"];
    UIImage *image = [InterfaceController generateQRCodeWithString:@"Welcome"];
    [self.qrImage setImage:image];
}

- (void)willActivate {
    [super willActivate];
}

- (void)didDeactivate {
    [super didDeactivate];
}

+ (UIImage *)generateQRCodeWithString:(NSString *)string {
    NSData *stringData = [string dataUsingEncoding:NSUTF8StringEncoding];
    CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
    [filter setValue:stringData forKey:@"inputMessage"];
    [filter setValue:@"M" forKey:@"inputCorrectionLevel"];

    CIImage *input = filter.outputImage;
    CGAffineTransform transform = CGAffineTransformMakeScale(10.0f, 10.0f);
    CIImage *output = [input imageByApplyingTransform: transform];

    return [UIImage imageWithCIImage:output];
}
@end

I'm trying to generate a QR code from some specific text and show it in the watch interface. The problem is that the UIImage generated by generateQRCodeWithString: is never shown. However, if I load an image with [UIImage imageNamed:@"XXX.png"] from the WatchKit Extension bundle, it's shown properly.

I'm not sure what's going on. What did I miss? Thanks in advance.


UPDATE: In response to msk, yes I'm pretty sure. I tried to NSLog the image, it gives <UIImage: 0x7fc261d276e0>, {230, 230}


Solution

  • The image returned from generateQRCodeWithString: isn't a "real" image (to be brief) and hasn't been fully rendered out. Think of the CIImage as a concept of what the image should look like rather than actual pixels.

    Replace the return line in generateQRCodeWithString: with something like this:

    CGImageRef cgOutput = [[CIContext contextWithOptions:nil]
                           createCGImage:output fromRect:output.extent];
    return [UIImage imageWithCGImage:cgOutput];
    

    That will render the QR code to a CGImage to turn it into pixels, and then on to a UIImage.

    Creating the CIContext is relatively expensive and if you're generating a lot of QR codes, the context should be static or something and initialized once. But for a one-off, it should be fine.