Creating a pod with PLCrash­Reporter

Creating a pod which includes a framework can prove troublesome, this entry contains the findings after struggling to create a working pod that uses PLCrashReporter.

Pod with frameworks

A normal pod using a standard-provided-by-apple framework such as QuartzCore adds its framework needs like the following.

Pod::Spec.new do |s|
  s.name = 'MyPod'
  s.version = '1.0'
  s.authors = {'Your Name Here' => 'you@example.com'}
  s.homepage = 'http://www.example.com'
  s.summary = 'My pod is awesome'
  s.source = {:git => 'https://git.example.com/MyPodRepo', :revision => '1e16eee5c4e2'}
  s.platform = :ios
  s.source_files =  'MyPodSubdir/**/*.{h,m}'
  s.frameworks = 'QuartzCore'
end

CocoaPods takes care of everything in this case.

Pod with vendor frameworks

One might wish to use a framework-not-provided-by-apple such as PLCrashReporter in a pod. In case you have looked at the documentation, you may have found the vendored_frameworks keyword and thought that was all that was needed.

The information that you do not seem to find in the documentation are:

  • vendored_frameworks is the path in your source repo to the framework folder
  • xcconfig should be used to add LD_RUNPATH_SEARCH_PATHS so xcodebuild understand where to find the framework
  • preserve_paths should be used so the contents of the framework is not cleaned(deleted) by CocoaPods
  • resource should be used to indicate that the framework will used as a bundle

The above bits of information was mostly found in issue #58 for CocoaPods. Using these bits of information you can include PLCrashReporter like the following.

Pod::Spec.new do |s|
  s.name = 'MyPod'
  s.version = '1.0'
  s.authors = {'Your Name Here' => 'you@example.com'}
  s.homepage = 'http://www.example.com'
  s.summary = 'My pod is awesome'
  s.source = {:git => 'https://git.example.com/MyPodRepo', :revision => '1e16eee5c4e2'}
  s.platform = :ios
  s.source_files =  'MyPodSubdir/**/*.{h,m}'
  s.frameworks = 'QuartzCore'
  s.ios.preserve_paths = 'MyPodSubdir/Externals/*.framework'
  s.ios.vendored_frameworks = 'MyPodSubdir/Externals/CrashReporter.framework'
  s.ios.resource = 'MyPodSubdir/Externals/CrashReporter.framework'
  s.ios.xcconfig = { 'LD_RUNPATH_SEARCH_PATHS' => '"$(PODS_ROOT)/MyPod/MyPodSubdir/Externals"' }
end

It may only be needed to add one of the preserve_paths and resource keywords however this was not confirmed before ending the exploration into pods and podspec.

Getting to know Jekyll and Hyde

Let me introduce Jekyll which can be summed up as a static website and blog generator and Hyde which is a template for Jekyll. Furthermore Hyde is based on a less elaborate template by the name of Poole. There is plenty of information about Jekyll, Hyde and Poole around the Internet, so I won't go out of my way to explain everything.

I came to know these tools by stumbling across a blog entry from Matt Thompson in which he went through his blogging tools. When I read this entry I had been writing some blogging software for this every blog for some time. I am was naturally very interested in this because it seemed to match my needs.

I am going to tell you about some of the challenges of using these tools.

The pretty URL problem

If you change the permalink setting away from pretty there are side-effects.

I wanted the structure of the URLs generated by Jekyll to be different then the default. I wanted all my blog entries to be in /blog/, but I also wanted the pages I create in Jekyll to not be in the /blog/ folder.

As it turned out this is not the easiest thing in the world to achieve. You could simply have added the following setting in your _config.yml:

destination: ./_site/blog

However this would put all the pages created by Jekyll into the /blog/ folder too.

Hyde's default setting for permalinks is pretty which is defined as /:categories/:year/:month/:day/:title/ which also was not exactly what I wanted. To get the URL I wanted and and have my blog entries in /blog/ I used the following setting in _config.yml:

