Archive for category Development

Swift Notes with comments about Functional Programming

If you just want to see my notes on the swift syntax bits and pieces that are novel to me, that are important aspects of swift and that I’m likely to forget then scroll down, otherwise continue reading for my first thoughts on functional programming.

I’ve finally got around to checking out Swift and along the way I got sidetracked by Functional Programming. I recognise that Swift is not a functional programming language but you can do functional programming in Swift in a way that is not possible in Objective-C.

Now that computer power is increasing mostly by adding CPU cores rather than increasing clock speed the need for programming tools that make it easier/safer/more reliable to work concurrently is more important than ever. Functional programming by removing state and passing immutable objects is far better at dealing with concurrency than object oriented programming. But I like state, I like objects that have properties that can change, that can receive messages and perform actions. I like thinking about how objects of the same and different types interact when it comes to creating something bigger. But there are issues of concurrency and multiple queues that working this way forces you to deal with, and every solution is a compromise.

I don’t think I’ll be giving up object oriented programming any time soon, but from now on I will be looking at any new problem with an eye to, how would I apply a functional programming solution to this problem. I’ve valued this diversion into functional programming. In particular I like the functional programming idea of looking for patterns, in things like function/method signatures. They can help to give the game away as to when things which you might think of as being different are similar or are actually be the same.

I like Rob Napier’s blog articles about functional programming. He is clear in his thinking and makes a concerted effort to strip his discussion about functional programming of its jargon. Actually there is more to it than that, he explains clearly. I realised this when I found myself going through his answers one by one on his stack overflow profile.

Rob Napier’s point that having functions whose output is only dependent on the input parameters means that fewer tests are needed than with object oriented programming to demonstrate that the output will be what you intend based on the inputs. The object oriented approach where objects hold state makes it much harder to demonstrate that the output for all inputs is what you intend.

I’m old enough to have started programming when procedural programming was the default paradigm which means that there are aspects of functional programming which are not foreign to me, but there is a big difference in mindset, staying away from mutable values is one, blocks are another.

In writing MovingImages I wrote a dictionary parser for creating CoreGraphics types like CGRects and creating CoreGraphic colors. The parser is made up of a bunch of procedural functions that hold no state, that take immutable objects, but are all written in Objective-C. My mindset was very much procedural when I was writing them. The parsing problem is very much one that lends itself to being solved within a functional paradigm and thinking about how I wrote the parser I don’t think it is a world away from being functional. Would I do it differently now? yes and I would use Swift to do it. The functional features in Swift make it a much better tool to solve this problem than Objective-C.

Now the first Swift feature I’d take advantage of when rewriting my dictionary parser would be enums with associated values. An enum with two cases, success and failure as described by @cocoaphony in his blog post Functional Wish Fulfilment though I’m not sure I’d use a NSError for the failure associated value.

enum Result<A> {
  case Success(Box<A>)
  case Failure(NSError)
}

My parser functions would return a Result object that I could get the result out of if no error occurred. Unfortunately this also requires a box class that can wrap up whatever A is into something the compiler can deal with. The box class looks like:

final class Box<T> {
  let unbox: T
  init(_ value: T) { self.unbox = value }
}

That is a messy implementation detail that hopefully will be fixed by the swift compiler team.

This introduces the final keyword which basically means that the class can’t be inherited from. The final keyword also has performance implications (instance method calling on a object which is declared final is faster). See Flex Monkey on inline performance. Using final on a method means the method can’t be overridden.

Swift syntax details I’m likely to forget, but that I will need

 

# Defining a class init and calling a constructor
class TipCalculator {
  init(total:Double, taxPct:Double) {
  ...
  }
}
let tipCalc = TipCalculator(total: 33.25, taxPct: 0.06)

 

Declaring arrays and dictionaries

Note the various ways to declare array and dictionary types:

// [Double] is a shortcut for Array
// Declaring arrays and dictionaries with item types specified.
let newArrayImplicitDouble = [1.2, 1.3, 5.1, 0.1]
let newArray: Array = [1.2, 1.3, 5.1, 0.1]
let newArray2: [Double] = [2.3, 0.1, -0.8, 10.2, 153.7]
let dict: Dictionary<String, Double> = ["key1":1.2, "key2":-3.4]
let dict2: [String:Double] = ["key1":1.2, "key2":-3.4]

 

