Swift: Springboard-like loading animation using a custom layer

One thing I have struggled to wrap my head around in iOS is what’s the concept behind some of the eye candy that happens on screen. Being a long time full stack web developer, the concept of using graphic contexts to draw into is not obscure, since that’s what the <canvas> drawing/animation is based on, but with iOS it seems that there’s more than that.

You have the CoreGraphics stack, but you also have some UIKit tools that allow you to draw using simplified syntax (UIBezierPath being the most colorful example). In today’s post I’ll focus on using CoreGraphics instead of UIBezierPath, although my solution started with using UIBezierPath. In short, it went nowhere, so I had to go back to CoreGraphics :)

I always believed that, to learn something, one should have a real problem to solve. My plan was to mimic what happens on iOS springboard when an app installs – there’s a layer that dims the app icon and a circular pie slice animation that shows the application download progress, knocking out more and more of the dimming as the progress advances.

It’s a good idea to toy around so here’s what I ended up with:

loader2

First, a quick research revealed that simply creating a layer to host the graphic won’t be enough and I had to create a custom subclass off of the CALayer. Then I had to override one of its static methods (needsDisplayForKey) to allow the endAngle property of my class to become animated.

Not doing it simply doesn’t track the animation intermediate states, therefore resulting in pie slices “skipping” between the values. What makes it better is that XCode 6.1.1 doesn’t display that method in its autocomplete menu. Lesson learned here – read the documentation carefully.

Also notice how the endAngle variable is declared with @NSManaged, since this is the property we’re gonna animate on:

@NSManaged var endAngle: CGFloat
var startAngle = CGFloat(-0.5 * M_PI)
var maxAngle = CGFloat(1.5 * M_PI)

private var circleOffset:CGFloat = 30.0

var center: CGPoint {
  return CGPointMake(self.bounds.size.width/2, self.bounds.size.height/2)
}

var radius: CGFloat {
  return min(center.x - circleOffset, center.y - circleOffset)
}

var startPoint: CGPoint {
  var startPointX = Float(center.x) + Float(radius) * cosf(Float(startAngle))
  var startPointY = Float(center.y) + Float(radius) * sinf(Float(startAngle))
  return CGPointMake(CGFloat(startPointX), CGFloat(startPointY))
}

var cw:Int32  {
  return (startAngle > endAngle) ? 1 : 0
}


override init!(layer: AnyObject!) {
  super.init(layer: layer)
  if (layer.isKindOfClass(LoaderLayer)) {
    if let other = layer as? Loaderayer {
      startAngle = other.startAngle
      endAngle = other.endAngle
    }
  }
}

required init(coder aDecoder: NSCoder) {
  super.init(coder: aDecoder)
}

override class func needsDisplayForKey(key: String!) -> Bool {
  if (key == "endAngle") {
    return true
  }
  return super.needsDisplayForKey(key)
}

Having all the above set, it’s time to implement the actionForKey function. This function is called whenever a property of the class gets changed. We want to animate the change on the endAngle, so we’re calling out our very own makeAnimationForKey method when we detect change in the endAngle value.

Notice how anim.fromValue is fetched from the presentation layer in makeAnimationForKey (line 10) – it’s the last know value of the endAngle property before the animation:

override func actionForKey(event: String!) -> CAAction! {
  if event == "endAngle" {
    return makeAnimationForKey(event)
  }
  return super.actionForKey(event)
}

func makeAnimationForKey(key: String!) -> CABasicAnimation {
  var anim = CABasicAnimation(keyPath: key)
  anim.fromValue = self.presentationLayer()?.valueForKey(key)
  anim.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
  anim.duration = 0.5
  return anim
}

And, finally, here’s the drawing function itself. The most interesting part is how it uses blend modes to knock out the pie chart progress in the background (lines 12 and 26), revealing more and more of what’s underneath.

The layer automatically removes itself when the progress reaches 100%:

