如何使用SVGKit渲染引用iOS设备照片的SVG XML字符串?



所以,我的基本问题是:

是否有一种方法在iOS上使用SVGKit来渲染包含引用本地图像的SVG ?

血淋淋的细节

我的应用程序需要生成和渲染SVG (XML在一个NSString)。XML将引用设备(在Camera Roll中)上的图像url。我在iOS上使用SVGKit。我能够使用以下方法从图像PHAssets获得url(参见: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);
    }];
}

然后在生成的SVG XML字符串(这个字符串是在模拟器中生成的)中使用该图像URL:

<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 try

我试图使用SVGKSourceString来创建一个SVGKImage,但是这会为本地图像URL返回一个空白图像(远程URL引用工作良好)。这里的"空白图像"是指具有大小但没有图像内容的非nil对象。

// 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
}

我注意到在模拟器上,如果我从设备上的文件读取SVG内容,它工作。我觉得很奇怪,不过无所谓了。当它从文件中读取SVG内容时,它必须以不同的方式处理URL引用。我把NSString变成一个NSInputStream,然后使用SVGSourceLocalFile。initWithInputStream:创建SVGKSourceLocalFile,它也在模拟器上工作。在呈现的SVG中引用的本地图像。(注意:我必须设置filePath与一个假的文件名,以防止imageWithSource爆炸。)

但是,遗憾的是,这在真正的设备上不起作用。SVGKImage imageSource:返回一个空白图像。

// 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];
}

我强烈怀疑它不喜欢设备URL引用。我知道从PHAsset获得通用URL存在问题。模拟器上的URL在Safari模拟器中工作。但是我在真实设备上得到的URL(看起来像"file:///var/mobile/Media/DCIM/102APPLE/IMG_2405.JPG")在设备的Safari应用程序上不工作。我还尝试将PHAsset转换为ALAssetURL..(参见StackOverflow:how-to-get-an-alasset-url-from-a-phasset),但这也不起作用。这也返回一个空白图像。

版本细节
  • iOS版本:10.0.2(真实设备),各种版本在sim卡(8.4,9.3,10.0)
  • SVGKit版本:pod 'SVGKit',:git => 'https://github.com/SVGKit/SVGKit.git',:branch => '2.x'

SVGKit使用Apple自己的类来解析这些URL,并且不对它们进行额外处理。

所以…如果你得到的是一个nil图像,你可能会破坏NSURL自己的解析能力——c.f Apple的docs.

然而

…如果你运行Xcode调试器,在SVGKit SVGKSourceXXXXX类上设置一个断点,你正在使用,并在设备上运行,你应该能够很容易地实时看到什么是失败的,在哪里-我的猜测是NSURL,但你可以确认这一点。

最新更新