Obtaining a class from a string using a dictionary

If you want to be able to create a swift class from a string, you will need to use a lookup dictionary, as the Objective-C approach using NSClassFromString is not available. From this stack overflow answer.

# Creating a swift class from a string:
let classmapping: [String:String.Type] = ["string1":String.self]

if let stringClass = classmapping["string1"] {
    let theString = stringClass("A string")
    println(theString)
}

The above currently crashes the swift compiler. There is a swift compiler bug which I’ve reported.

Swift compiler does implicit type

The Swift compiler will do everything it can to determine the type information it needs which means that you can leave a lot of explicit type information out. The following is variations on a theme demonstrating the different ways constants and variables can be declared. You can also often leave out named parameters and refer to a parameter by order. Named parameters also don’t need to have the type specified if it can be determined by the compiler elsewhere.

let intArray = [2, 9,4,5,3,2,11,17,16,4,1,3,0,23]
var evenArray = filter(intArray) { $0 % 2 == 0 }
println(evenArray)

evenArray = intArray.filter() { $0 % 2 == 0 }
println(evenArray)
let evenArray2: Array = filter(intArray) { (intVal: Int) -> Bool in intVal % 2 == 0 }

println(evenArray2)

println(5.description)
println(String(5))

let twoTimesArray = intArray.map({$0 * 2})
let twoTimesStringArray = map(intArray, { (intVal: Int) -> String in String(intVal * 2) })
for theString in twoTimesStringArray {
    println(theString)
}

let twoTimesStringArray2 = intArray.map({String($0 * 2)})
println(twoTimesStringArray2)
The Swift Tuple object

Swift also has a construct called a Tuple which can package up multiple values into a single object. The values can be assigned with names or be anonymous. That means a way to obtain the values from an anonymous tuple is required.

// Accessing elements of an anonymous tuple

let firstTuple = ("String 1", "String 2")
let firstItem = firstTuple.0
let secondItem = firstTuple.1
let (item1, item2) = firstTuple
let secondTuple: (String, Double) = ("Price", 25.99)
println("firstItem: \(firstItem), secondItem: \(secondItem), item1: \(item1), item2: \(item2)")

let namedTuple = (string1: "String 1", double1: 45.2)
println("string1: \(namedTuple.string1), double1: \(namedTuple.double1)")
A few optional notes

Optionals are really just a simple enum with two values (.Some and .None). Optionals can be created on demand, for example when a function/method is meant to return an optional we don’t have to return an optional instead we return a value or nil and the optional is automatically created for us wrapping the return value. Alexandros Salazar goes into some details about Optionals. This article by Natasha the Robot on unwrapping multiple-options is also useful. It’s kind of like wrapping the optionals up in a Tuple.

class Person {
    var residence: Residence?
}
 
class Residence {
    var numberOfRooms = 1
}

let john = Person()
// The following line will trigger a run time error.
// The ! forces the unwrapping of the optional.
let roomCount = john.residence!.numberOfRooms

// You can also check the validity of the optional through optional chaining before accessing.
if let roomCount = john.residence?.numberOfRooms {
    println("John's residence has \(roomCount) room(s).")
} else {
    println("Unable to retrieve the number of rooms.")
}

// You can assign an option the .None value.

let optional2: Int? = .None
println(optional2)
Methods and functions can have named parameters

The external argument name can be different to the internal parameter name. Named parameters with swift functions Natasha Murashev aka the robot

func hello(fromName name: String) {
    println("\(name) says hello to you!")
}
hello(fromName: "Mr. Roboto")

If you want the external parameter name to be the same as the internal name, you don’t have to repeat the name, all you have to do is add a # to the front of the name in the function/method declaration.

The behaviour is different again for functions/methods declared in classes/structs/enums. The first parameter name is ignored, whilst all following named parameters don’t make a distinction between external and internal names. If you’ve forgotten the details I’d really recommend you go and read that article by Natasha again.

Declaring and implementing a class method, which are actually called Type methods:

class ClassWithClassMethod {
  class func classMethod() -> String
  {
    return "My string"
  }
}

I’d also recommend playing with Apple’s pattern matching playground which you access through the swift blog.

Instance Methods are Curried Functions in Swift

This blog post by Ole Begemann that Swift instance methods are curried functions is an eye opener. The following captures the idea of it, but I’d recommend reading Ole’s blog post.

