Hi, I'm Adam. Email me about: CTOs, Mobile/iOS, Project Management, and Development

SVGKit 2013 – Recipes

SVG is an awesome image format thats widely used, works in all browsers. SVG graphics make better apps and better games – and automatically “upgrade” themselves for future devices.

This post gives some simple 1-line / few lines of code recipes for using some of the main features of SVGKit – SVG implementation for iOS/OS X.

NOTE: this post refers to the 1.0.x version of SVGKit

Basic usage / installation

Install instructions are on the main GitHub page.

Basic usage / first-time usage info is on SVGKit 2013 – Usage.


Load an SVG file like loading a PNG file

SVGKImage* newImage = [SVGKImage imageNamed:@"imagename"];

Display an SVG file on-screen using an ImageView

[self.view addSubView: [[SVGKFastImageView alloc] initWithImage:newImage];

…or an ImageView that supports CoreAnimation for every element

NB: the “Fast” imageview above saves everything as a single layer. Good for rendering, but bad for interaction. The “Layered” imageview here allows you to tap on any layer, rotate/animate/fade/drop-shadow/glow any element, etc.

[self.view addSubView:  [[SVGKLayeredImageView alloc] initWithImage:newImage];

Use a URL to load an SVG (open an SVG file *directly* from the web)

// Splitting URL to multiple lines to make blogpost
//    easier to read...
NSString* longURL = [NSString stringWithFormat:@"%@%@%@",
NSURL* url = [NSURL urlWithString:longURL];
SVGKImage* newImage = [SVGKImage imageWithContentsOfURL:url];

Open an SVG from a custom source (maybe an in-memory SVG creation method)

First, create a class that conforms to SVGKSourceReader, i.e.:

@interface MyNewClass : NSObject <SVGKSourceReader>

…then subclass SVGKSource, and over-ride the method:

-(NSObject<SVGKSourceReader>*) newReader:(NSError**) error

Finally, use your customized SVGKSource to load your SVG:

SVGKSource* myCustomSource = [[[MyCustomClass alloc] init] newReader:nil];

/** Other examples, using the default SVGKSource class:
SVGKSource* urlSource = [SVGKSource sourceFromURL: [NSURL ...];
SVGKSource* fileSource = [SVGKSource sourceFromFilename: @"monkey.svg"];

SVGKImage* newImage = [SVGKImage imageWithSource:myCustomSource];

Search an SVG file for particular tags / nodes / elements

SVG is an XML file, containing XML tags/nodes such as: “<svg>”, “<g>”, “<path>”, “<linearGradient>”, etc.

NSString* tagToFind = @"linearGradient";
NodeList* result = [svgImage.DOMDocument getElementsByTagName:tagToFind];

for( Element* domElement in result )
   // You can use the Element object directly:

   // ...or, if it was parsed by the SVG parser, you can convert it to an SVGElement:
   SVGElement* svgElement = (SVGElement*) domElement; 

Search for sub-tags / sub-nodes of a particular tag/node

If you already have an SVGElement reference, you can search all its descendants:

// To search the entire document, use:

// SVGElement* startPoint = newImage.DOMTree;
SVGElement* startPoint = ... // from your code

NSString* tagToFind = @"linearGradient";
NodeList* result = [startPoint getElementsByTagName:tagToFind];

for( Element* domElement in result )
   SVGElement* svgElement = (SVGElement*) domElement; // if your tags are all supported by SVGKit, they will be converted to SVGElement instances

Get a list of ALL descendant tags (from a particular node down)

SVGElement* startPoint = ... // e.g. for whole SVG doc, use: newImage.DOMDocument;
NodeList* allElements = [startPoint getElementsByTagName:@"*"];

Render one small part of the SVG file on its own

E.g. if you want to display a subset of the SVG, or want to export a single element:

NSString* idInSVGFile = ... // assuming your SVG file has an "id" attribute for this node
CALayer* absoluteLayer = [newImage newCopyPositionedAbsoluteLayerWithIdentifier:isInSVGFile];


// NB: "absoluteLayer" is now positioned in absolute space;
//   if you add it to your window using e.g.:
[self.view.layer addSublayer: absoluteLayer];
// ...it will appear in the same place as it appeared before,
//   keeping all the offsets, rotations, etc

NOTE: there are several “newCopy…” methods, and each has different effects and outcomes. Read the method docs for each to decide which one you want to use. In a future version of SVGKit, we’d like to move these methods into a class of their own, and make it easier to see which one does what

Customise the parsing, using your own parser extensions

Create your custom class that adheres to SVGKParserExtension:

@interface MyCustomSVGParserExtension : NSObject <SVGKParserExtension>

Then create a parser, INCLUDE THE DEFAULT extensions, and add your one on the end:

MyCustomSVGParserExtension* myCustomExtension = [[MyCustomSVGParserExtension alloc] init];

SVGKParser* parser = [[SVGKParser alloc] init];
[parser addDefaultSVGParserExtensions]; // HIGHLY RECOMMENDED
[parser addParserExtension:myCustomExtension];

SVGKParseResult* result = [parser parseSynchronously];

SVGKImage* newImage = [[SVGKImage alloc] initWithParsedSVG:result];

Get help on why parsing failed (and warnings and line numbers!)

SVGKImage* newImage = ... // use methods above

// EITHER: parse using default parser:
SVGKParseResult* parseResult1 = newImage.parseErrorsAndWarnings; // this is a convenience pointer to (SVGKParser*).currentParseRun

// OR: use a custom parser:
SVGKParser* parser = ... // use methods above
SVGKParseResult* parseResult2 = parser.currentParseRun;

And then you have the following info:

/*  array of NSError objects, each one a "WARNING" from the parser */

/* array of NSError objects, each one a "FATAL ERROR" from the parser - if your SVG didn't render at all, this is why! */

/* array of NSError objects, each one a "RECOVERABLE ERROR" from the parser - if your SVG didn't render correctly, this is why! (although you probably still got to see something) */

UPDATE: more Recipes!

For more recipes, see SVGKit Recipes part 2

(this covers answers to some of the common questions asked in the Comments below)

37 thoughts on “SVGKit 2013 – Recipes”

Comments are closed.