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

Posted

技术标签:

【中文标题】SVGKit:如何使用 SVGKit 渲染引用 iOS 设备照片的 SVG XML 字符串【英文标题】:SVGKit: How do i render an SVG XML String that references a iOS device photo using SVGKit 【发布时间】:2016-10-03 22:27:56 【问题描述】:

所以,我的基本问题是:

ios 上有没有办法使用 SVGKit 来呈现包含对本地图像的引用的 SVG?

血腥细节

我的应用程序需要生成和渲染 SVG(NSString 中的 XML)。 XML 将引用设备上的图像 URL(在相机胶卷中)。我在 iOS 上使用SVGKit。我可以使用以下方法从图像 PHAsset 中获取 URL(参见:***: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"   viewBox="0 0 2175 1537" style="background-color:#ffffff">

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

<g clip-path="url(#my-uuid)">
    <image overflow="hidden" transform="translate(1062, -64.58393285371704) rotate(0, 555, 832)" x="0" y="0"   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..(请参阅 ***: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'

【问题讨论】:

【参考方案1】:

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

所以......如果你得到一个 nil 图像,你可能破坏了 NSURL 自己的解析能力 - c.f. Apple 的文档。

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

【讨论】:

以上是关于SVGKit:如何使用 SVGKit 渲染引用 iOS 设备照片的 SVG XML 字符串的主要内容,如果未能解决你的问题,请参考以下文章

未在实例上定义但在渲染期间引用的属性或方法 I Vuex

[react] 如何解决引用类型在pureComponent下修改值的时候,页面不渲染的问题?

引导 React 渲染器:如何在应用启动时获取对根视图的引用?

[react] 如何解决引用类型在pureComponent下修改值的时候,页面不渲染的问题?

[react] 如何解决引用类型在pureComponent下修改值的时候,页面不渲染的问题?

如何解决 Vue.js 中的“属性或方法未在实例上定义但在渲染期间引用..”?