0

所以,我的基本问题是:

iOS 上有没有办法使用 SVGKit 来渲染包含对本地图像的引用的 SVG?

血腥细节

我的应用程序需要生成和呈现 SVG(NSString 中的 XML)。XML 将引用设备上的图像 URL(在相机胶卷中)。我正在使用适用于 iOS 的SVGKit。我可以使用以下方法从图像 PHAsset 中获取 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>

我试过的

我尝试使用SVGKSourceString创建一个SVGKImage,但这会为本地图像 URL 返回一个空白图像(远程 URL 引用工作正常)。“空白图像”是指具有大小但没有图像内容的非零对象。

// 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'
4

1 回答 1

0

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

所以......如果你得到一个 nil 图像,你可能会破坏 NSURL 自己的解析能力 - cf Apple's docs。

但是...如果您运行 Xcode 调试器,在您正在使用的 SVGKit SVGKSourceXXXXX 类上设置断点,并在设备上运行,您应该能够轻松地实时查看失败的原因和位置 - 我猜是 NSURL,但您可以证实这一点。

于 2016-10-13T14:15:37.057 回答