override func drawInContext(ctx: CGContext!) {
  if (self.endAngle < maxAngle)
  {
    var backgroundRect = CGRectMake(0, 0, bounds.size.width, bounds.size.height)
    CGContextSetBlendMode(ctx, kCGBlendModeDestinationOver)
    CGContextAddRect(ctx, backgroundRect)
    CGContextSetFillColorWithColor(ctx, UIColor(white: 0.0, alpha: 0.4).CGColor)
    CGContextFillPath(ctx)

    CGContextBeginPath(ctx)
    CGContextMoveToPoint(ctx, center.x, center.y)
    CGContextAddLineToPoint(ctx, startPoint.x, startPoint.y)
    CGContextAddArc(ctx, center.x, center.y, radius, startAngle, endAngle, cw)
    CGContextClosePath(ctx)

    CGContextSetFillColorWithColor(ctx, UIColor(white: 1.0, alpha: 1).CGColor)
    CGContextSetLineCap(ctx, kCGLineCapRound)

    CGContextSetBlendMode(ctx, kCGBlendModeDestinationOut)
    CGContextDrawPath(ctx, kCGPathFill)
  } else {
    self.removeFromSuperlayer()
  }
}

Swift: Regular expression-based string replacements

One of the quirkiest things in Swift for me turned out to be the understanding on how the Strings work.

Since all the Strings are Unicode in Swift, it is the fact that sometimes a character might be constructed from two (or more) unicode glyphs what makes the String manipulation a bit tricky.

The root of all string operations is the understanding of what the String index is and how does it differs from, say Int.

The String index is basically a representation of the character’s position within the String. Swift differs from many of the other programming languages by the fact that it’s Strings are actually CollectionTypes (instead of being treated as an array of characters or an indexed pointer) and the String index is BidirectionalIndexType instead of being an Int that is used to access a character within the string in the other programming languages. This gives us the ability to have functions like predecessor() or successor() on string indexes among everything else.

In short you can’t get a character by using string[3]. To access a character in Swift you have to use a String index, which is generated by the Core library’s advance function:

var s = "test"
var charIndex = advance(s.startIndex, 2)
var ch = s[charIndex]
>> "s"
ch = s[charIndex.predecessor()]
>> "e"
ch = s[charIndex.successor()]
>> "t"

Almost any of the string manipulations are performed using ranges. Ranges must consist of String indexes. A numeric range will produce an error:

charIndex = advance(s.startIndex, 2)

s.substringWithRange(Range(start: charIndex, end: s.endIndex))
// or
s[charIndex..<s.endIndex]
>> "st"

s.replaceRange(Range(start: charIndex, end: s.endIndex), with: "rererer")
// or
s.replaceRange(charIndex..<s.endIndex, with: "rererer")
>> "terererer"

Now, let’s give some practical usage to that knowledge.

Let’s assume that we have a string that has some HTML data and we want to convert that string to a Markdown-compatible one. For the sake of simplicity I’ll just look at the case of replacing the <strong> opening and closing tags with * which is used to make a string bold using Markdown. See below:

var s = "<strong>Hell</strong>o, <strong>Hell</strong>o, <strong>Hell</strong>o"
var search = "<\\/?strong>"
var replaceWith = "*"
var replacementLength = countElements(replaceWith)
var err: NSError? = nil
var expr = NSRegularExpression(pattern: search, options: .CaseInsensitive, error: &err)


if let matches = expr?.matchesInString(s, options: nil, range: NSMakeRange(0, countElements(s)) ) {
  var replacedStringLengthDifference = 0
  for match in matches {
    var startIndex = advance(s.startIndex, (match.range.location + replacedStringLengthDifference))
    var endIndex = advance(s.startIndex, (match.range.length + match.range.location + replacedStringLengthDifference))
    replacedStringLengthDifference -= (match.range.length - replacementLength)
    s.replaceRange(startIndex..<endIndex, with: replaceWith)
  }
}

>> "*Hell*o, *Hell*o, *Hell*o"