class BankAccount {
    var balance: Double = 0.0
    
    func deposit(amount: Double) {
        balance += amount
    }
}

let account = BankAccount()
account.deposit(100) // balance is now 100

let depositor = BankAccount.deposit // Notice the assignment to the method pointer.
depositor(account)(100) // balance is now 200

In the above case depositor is of type:

let depositor: BankAccount -> (Double) -> ()
Swift Namespaces

Namespaces in swift are implicit. All classes etc. are implicitly scoped by the module (Xcode Target) they are in. No class prefixes needed.

How are name clashes resolved? E.g. when I import a lib with Product class and have one myself?

You can always explicitly qualify with the module name. F.e., if you define a “swap” you can always get to “Swift.swap” as well.

The difference between objects created from a struct type and objects created from a class type is that objects instantiated from a struct are passed by value, whereas objects instantiated from a class are passed by reference. I’ve not seen anything that describes how to copy objects created from a class. The discussion in Apple’s developer documents doesn’t mention what you should do. My guess is that in Swift you’ll need something like the copy protocol in objective-c.

Tags:

Thinking about my tests

I’ve installed Yosemite and of course the first thing I did was to run my tests

Almost every test failed. Generated images are all different. They look the same to my poor eyesight but pixel values can be quite different with the compare tolerance increased to 26* from 0 needed for an image to be identified as the same. I had previously only needed to do this when comparing images created from windows on different monitors. I think perhaps I need to have a think about exactly what it is I’m testing. These tests have saved me a lot of time and given me confidence that I’ve not been breaking stuff but for so many to break with an os upgrade doesn’t help.

For now the failure of the tests beyond the image generation described above, has informed me about the following changes to ImageIO and CoreImage filters.

Information returned about functionality provided by ImageIO and CoreImage

ImageIO can now import three new formats: “public.pbm”, “public.pvr”, “com.apple.rjpeg”
ImageIO has lost one import format: “public.xbitmap-image”

I’ve no idea what these formats are and I’ve been unsuccessful at finding information about them.

ImageIO has added export formats: “public.pbm”, “public.pvr”, “com.apple.rjpeg”

Apple has added these new CoreImage filters:

CIAccordionFoldTransition CIAztecCodeGenerator CICode128BarcodeGenerator CIDivideBlendMode CILinearBurnBlendMode CILinearDodgeBlendMode CILinearToSRGBToneCurve CIMaskedVariableBlur CIPerspectiveCorrection CIPinLightBlendMode CISRGBToneCurveToLinear CISubtractBlendMode

There are minor configuration or filter property changes to the filters listed below with a brief description of the change:

  • CIBarsSwipeTransition inputAngle given updated values for default and max. Identity attributes removed for inputWidth and inputBarOffset.
  • CIVignetteEffect inputIntensity slider min changed from 0 to -1.
  • CIQRCodeGenerator has spaces added to description of one property, and a description added for another.
  • CILanczosScaleTransform has a fix for the filter display name.
  • CIHighlightShadowAdjust inputRadius has minimum slider value changed from 1 to 0.
  • CICMYKHalftone inputWidth attribute minimum changed from 2 to -2. inputShapness attribute type is CIAttributeTypeDistance not CIAttributeTypeScalar
  • CICircleSplashDistortion inputRadius has a new identity attribute with value 0.1
  • CIBumpDistortionLinear inputScale, inputRadius and inputCenter given slightly more rational default values.
  • CIBumpDistortion inputScale, and inputRadius are given slightly more rational defaults.
  • CIBarsSwipeTransition inputAngle given updated values for default and max. Identity attributes removed for inputWidth and inputBarOffset.

*This is comparing images created from a 8 bit per color component bitmap context. So out of a range of 256 possible values images generated on Mavericks compared to ones generated on Yosemite are different by up to 26 of those 256 values. That’s huge.

Documentation markdown to html

The branding in relation to the documentation should be minimal but clear. Each documentation page should have a header which has the branding and then some navigation options to move around documentation. A static list that is the same for every page.

Documentation is all in markdown, github/gitlab flavoured markdown.

