The First Essential Swift 3rd Party Library To Include In Your Project

Posted by on
  • Font size: Larger Smaller
  • Hits: 3565
  • 7 Comments

As we all scramble to learn this fantastic new language Apple gifted to us at WWDC 2014, we're coming across new ways of doing things, either because the new way is better, or because the old way is no longer possible.

One of the main features that Swift has taken away, is the C preprocessor. That's what enabled #define's to work. A common #define used is for debug logging, to include useful info with every line.

#define DLog(...) NSLog(@"%s(%p) %@", __PRETTY_FUNCTION__, self, [NSString stringWithFormat:__VA_ARGS__])

This lets us go from this:

NSLog(@"Simple Message");
2014-06-08 05:38:54.649 TestApp[35062:60b] Simple Message

to this:

DLog(@"Simple Message");
2014-06-08 05:38:54.649 TestApp[35062:60b] -[TSTAppDelegate application:didFinishLaunchingWithOptions:](0x10961f2e0) Simple Message

We now get a lot more info in our log messages and can see where in our code the log message came from without having to type it in for every line.

In Swift, we lost this functionality. The reason this was traditionally done with a #define, and not a function or class, is so that we can use the __PRETTY_FUNCTION__, __FUNCTION__, __FILE__, and __LINE__ macros. The preprocessor replaces those macros with their actual values. For example, __FILE__ will always contain the filename where the macro is placed for example. If you were to use them in a logging function, the macros would always contain the information of the logging function, not the calling function, rendering them useless.

This looked like it was going to be a major inconvenience in Swift so I filed a radar about it: http://openradar.appspot.com/17170702. After playing with Swift for a while, I've discovered a solution. I've built a library you can use in your projects.

Introducing XCGLogger. My first open sourced third party library, that I think will be essential to add to your project.

The source can be found on GitHub here: https://github.com/DaveWoodCom/XCGLogger, with basic instructions on how to use it.

At a glance, it will change your logs from this:

Simple message

to this:

2014-06-09 06:44:43.600 [Debug] [AppDelegate.swift:40] application(_:didFinishLaunchingWithOptions:): Simple message

By writing code like this:

log.debug("Simple message")

instead of this:

println("Simple message")

A few things to note:

  1. Swift is brand new and in a state of flux, so it — and any libraries using it — will be subject to frequent changes.
  2. This is my first released library, so please let me know what you think and please share any ideas for improvement.
  3. There is a bug in Xcode 6 when using __FUNCTION__. XCGLogger uses a workaround for now, but will remove that once the bug is fixed. See: http://openradar.appspot.com/17219684
  4. This library is intended for use in Swift projects. There's no Objective-C compatibility included in it at this time. If it's a requested feature, it can be added.

Since Swift is brand new, there are a lot of different ways to accomplish the same thing. Over time, some best practices and patterns will emerge. I've used what I think are good practices and patterns in this library and hopefully they'll be helpful for developers as we work to establish what's best. For example, how to store static tokens for dispatch_once calls, shared instances, and global variables etc.

How does this work when I said earlier that using __FUNCTION__ and its friends in a function only gives you the information in the function instead of where it's called? Well, that's the secret sauce I discovered last week. If you set the default value of a parameter in a function to one of the macros, the compiler fills in that value at the calling location giving us the effect we need. Giving us access to the correct macro values inside the function that's called.

If you find this library helpful, you'll definitely find these other tools helpful:

Watchdog - monitors Xcode® and automatically cleans up stale cache files

Slender - cleans up Xcode projects, removing duplicate and/or unused assets

Briefs - powerful app prototyping, lets you and your clients try before you build

Follow me on Twitter @cerebralgardens

This post is part of iDevBlogADay, a group of indie iPhone development blogs featuring two posts per day. You can keep up with iDevBlogADay through the web site, RSS feed, or Twitter.

Comments

  • Guest
    Jimmy Hough Tuesday, 17 June 2014

    Thank you!

    Ive sorely missed my best friend DLog. I'll try this out soon.
    ALog and Ulog analogs would be great too!

  • Guest
    Phillipus Tuesday, 17 June 2014

    Nicely done!

    Thanks very much for this. Just what I needed to replace the old logger.
    Nicely done!

  • Guest
    Guy Wednesday, 16 July 2014

    Cocoapod?

    Are you going to create a pod spec for this?

  • Dave Wood
    Dave Wood Wednesday, 16 July 2014

    Cocoapod?

    It's unlikely that I'll make a pod spec for this. I'm not a fan of CocoaPods as I feel it encourages bad app design/architecture. I will create a module that can be easily added to your project, once Xcode 6 properly supports it.

  • Guest
    fleg Monday, 18 August 2014

    add as an embedded project

    hi,
    warning: xcode newbie!

    your logger looks like just what i need.

    however under "How To Use" you say "Add the XCGLogger files to your project as an embedded framework"

    how?!

    i have a sample app from...
    http://www.raywenderlich.com/74438/swift-tutorial-a-quick-start

    and i've been trying to follow "Embedding A Private Framework In Your Application Bundle" from...

    https://developer.apple.com/library/mac/documentation/MacOSX/Conceptual/BPFrameworks/Tasks/CreatingFrameworks.html#//apple_ref/doc/uid/20002258-DontLinkElementID_3

    but i'm not getting anywhere. am i even looking at the right page?
    thanks,
    fleg

  • Dave Wood
    Dave Wood Monday, 18 August 2014

    Re: add as an embedded project

    @fleg

    As of right now, there's a issue in Xcode that doesn't let you easily add Swift modules as an embedded framework. You can fake it by creating a new embedded framework and then swapping in the XCGLogger files, but the easiest thing to do right now is to just add the XCGLogger.swift file to your project directly.

    More info here: https://github.com/DaveWoodCom/XCGLogger/issues/5

  • Guest
    fleg Tuesday, 19 August 2014

    Re: add as an embedded project

    thanks that worked fine (and next time i'll check github issues first!)

Leave your comment

Guest Wednesday, 17 September 2014