Leveraging the string indexes and ranges it’s pretty easy to do String manipulations in Swift. The replacedStringLengthDifference is a variable that keeps the difference in the string length (amount of characters in Int) after the replacement has been made. We use that difference to find the correct location of the next match.

Of course, all of the above could be solved by using a regular expression-based replacement, it depends if you want to have the source string replaced, in which case you’ll have to turn the string into a NSMutableString first, or if you want a new string that contains the replacements. Here’s the case where we replace within the original string:

var original = NSMutableString(string: "<strong>Hell</strong>o, <strong>Hell</strong>o, <strong>Hell</strong>o")
var search = "<\\/?strong>"
var replaceWith = "*"
var err: NSError? = nil
var expr = NSRegularExpression(pattern: search, options: .CaseInsensitive, error: &err)
if (err === nil) { 
  expr?.replaceMatchesInString(original, options: nil, range: NSMakeRange(0, original.length), withTemplate: replaceWith)
  println(original)
}

>> "*Hell*o, *Hell*o, *Hell*o"

And here’s a case where we get a string containing all the replacements by keeping the original string untouched. Note that the replacement is an Optional:

var original = "<strong>Hell</strong>o, <strong>Hell</strong>o, <strong>Hell</strong>o"
var search = "<\\/?strong>"
var replaceWith = "*"
var err: NSError? = nil
var expr = NSRegularExpression(pattern: search, options: .CaseInsensitive, error: &err)
if (err === nil) { 
  if let replacement = expr?.stringByReplacingMatchesInString(original, options: nil, range: NSMakeRange(0, countElements(original)), withTemplate: replaceWith) {
    println(replacement)
  }
}

>> "*Hell*o, *Hell*o, *Hell*o"

Swift: Printing an Array of enum

It was just recently that I discovered a cool little feature that allows you to describe Objects, structs and enums in Swift. It’s called the Printable protocol and it’s part of the Swift’s standard library.

Let’s describe a situation when it is handy. Imagine that you have an array that represents a magazine table of contents. This array holds not only the articles but also the adverts between them.

Let’s assume that our articles will all have a title, as well as many other properties that I won’t list for the sake of simplicity:

class Article {
  var title =  ""
  ...
  init (title:String) {
    self.title = title
  }
}

Let’s also assume that our adverts will all have a description:

class Advertising {
  var description = ""
  ...
  init(description:String)
  {
    self.description = description
  }
}

Now, we need an array which will host instances of both Article and Advertising type. Since Swift arrays are typed we have to base our array on an enum that has associated values to achieve our goal:

enum Content {
  case Story(Article)
  case Ad(Advertising)
}

var articles = [Content]()
var article1 = Article(title: "First article")
var ad1 = Advertising(description: "Some advertising")
var article2 = Article(title: "Second article")

articles += [Content.Story(article1), Content.Ad(ad1), Content.Story(article2)]

So, what’s the problem?

Well, sometimes we have to have a peak at what’s in the array and when we try to do so we usually get a very obscured output:

println(articles)
>>  [(Enum Value), (Enum Value), (Enum Value)]

OK, what can I do about it?

Here’s where the Printable protocol comes into play. Let’s look at what we have to do to get it implemented:

/// A type with a customized textual representation.
///
/// This textual representation is used when objects are written to an
/// *output stream*, for example, by `print` and `println`.
protocol Printable {

  /// A textual representation of `self`.
  var description: String { get }
}

Pretty easy to understand, huh? Probably one of the easiest protocols (if not the easiest one) in Swift.

Hint: Have a peak at the Apple’s documentation for an example on how to use it with structs: https://developer.apple.com/library/ios/documentation/General/Reference/SwiftStandardLibraryReference/Printable.html

The Solution

Let’s say that we want to display the article’s title and the advertising’s description when we print out the articles array.

To achieve that we have to extend our enum a bit, in a way that it implements the Printable protocol. Here’s one way to do it:

enum Content: Printable {
  case Story(Article)
  case Ad(Advertising)