permalink: /blog/:year/:title/

This left me with the blog entries where I wanted them, but it still left the blog entries index is at / and not /blog/. We will handle that in a bit in the section about the paginator. First we deal with the changes to pages.

Page URL conversion

Since I changed away from the pretty setting pages like the /about/ was now at /about.html. This side-effect is caused by about.md is converted to /about/, but only if the permalink setting is set to pretty. No other setting will cause this conversion and this effect is not exactly visible in the documentation. The easy fix is to set each misplaced page's permalink in it's yaml front matter, e.g. for the about page:

permalink: /about/

So that's what I did, since you can not trigger the conversion otherwise, but then again it is trivial to create the about page in /about/index.htmlinstead.

Secrets of the paginator

Getting back to the issue of the index of blog entries not being in /blog/. Needless to say I tried a few things without success before ending up with the following setting for the config file :

paginate_path: "/blog/page/:num/"

Now if you use the paginate_path setting like it is above, then it is important to use the paginator in a file named /blog/index.html. Basically move the current /index.html file to /blog/index.html.

The paginator_path value must match up to the file which uses the paginator and the paginator will not work if the file extension is not .html. If you are trying to use a .md file it will look like the paginator.posts variable is empty.

Caring for old posts

If you are like me then you have some old posts that should be kept around which do not fit into the url template above. You have two choices:

  1. Create a page with the old content with a permalink in it's yaml that matches the old url.
  2. Create a post with the old content and create a page with a permalink in it's yaml that matches the old URL and redirect to the new post.

Now redirection is not something that is mentioned in the documentation, but it is a simple matter to have redirection.

Redirection

Redirection is really simple. Create this layout _layouts/redirect.html with the following content:

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<meta http-equiv="refresh" content="0;url={{ page.redirect }}" />
</head>
</html>

You may at this point already have figured out how that is supposed to work, but here is the last piece to redirection:

---
layout: redirect
redirect: /blog/
permalink: /some-place/
---

Having the redirect layout around then the above yaml will create a page positioned at /some-place/ which will redirect you to /blog/.

Assets

I prefer not having every file in a single directory as many suggest doing instead I like grouping assets used in blog entries. I found a plug-in somewhere online and I seem to have lost the source, but it was MIT licensed. I have modified it in a few places, so here is my version in it's entirety.

module Jekyll
  class AssetPathTag < Liquid::Tag
    @filename = nil

    def initialize(tag_name, markup, tokens)
      #strip leading and trailing quotes
      @filename = markup.strip.gsub(/^("|')|("|')$/, '')
      super
    end

    def render(context)
      if @filename.empty?
        return "Error processing input, expected syntax: {% asset_path [filename] %}"
      end

      path = ""
      page = context.environments.first["page"]

      #if a post
      if page["id"]
        #loop through posts to find match and get slug
        context.registers[:site].posts.each do |post|
          if post.id == page["id"]
            path = "posts/#{post.url}"
          end
        end
      else
        raise "dont use asset_path in pages please..."
      end

      #strip filename
      path = File.dirname(path) if path =~ /\.\w+$/

      #fix double slashes
      "/assets/#{path}/#{@filename}".gsub(/\/{2,}/, '/')
    end
  end
end

Liquid::Template.register_tag('asset_path', Jekyll::AssetPathTag)

This will allow you to group files needed in a post in a directory such as /assets/posts/:permalink/:filename.

The first post

Having the above modifications in place, I needed to actually write a blog entry. I quickly noticed that I had to lookup the syntax for markdown here is the cheat sheet I have been using.

I found myself needing to lookup the correct lexer argument to the tag {% highlight [lexer] %} so here is the rather long list of lexers.

Other users of Hyde may notice the layout looks slightly different. I had to make the sidebar area larger since the CodeReaper name is too long, especially in comparison to the name Hyde. While I was tinkering with the CSS I also added an alternate gray theme.

I am sure I will make many more changes, but the changes prior to this blog entry gave me some insight that I have now shared with you.