0

So, my basic question is:

Is there a way on iOS to use SVGKit to render SVG that contains references to local images?

Gory Details

My application needs to generate and render SVG (XML in an NSString). The XML will reference image URLs on the device (in the Camera Roll). I'm using SVGKit for iOS. I am able to get URLs from image PHAssets using the following (see: StackOverflow:nsurl-from-phasset ):

+ (void) getUrlFromPHAsset:(PHAsset *)asset 
         completionHandler:(void (^)(NSURL *url)) handler {

    PHImageRequestOptions *imgOptions = [PHImageRequestOptions new];
    PHContentEditingInputRequestOptions *options = 
                              [PHContentEditingInputRequestOptions new];
    imgOptions.version = PHImageRequestOptionsVersionCurrent;

    [asset requestContentEditingInputWithOptions:options 
            completionHandler:^(PHContentEditingInput * _Nullable contentEditingInput, NSDictionary * _Nonnull info) {
        handler(contentEditingInput.fullSizeImageURL);
    }];
}

I then use that image URL in my generated SVG XML string (this one was generated in the simulator):

<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="2175px" height="1537px" viewBox="0 0 2175 1537" style="background-color:#ffffff">

<defs>
    <clipPath id="my-uuid" clipPathUnits="userSpaceOnUse">  <rect x="1062" y="-1" width="1111" height="1538"/>
    </clipPath>
</defs>

<g clip-path="url(#my-uuid)">
    <image overflow="hidden" transform="translate(1062, -64.58393285371704) rotate(0, 555, 832)" x="0" y="0" width="1111" height="1665.167865707434" xlink:href="file:///Users/joe/Library/Developer/CoreSimulator/Devices/E8B8D888-93EC-4152-B0AD-B82D0C1B2FFE/data/Media/DCIM/100APPLE/IMG_0003.JPG"></image>
</g>
</svg>

What I've tried

I attempted to use SVGKSourceString to create an SVGKImage, but this returns a blank image for the local image URL (remote URL references work fine). By "blank image", I mean a non-nil object with a size, but no image content.

// DOESNT WORK on Simulator or real device
+ (SVGKImage *) svgImageFromString:(NSString *)text {
    SVGKSource *source = [SVGKSourceString sourceFromContentsOfString:svgText];
    SVGKImage *img = [SVGKImage imageWithSource:source]; // returns a blank image
}

I noticed on the simulator that if I read the SVG content from a file on the device, it worked. I thought that was weird, but, whatever. When it reads the SVG content from a file, it must handle URL references differently. So, I turned the NSString into an NSInputStream, then used SVGSourceLocalFile.initWithInputStream: to create the SVGKSourceLocalFile, and it too worked on the simulator. The local image referenced in the SVG rendered. (NOTE: I had to set filePath with a phoney file name to prevent imageWithSource from blowing up.)

But, sadly, this didn't work on a real device. SVGKImage imageSource: comes back with a blank image.

// WORKS ON THE SIMULATOR, not on a real device
+ (SVGKImage *) svgImageFromString:(NSString *)text {
    NSData *svgData = [text dataUsingEncoding:NSUTF8StringEncoding];
    NSInputStream *inp = [NSInputStream inputStreamWithData:svgData];
    SVGKSourceLocalFile *fsource = [[SVGKSourceLocalFile alloc] initWithInputSteam:inp];
    // hack: set filePath to prevent SVGKit from barfing
    fsource.filePath = @"foo.bar";
    return [SVGKImage imageWithSource:fsource];
}

I strongly suspect that it didn't like the device URL reference. I know there are issues getting a generic URL from a PHAsset. The URL on the simulator works in Safari simulator. But the URL I get back on the real device (looks like "file:///var/mobile/Media/DCIM/102APPLE/IMG_2405.JPG") did NOT work on the device's Safari app. I also tried converting the PHAsset to an ALAssetURL.. (see StackOverflow:how-to-get-an-alasset-url-from-a-phasset ), but that too, did not work. That also returns a blank image.

Version Details

Community
  • 1
  • 1
Joe Oguri
  • 1
  • 2

1 Answers1

0

SVGKit uses Apple's own classes to parse those URL's, and does no additional processing on them.

So ... if you're getting a nil image, you're probably breaking NSURL's own parsing capabilities - c.f. Apple's docs.

However ... if you run the Xcode debugger, set a breakpoint on the SVGKit SVGKSourceXXXXX class you're using, and run on device, you should be able to easily see in realtime what's failing and where - my guess is NSURL, but you could confirm this.

Adam
  • 32,900
  • 16
  • 126
  • 153