These are the lists of tools I looked at for generating/hosting customised documentation and the issues I had with them.

  1. GitHub pages with/without Jekyll – Removed from consideration. The stench is too great.
    • Takes markdown as input +
    • Aimed at blogging rather than documentation –
    • I believe it could be forced into a usable documentation system but it would be tricky. –
    • The .io domain for ones without custom domain names. Supports Diego Garcia’s theft. Why would you even choose this. –
    • The guy at github who put it together is the problematic github founder
  2. Sphinx Looks promising
    • Takes .rst rather than markdown –
    • Produces static searchable documentation from markdown +
    • Branding seems possible from css and templates +
    • Installation (I did get it to install, but flaky) –
      • Using MacPorts. I’ve wasted hours in the past trying to get home-brew and MacPorts installed. I’m reluctant to try again
      • Alternate suggested is python easy_install
      • I installed easy_install, which wasn’t quite an easy install
      • I ran sudo easy_install sphinx which seemed to work with some warnings like:
        • warning: no previously-included files matching ‘*.pyc’ found under directory ‘jinja2’
      • I ran sudo sphinx-build as in the install instructions
        • I get a reply: “Error: Insufficient arguments.”
        • Does this mean that my sphinx installation is not yet built? Actually I think that is the actual sphinx command for building documentation. Instructing the user to run that on the install page without actually informing the user that running of the command was purely to confirm sphinx is installed was confusing.
        • Running sphinx-build without sudo produces same result
        • Running sphinx-build –version returns: Sphinx (sphinx-build) 1.2.2
    • It is python based. If something goes wrong and I haven’t used python then I’m dependent on others –
  3. Yard
    • It takes markdown files (using .yardopts file), it certainly sucks in a Readme markdown file & process correctly +
    • I use it already for generating ruby reference documentation. +
    • I’ve not been able to get it to suck up additional markdown files. –
      • I’ve tried the command line option –files
      • I’ve tried list files after: ” – ” on the the command line
      • Neither of the above work, I’ve tried both with simple markdown files
    • Adding templates for branding the documentation looks non-trivial. –
  4. Pandoc Serious consideration
    • Provides an opportunity to produce documentation in almost any format imaginable from markdown +
    • Output can be customised using templates plus headers/footers and css +
    • Can generate table of contents (toc) from markdown +
    • Work needed to write the templates and css needed to get correct branding
    • I’d be capable of this but it will require time for me to do, due to lack of experience

I’m going to go with pandoc, installation trivial, reads markdown, outputs in a huge variety of formats, customizable. As stated the only issue is getting my head around how the templates work. I wish I’d spent time just getting pandoc templates/headers/footers and css files written rather than trying to find a more user friendly tool which doesn’t appear to exist.

Small things I like about ruby

The interactive ruby shell (irb) is really great tool to get comfortable with trying out features of ruby.

There are a couple of things that really help to make irb interactive. These come from ruby’s introspective capabilities.

The first is the method “methods” which returns a list of all the methods that relate to an object and since everything is an object in ruby you can call methods on anything:

For example what are the methods that an integer can take:

10.methods

which returns:

:to_s, :inspect, :-@, :+, :-, :*, :/, :div, :%, :modulo, :divmod, :fdiv, :**, :abs, :magnitude, :==, :===, :<=>, :>, :>=, :<, :<=, :~, :&, :|, :^, :[], :<<, :>>, :to_f, :size, :zero?, :odd?, :even?, :succ, :to_json, :integer?, :upto, :downto, :times, :next, :pred, :chr, :ord, :to_i, :to_int, :floor, :ceil, :truncate, :round, :gcd, :lcm, :gcdlcm, :numerator, :denominator, :to_r, :rationalize, :to_bn, :singleton_method_added, :coerce, :i, :+@, :eql?, :quo, :remainder, :real?, :nonzero?, :step, :to_c, :real, :imaginary, :imag, :abs2, :arg, :angle, :phase, :rectangular, :rect, :polar, :conjugate, :conj, :between?, :nil?, :=~, ...]

You can do the same on an array. For example an empty array:

[].methods

Now that is kind of useful, but as long as people have given their methods decent parameter names then you can work out how to call a method. So for example I have created a module ‘Smig’ with a method “create_imageimporter”. So if I enter the following in irb:

Smig.method(:create_imageimporter).parameters

Which returns:

[[:req, :pathToFile], [:opt, :importerName]]