  var description: String {
    get {
      switch(self){
        case let .Story(article):
          return "\"\(article.title)\""
        case let .Ad(advertising):
          return "\"\(advertising.description)\""
      }
    }
  }
}

Doing so allows us to get what we want – the article’s title and the advertising’s description are displayed when we print out the articles array, replacing the obscure (Enum value):

println(articles)
>> ["First article", "Some advertising", "Second article"]

Note: At the moment of writing the Printable protocol doesn’t work in the playground (Xcode 6.1.1), which is a known bug and hopefully will be sorted out soon. The code works great in a project context though :)

2014 in Music

2014 се оказа доста силна година – сред мейнстрийма нямаше нищо ново, но underground-a е пълен с интересни находки като Intervals, Monuments и Animals As Leaders. Особено внимание заслужават албумите на Coldplay и Royal Blood – Първият, защото става за всякакви ситуации, а вторият – защото е записан от група, състояща се само от барабанист и басист. Има и неща от чиста проба уважение (AC/DC, Pink Floyd, Slash), както и доста неща останали извън 20-ката (Machine Head, Machinae Supremacy), които спокойно могат да ги заместят, така че не мога да съм категоричен че ако бях писал поста по друго време нямаше да изглежда по-различно.

В крайна сметка – ето 20 албума, които можете да си завъртите и да прецените за себе си стават ли, или не.

20
World Of Fire
Slash
19
Vices. Virtues. Visions.
Raunchy
18
Catacombs Of The Black Vatican
Black Label Society
17
V
Voyager
16
California Breed
California Breed
15
Ruining Lives
Prong
14
The Endless River
Pink Floyd
13
Rock Or Burst
AC/DC
12
Second Nature
Flying Colors
11
Hymns For The Broken
Evergrey
10
Distant Satellites
Anathema
09
Clear
Periphery
08
Royal Blood
Royal Blood
07
Sonic Highways
Foo Fighters
06
Synaesthesia
Synaesthesia
05
Ghost Stories
Coldplay
04
The Amanuensis
Monuments
03
Pale Communion
Opeth
02
A Voice Within
Intervals
01
The Joy Of Motion
Animals As Leaders

2013 in music

Малко странен ми се вижда фактът, че оценявам изкуство, затова предпочитам да гледам на „класацията“ като на списък с 20-те неща които ми направиха най-силно впечатление през годината и подредбата им отразява по-скоро моментното ми отношение спрямо тях.

20
The Living Infinite
Soilwork
19
Brief Nocturnes and Dreamless Sleep
Spock’s Beard
18
Like Clockwork
Queens Of The Stone Age
17
Random Access Memories
Daft Punk
16
The Devil Put Dinosaurs In Here
Alice In Chains
15
Eternal Movement
Tides From Nebula
14
House of Gold & Bones Part 2
Stone Sour
13
The Theory Of Everything
Ayreon
12
Earth Rocker
Clutch
11
Unstoppable Momentum
Joe Satriani
10
Culture Clash
The Aristocrats
09
Dream Theater
Dream Theater
08
Desolation Rose
The Flower Kings
07
Sempiternal
Bring Me The Horizon
06
Shrine Of New Generation Slaves
Riverside
05
Darkness In Different Light
Fates Warning
04
The Raven That Refused to Sing
Steven Wilson
03
Hail To The King
Avenged Sevenfold
02
Fortress
Alter Bridge
01
Altered State
Tesseract

2012 in music

С леко закъснение – ето я и 2012 така, както я чух

10
Story Of Light
Steve Vai
09
Weather Systems
Anathema
08
Fire Make Thunder
OSI
07
I Am Anonymous
Headspace
06
Flying Colors
Flying Colors
05
Silverthorn
Kamelot
04
House of Gold & Bones Part 1
Stone Sour
03
The 2nd Law
Muse
02
Storm Corrosion
Storm Corrosion
01
Periphery II: This Time It’s Personal
Periphery