This tells me that the first parameter is required and because I named the parameter pathToFile then I know I need to supply a path to a file. The second parameter is an optional parameter and is called importerName. Without reading about Smig this is probably not helpful but for me this is enough information to remind me how to call “create_imageimporter” without having to go and look up documentation elsewhere.

#Update 23 June 2014

I’ve now started using the Yard documentation tool for reference documenting of ruby code.

I’ve also been testing the use of MovingImages asynchronously but this of course means having the ability to track when asynchronous tasks are completed. A MovingImages asynchronous task can save the results of the asynchronous command to a file when it is completed. As a result I’ve installed the ruby gem ‘listen‘. Documentation for the ruby gem listen. The githug repo for listen.

Tags:

Useful Ruby links

Understanding Ruby Blocks, Procs and Lambdas

Community Ruby Style Guide

A Ruby static code analyzer, based on the community Ruby style guide.

Ruby named parameters with defaults plus Keyword arguments in Ruby

Making Ruby Gems

A guide to Ruby Gems

Ruby 2.0.0 Standard Library Documentation

Ruby 2.0 Core API

Neat things about ruby

Programming Ruby

Ruby in Twenty minutes

Ruby Constructs: Class, Module and Mixin

Opening files relative to the home directory. Some of the info here is a bit shit, but there is also some useful info. The call:

File.dirname(__FILE__)

will give you the current file’s path.

Modules as Namespaces

Useful looking external frameworks for iOS and OS X

Frameworks that work for both iOS and OS X

CocoaLumberjack by Ernesto Rivera. A logging framework. I use this.

Ensembles by Drew McCormack. A synchronisation framework for Core Data.

Extensible iOS and OS X animation library called pop. By developers at Facebook under BSD license.

Frameworks for OS X

 

Frameworks for iOS

PromiseKit by mcxl. Makes working with asynchronous design patterns easier.

Quadrilaterals on CALayer

Bridging AGGeometryKit with POP for amazing dynamics and animations.

Core Image Filter Rendering. Performance & color profiles

The Apple documentation for rendering a core image filter chain notes that allowing the filter chain to render in the Generic Linear color space is faster. If you need better performance and are willing to trade that off against better color matching then allowing the filter chain to render in the generic linear color space should be faster.

I thought I better look at what the impact of this was both for performance and color matching. I also wanted to see what the difference was if the core graphics context that the filter chain rendered to was created with a sRGB color profile or a Generic Linear RGB profile when the context bitmap was saved as an image to an image file.

All the tests were done on my laptop with the following configuration:

OS: Mavericks 10.9.2
System information: MacBookPro non retina, model: MacBookPro9,1
Chipset Model:	NVIDIA GeForce GT 650M 500MByte.
Chipset Model:	Intel HD Graphics 4000
A 512GByte SSD, 16GByte RAM.

I installed gfxCard Status tool sometime ago which allows me to manually switch which cards to use, and also to inform me when the system automatically changes which card is in use. I use to get changes reported regularly but after one of the Mavericks updates this happened much less. After that update the only consistent way for the discrete card to be switched on automatically by the system was having an external monitor plugged in. I think the OS is trying much harder to keep the discrete graphics card turned off. I have NSSupportsAutomaticGraphics switching key in my info.plist set to YES. I have tried setting the value to NO, and if I run the tests then as long as software render is not specified I’m informed that the system has turned the discrete graphics card on but the CoreImage filter render performance is still poor. The consequence is I’m not really sure that the discrete graphics card is being used for these tests. Perhaps I’d get different results as to whether GPU rendering or software rendering was faster if I had a more complex filter chain so what I might be seeing here is the time needed to push the data to the graphics card, and then pull it back dominating the timing results.

First up, when comparing images where the only difference in image generation has been whether they are rendered to a CGContext with a sRGB profile or a Generic Linear RGB profile then when I view the images in Preview they look identical. The reported profiles are different, the image generated from a context with Generic Linear RGB has a reported profile of Generic HDR profile while the image from a context with a SRGB profile has a reported profile of sRGB IEC61966-2.1.

When the filter chain has the straighten filter and it rotates the image 180 degrees the colors of the output image are exactly the same as the input image when viewed in Preview, no matter the options for generating the output image.

When the filter chain has the box blur filter applied with a radius of 10 pixels the image rendered in the linear generic rgb profile is lighter than the one rendered using the sRGB profile when viewing the output images in preview. The image rendered using the sRGB looks to match better the original colors of the image. The generic linear rgb profile appears to lighten the image. The color change is not large and would be probably be acceptable for real time rendering purposes.

Setting kCIContextUseSoftwareRenderer to YES or NO when creating the CIContext makes no difference in terms of the color changes.

However I get the opposite of what I’d expect with speed.

Asking the filter chain with filter CIBoxBlur with radius of 10 to render 200 times to a Core Graphics context with a sRGB color profile:

Software render using sRGB profile: 4.1 seconds
Software render using Linear Generic RGB profile: 5.3 seconds
GPU render using sRGB profile: 7.0 seconds
GPU render using Linear Generic RGB profile: 7.5 seconds

If I create a Core Graphics context with a Generic Linear RGB color profile then:

Software render using sRGB profile: 4.0 seconds
Software render using Linear Generic RGB profile: 5.3 seconds
GPU render using sRGB profile: 7.3 seconds
GPU render using Linear Generic RGB profile: 7.7 seconds
  1. These results are completely 180º turned around from the results that I’d expect. If I was to accept them as unquestioned truth then I’d have to decide to always just work using the sRGB profile and to do all rendering via software and not worry about using the GPU unless I needed to offload work from the CPU.

A later observation (Friday 2nd Mary 2014), when drawing text into a bitmap context and running off battery power, I’m informed that the system has switched temporarily to using the discrete graphics card and then informed soon after it has switched back.

Tags: , ,

MovingImages CoreImage Transition Filter Example

I’ve written a number of ruby scripts that use MovingImages. One of the recent ones takes advantage of the CoreImage filter functionality that I’ve recently hooked into Moving Images. You’ll get to see this in the second alpha release which I’m pleased to say will be released soon.

The script is called exactly as shown below:

./dotransition --count 30 --sourceimage "/Users/ktam/Pictures/20140422 Pictures/DSC01625Small2.JPG" --destinationimage "/Users/ktam/Pictures/20140422 Pictures/DSC01625Small2.JPG" --basename PageCurl --outputdir "~/Desktop/deleteme/" --backsideimage "/Users/ktam/Pictures/20140422 Pictures/DSC01625SmallCropped.jpg" --angle=-3.07 --transitionfilter CIPageCurlTransition --extent 0,0,463,694 --verbose

I then used a script that you can download that works with the first alpha release of MovingImages and was called exactly as shown below:

./createanimation --delaytime 0.1 --outputfile ~/Desktop/PageTurningAnimation.gif --verbose ~/Desktop/deleteme/PageCurl*.tiff

The result of running both those scripts

Gif animation where the same page is turned over forever

The MovingImages documentation shows the output images at each step of the filter chain. Scroll down past the generated json code to see the images.

The create animation script can be viewed here.

The do transition script can be viewed here.

And an earlier demonstration using the embossmask script

Moving Images

Backside image supplied to CIPageCurlTransition filter doesn’t take

Please see note at end.

I’ve not been able to get setting the “inputBacksideImage” key to work when setting an image to use as the image displayed on the reverse side when a page is being curled over. I’ve not seen any reports that this is broken anywhere on the internet, so I thought I’d just let people know here.

As of OS X 10.9.2 using Xcode 5.1 developer tools, this option doesn’t work.

I’ve posted sample code for a command line tool that demonstrates the problem. This is the same code I used in my bug report to Apple. The sample code can be viewed as a gist on git hub: https://gist.github.com/SheffieldKevin/9873485

Note: This is not broken. The circle in the shading image needs to be partially transparent. The shading image is applied on top of the backside image and covers it up unless it is partially transparent. I’ve updated the code in the gist and everything works as it should.

CoreImage, CIPageCurlTransition, Cocoa, inputBacksideImage, broken, OS X

 

SSD versus HDD, Movie Frame Grabs and the importance of profiling

There was an e-mail to Apple’s cocoa-dev e-mail list that provoked a bit of discussion. The discussion thread starts with this e-mail to cocoa dev by Trygve.

Basically Trygve was wanting to get better performance from his code for taking frame grabs from movies and drawing those frame grabs as thumbnails to what I call a cover sheet. Trygve was using NSImage to do the drawing and was complaining that based on profiling his code was spending 90% of the time in a method called drawInRect.

Read the rest of this entry »

Tags: , , , , , , , ,