2011 in music

Този път заглавията са 30 и, както винаги, няма празно. Годината беше пълна с хубава музика, прекрасни концерти и списъкът можеше да удари 50 без никакви проблеми :)

30
Testimony 2
Neal Morse
29
Sympathetic Resonance
Arch/Matheos
28
Rockaholic
Warrant
27
Dualism
Textures
26
Eclipse
Journey
25
Velociraptor
Kasabian
24
How I Go
Kenny Wayne Shepherd
23
The Haunting
Within Temptation
22
Evanescence
Evanescence
21
Visions
Haken
20
Impressions
Lunatic Soul
19
Unto The Locust
Machine Head
18
The Road
Mike And The Mechanics
17
Iconoclast
Symphony X
16
The Path Of Totality
Korn
15
Earthshine
Tides From Nebula
14
Bilateral
Leprous
13
Road Salt Two
Pain Of Salvation
12
Sound Of A Playground Fading
In Flames
11
Communication Lost
Wolverine
10
Grace For Drowning
Steven Wilson
09
Anything But Time
Matt Schofield
08
III
Chickenfoot
07
Oceania
Derek Sherinian
06
A Dramatic Turn Of Events
Dream Theater
05
This Mortal Coil
Redemption
04
Worship Music
Anthrax
03
Heritage
Opeth
02
2
Black Country Communion
01
Dust Bowl
Joe Bonamassa

2010 in music

Обикновено около коледа пускам нещо като лична класация съдържаща 10-те ми любими албума, появили се през годината, и, за пореден път, няма да наруша традицията си – напук на клишетата :)

Разликата, обаче, е, че албумите тази година са 20! Не ми се струва честно да оставя някои албуми извън 10-ката, без дори да спомена за тях, особено след като през последната година нямах много време да блогвам.

Та – за ваше (не)удоволствие – списъкът започва от 20:

20
Road Salt One
Pain Of Salvation
19
Audio Secrecy
Stone Sour
18
Festival
Jon Oliva’s Pain
17
A View From The End Of The World
Machinae Supremacy
16
The Showdown
Allen/Lande
15
We’re Here Beacuse We’re Here
Anathema
14
Fever
Bullet For My Valentine
13
X
Spocks Beard
12
Dead New World
Ill Nino
11
The Obsidian Conspiracy
Nevermore
10
Poetry For The Poisoned
Kamelot
09
Sitha Ahra
Therion
08
Avalon
Sully Erna
07
Lunatic Soul II
Lunatic Soul
06
Static Impulse
James LaBrie
05
7 Sinners
Helloween
04
Plastic Pig Society
Bastardolomey
03
Victims Of The Modern Age
Star One
02
Strings To A Web
Rage
01
Nightmare
Avenged Sevenfold

TightMVC

От доста време базирам всичките си проекти на MVC PHP frameworks. Наскоро обаче се натъкнах на един проблем – почти няма framework, който да поддържа само основните неща – дори любимият ми CodeIgniter е тлъстичък, когато стане въпрос за малки сайтове. Mакар да не се използват по подразбиране, библиотеките му си седят в дистрибуцията и заемат ненужно (според мен) място. Да не говорим какъв слон е ZendFramework, въпреки всичките му предимства.

За някои от проектите си наистина имах нужда от нещо доста по-леко, възможно най-минимална имаплементация на MVC pattern-a. Преди време бях попадал на една много добра статия от Anand Garg в която той даваше много добри съвети (и код) за разработване на собствен MVC framework.

Започнах от неговия код, целейки само и единствено поддръжка на PHP5. Изхвърлих всичко ненужно, добавих поддръжка на PDO за комуникация с базата данни, добавих поддръжка за Layouts, Helpers и Modules и в крайна сметка получих един доста приличен framework с много малък codebase.

Резултатът е качен тук, а не много пълна документация можете да откриете във wiki-то към проекта тук.

На който му се стори интересно – може да тегли, тества, праща bug reports и т.н.