Sonntag, 19. Juli 2015

Multiline chart, now with less code

I started adding some convenience classes to SwiftCharts to create popular charts quickly.

This is how now a multiline chart is created:

let chart = LineChart(
    frame: CGRectMake(0, 70, 300, 500),
    chartConfig: ChartConfig(
        xAxisConfig: ChartAxisConfig(from: 2, to: 14, by: 2),
        yAxisConfig: ChartAxisConfig(from: 0, to: 14, by: 2)
    ),
    xTitle: "X axis",
    yTitle: "Y axis",
    lines: [
        (chartPoints: [(2.0, 10.6), (4.2, 5.1), (7.3, 3.0), (8.1, 5.5), (14.0, 8.0)], color: UIColor.redColor()),
        (chartPoints: [(2.0, 2.6), (4.2, 4.1), (7.3, 1.0), (8.1, 11.5), (14.0, 3.0)], color: UIColor.blueColor())
    ]
)
self.view.addSubview(chart.view)

Of course the "low level" api and examples continue to be available, and should be used when the convenience charts don't provide the required level of customization.

More will follow!

Dienstag, 14. Juli 2015

Some utility functions to work with Realm in iOS

I started using Realm today. So far a very good first impression! My initial ~1000 lines of core data shrank to 350 lines, which are also generally easier to understand. It also took me only about 3 hours to port the core data code which I wrote in about 3 days. I hope it continues like this.

Since I was repeating a lot of code, I wrote these helper functions for simple operations, so I can now load and save using mostly 1-liners. I use GCD to execute the read and writes in the background, so the db access doesn't block the UI. I also use a model layer, which is entirely decoupled from the database (*).

Here are the functions:

Update for Swift 2:
func saveObj<T: Object>(obj: T, update: Bool = false, handler: Bool -> ()) {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
        do {
            let realm = try Realm()
            realm.write {
                realm.add(obj, update: update)
            }
            dispatch_async(dispatch_get_main_queue(), {
                handler(true)
            })
        } catch _ {
            print("Error: creating Realm")
            dispatch_async(dispatch_get_main_queue(), {
                handler(false)
            })
        }
    })
}

//usage:
saveObj(myRealmObj, update: true, handler: myHandler)


func saveObjs<T: Object>(objs: [T], update: Bool = false, handler: Bool -> ()) {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
        do {
            let realm = try Realm()
            realm.write {
                for obj in objs {
                    realm.add(obj, update: update)
                }
            }
            dispatch_async(dispatch_get_main_queue(), {
                handler(true)
            })
        } catch _ {
            print("Error: creating Realm")
            dispatch_async(dispatch_get_main_queue(), {
                handler(false)
            })
        }
    })
}

//usage:
saveObjs(myRealmObjs, update: true, handler: myHandler)


// mapper is a function that maps a database object of type T to a model object of type U
// filterMaybe filter string as in Realm's docs e.g. "name = 'foo'"
// handler function which gets the model object U, which was generated by mapper, as parameter
func load<T: Object, U>(mapper: T -> U, filter filterMaybe: String? = nil, handler: [U] -> ()) {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
        do {
            let realm = try Realm()
            
            var results = realm.objects(T)
            if let filter = filterMaybe {
                results = results.filter(filter)
            }
            
            let objs: [T] = results.toArray()
            let models = objs.map{mapper($0)}
            
            dispatch_async(dispatch_get_main_queue(), {
                handler(models)
            })
            
        } catch _ {
            print("Error: creating Realm")
            dispatch_async(dispatch_get_main_queue(), {
                handler([])
            })
        }
    })
}

//usage:
let mapper = {realmObj in
    return MyModelObj(name: realmObj.name, color: realmObj.color)
}
load(mapper) {myModelObjs in
    // do something with models
}


// pred string as in Realm's docs e.g. "name = 'foo'"
func remove<T: Object>(pred: String, handler: Bool -> (), objType: T.Type) {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
        do {
            let realm = try Realm()
            let results: Results<T> = realm.objects(T).filter(pred)
            realm.write {
                realm.delete(results)
            }
            dispatch_async(dispatch_get_main_queue(), {
                handler(true)
            })
        } catch _ {
            print("Error: creating Realm")
            dispatch_async(dispatch_get_main_queue(), {
                handler(true)
            })
        }
    })
}


extension Results {
    //loads the results into an array    
    func toArray() -> [T] {
        return self.map{$0}
    }
}

extension RealmSwift.List {    
    func toArray() -> [T] {
        return self.map{$0}
    }
}




Swift 1.2:
func saveObj<T: Object>(obj: T, update: Bool = false, handler: Bool -> ()) {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
        let realm = Realm()
        realm.write {
            realm.add(obj, update: update)
        }
        dispatch_async(dispatch_get_main_queue(), {
            handler(true) // I don't know exactly yet what to return here, since Realm's operations don't return anything. For now indicates method executed successfully.
        })
    })
}

//usage:
saveObj(myRealmObj, update: true, handler: myHandler)


func saveObjs<T: Object>(objs: [T], update: Bool = false, handler: Bool -> ()) {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
        let realm = Realm()
        realm.write {
            for obj in objs {
                realm.add(obj, update: update)
            }
        }
        dispatch_async(dispatch_get_main_queue(), {
            handler(true)
        })
    })
}

//usage:
saveObjs(myRealmObjs, update: true, handler: myHandler)
    

// mapper is a function that maps a database object of type T to a model object of type U
// filterMaybe filter string as in Realm's docs e.g. "name = 'foo'"
// handler function which gets the model object U, which was generated by mapper, as parameter
func load<T: Object, U>(mapper: T -> U, filter filterMaybe: String? = nil, handler: [U] -> ()) {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
        var results = Realm().objects(T)
        if let filter = filterMaybe {
            results = results.filter(filter)
        }
            
        let objs: [T] = Realm().objects(T).toArray()
        let models = objs.map{mapper($0)}
            
        dispatch_async(dispatch_get_main_queue(), {
            handler(models)
        })
    })
}

//usage:
let mapper = {realmObj in
    return MyModelObj(name: realmObj.name, color: realmObj.color)
}
load(mapper) {myModelObjs in
    // do something with models
}    
    
 
// pred string as in Realm's docs e.g. "name = 'foo'"
func remove<T: Object>(pred: String, handler: Bool -> (), objType: T.Type) {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
        let realm = Realm()
        let results: Results<T> = realm.objects(T).filter(pred)
        realm.write {
            realm.delete(results)
        }

        dispatch_async(dispatch_get_main_queue(), {
            handler(true)
        })
    })
}

//usage:
remove("name = 'foo'", handler: myHandler, objType: MyRealmObject.self)


extension Results {
    //loads the results into an array    
    func toArray() -> [T] {
        return map(self){$0}
    }
}



I hope this is useful to somebody, and if there's something to improve please add a comment!

(*) This has pros and cons, (roughly), pros: decoupling from db, cleaner models, fixes issue with Realm of not being able to read in the background and use the result objects in the main thread. Cons: performance, since the query result has to be loaded into memory and mapped, but for regular, limited/segmented datasets and considering that loading and parsing is done in the background this is not an issue.

Montag, 13. Juli 2015

Donnerstag, 19. März 2015

Function wrapping fun in Swift

I was today looking for a convenient way to wrap table view updates with begin/end updates, and also with the probably well known CATransaction.setDisableActions which is sometimes necessary to turn the animations really off.

As an introduction, here is how this is done normally:
        
tableView.beginUpdates()
// code updating table view
tableView.endUpdates()

CATransaction.setDisableActions(true)
// code with animations actually disabled
CATransaction.setDisableActions(false)

If we need both, we have to write:
        
tableView.beginUpdates()
CATransaction.setDisableActions(true)
// code updating table view and animations actually disabled
CATransaction.setDisableActions(false)
tableView.endUpdates()

This is not terribly painful to do, but it looks like something that can be implemented nicely using functional programming. Let's see.

The most basic approach is to put our updates in a function, that will be passed to another function, which executes the surrounding code:

func wrapUpdates(function:()->()) {
    tableView.beginUpdates()
    function()
    tableView.endUpdates()
}

we would call it like this:
        
wrapUpdates({println("doing some table view updates")})

Same with disable actions...
        
func wrapDisableActions(function:()->()) {
    CATransaction.setDisableActions(true)
    function()
    CATransaction.setDisableActions(false)
}

wrapDisableActions({println("doing some table view updates")})

And for both of them combined:
func wrapUpdatesDisableActions(function:()->()) {
        tableView.beginUpdates()
        CATransaction.setDisableActions(true)
        function()
        CATransaction.setDisableActions(false)
        tableView.endUpdates()
}

wrapUpdatesDisableActions({println("doing some table view updates")})


This is not so bad, at least we avoid having to repeat code when we need this exact functionality. But you see we are, still, repeating code. Imagine that instead of 2 lines our wrappers would have a lot of code. Imagine also, that we need more wrappers, different combinations, maybe different ordering. We would need each time a new function with repeated code. The solution for this kind of problem would be to to have reusable wrapper functions, which we can combine arbitrarily. The keyword for this is composition.

How do we achieve it?

The basic idea, is to have functions that return functions, that we can then wrap (also called "decorate") with other functions, and so on and so on. We end with one "composed" function, which basically will call all the functions when we call it. Let's see it in the example.

We will now write wrapUpdates such that it returns a function:
        

func wrapUpdates(function:()->()) -> ()->() {
    return {
        tableView.beginUpdates()
        function()
        tableView.endUpdates()
    }
}

The signature is a bit unwieldy so we will create a typealias for our function.
        
typealias VoidFunction = ()->()

Now the signature is more readable:

func wrapUpdates(function: VoidFunction) -> VoidFunction {
       return {
        tableView.beginUpdates()
        function()
        tableView.endUpdates()
       }
}

Take note of the {} where we put the code in - this is the syntax to make the block of code a closure/function, which in this case doesn't accept any parameters or returns anything.

We do the same with disable actions function:

func wrapDisableActions(function: VoidFunction) -> VoidFunction {
       return { 
        CATransaction.setDisableActions(true)
        function()
        CATransaction.setDisableActions(false)
      }
}

We call like this:

wrapUpdates({println("doing some table view updates")})()

Note () at the end, to call the function.

Nothing really better yet, we have to type more and the code looks complicated. But the magic comes when we start combining the functions:

func wrapUpdatesDisableActions(function: VoidFunction) -> VoidFunction {
    return wrapDisableActions(
            wrapUpdates(
                function
            )
        )
}
wrapUpdatesDisableActions({println("doing some table view updates")})()
This is much nicer than the first example!


This is the basic idea behind function composition. But it's still looks like it could be expressed more concisely.

Here Swift's ability to declare custom operators comes handy. A quick lookup with Google gives us  a quite satisfactory result:

infix operator >>> { associativity left }
func >>> <A, B, C>(f: B -> C, g: A -> B) -> A -> C {
    return { x in f(g(x)) }
}

You can find in that page an explanation and a very intuitive example of using this function for string manipulation. We will continue with our table view updates. The main difference is that we pass around functions instead of strings.

Now our wrapUpdatesDisableActions can be transformed into this awesomeness:
        
let wrapUpdatesDisableActions = wrapDisableActions >>> wrapUpdates

The call looks the same as before:
        
wrapUpdates({println("doing some table view updates")})()

Imagine what can be achieved with other, more complex examples:

let composed1 = f1 >>> f2 >>> f3 >>> f4 >>> f5
let composed2 = f2 >>> f5 >>> f4

composed1()
composed2()
//etc. etc.

Quite nice!

Appendix

In order to make our utilities generic, we can put them in extensions:

extension CATransaction {
    class func wrapDisableActions(function: VoidFunction) -> VoidFunction {
        return {
            CATransaction.setDisableActions(true)
            function()
            CATransaction.setDisableActions(false)
        }
    }
}

extension UITableView {
    func wrapUpdates(function: VoidFunction) -> VoidFunction {
        return {
            beginUpdates()
            function()
            endUpdates()
        }
    }
    
    var wrapUpdatesDisableActions: VoidFunction -> VoidFunction {
        return wrapUpdates >>> CATransaction.wrapDisableActions
    }
}
Note the composing closure is now in a computed variable - this way we have access to self.

 Now everytime we want to do begin end updates with (really) disabled animations, we just have to:
tableView.wrapUpdatesDisableActions({
    //do table view updates
})()

Samstag, 28. Februar 2015

Interval mapping / playing with intervals and functions in Swift

Playground (Gist)

Diverse approaches of mapping intervals to something. And learning a bit of Swift on the way.

For example, given a mapping of interval 0..<2 to a string "first interval" and 2..<4 to a string "second interval", we want to get the string for the value 3.4.

I started thinking about this because in my work I had to map rating intervals to certain background colors. If e.g. a user gives a 5.9 rating this would be in the range 4.5 - 6.0 which has to be displayed with a dark green background, etc. Sadly I had to do this using objc. I wondered how I would do it with Swift.

We start with the most primitive way:

let n = 3.4
let found1:String? = {if n < 2 {
    return "first"
} else if n < 4 {
    return "second"
} else {
    return nil
}}()

println("found: \(found1)") //found: Optional("second")

It's also possible to use a switch case. But I think switch case is not really meant to be used like this. Here I'm only exploring the possibilities of the language.

let found2:String? = {switch n {
    case _ where (0..<2) ~= n: return "first"
    case _ where (2..<4) ~= n: return "second"
    default: return nil
    }
}()

println("found: \(found2)") //found: Optional("second")

These approaches are a bit unflexible. And the worst: NOT FANCY! So we explore further.

Intro: get (first) containing range for a value
let result:HalfOpenInterval<Float>? = {
    for r:HalfOpenInterval<Float> in [(0..<1), (1..<2), (2..<3)] {
        if r ~= 2 {
            return r
        }
    }
    return nil
}()

Good! Now, we will make a helper struct that holds the range and the object:

struct RangedEntry<T> {
    let interval:HalfOpenInterval<Float>
    let obj:T
    
    init(_ interval:HalfOpenInterval<Float>, _ obj:T) {
        self.interval = interval
        self.obj = obj
    }
}

Now we can iterate through entries to find our match:

for re in [
    RangedEntry((0..<1), "a"),
    RangedEntry((1..<2), "b"),
    RangedEntry((2..<3), "c")
    ] {
        
        if re.interval ~= 1.9 {
            println("found: \(re.obj)") // found: b
            break;
        }
}

Alternatively, we can just use tuples:

for r:(HalfOpenInterval<Float>, String) in [
    ((0..<1), "a"),
    ((1..<2), "b"),
    ((2..<3), "c")
    ] {
        if r.0 ~= 1.9 {
            println("found: \(r.1)") // found: b
        }
}

What about more functional constructs?

Let's try out filter (we will continue using tuples):

let value:String? = [
    ((0..<1), "a"),
    ((1..<2), "b"),
    ((2..<3), "c")
    
    ].filter{(tuple:(HalfOpenInterval<Float>, String)) -> Bool in
        return tuple.0 ~= 1.9
        
}.first?.1

println("found: \(value)") // found: Optional("b")


This is O(n), since we will examine the whole array each time. Not so good. Coming back later to this. Also note we assume that the ranges don't overlap.

What if we want to generate the ranges dynamically, say, divide 1...7 in 16 equal parts?
Since in this case the intervals are continuos, we can represent them just as a succession of numbers.
We can use strides for this:

let start:Float = 1
let end:Float = 7
let sections = 16
let intervalLength:Float = (end - start) / Float(sections)


let s = stride(from: start, through: end, by: intervalLength)
Array(s) // see contents in playground

// generate tuples with dummy value objects. The start of the range represents the range, and we associate the value object with it.
let tuples:[(Float, String)] = Array(s).map {(val:Float) -> (Float, String) in
    return (val, "range starts:\(val) ends: \(val + intervalLength)")
}

Now let's try out an alternative approach to =~. Since in this case we know the ranges are sorted in increasing order, we can use this information to find the value.

The number we will search from now on:
let search:Float = 4.12

This is a simple filtering function with which we retrieve the ranges witch a start value smaller than our searched value:
let filtered = tuples.filter {
    return $0.0 < search
}

The range we are looking for is the range with the biggest starting value from result of above filtering. Since we know the ranges are sorted increasingly, we can just pick the last one from the filter results:
let val:String? = filtered.last?.1
println("found: \(val)") // found: Optional("range starts:4.0 ends: 4.375")
In this case we expect the ranges to be sorted, since we assumed this for the filtering. In an imaginary case that we didn't know that the values are sorted, we could get the range with the max. starting value using reduce:
let val1:String? = {
    filtered.isEmpty ? nil : filtered.reduce(filtered.first!, {
        return $0.0 > $1.0 ? $0 : $1
    }).1
}()

println("found: \(val1)") // found: Optional("range starts:4.0 ends: 4.375")

So far functions. But in order to avoid having to go through the whole array each time, we will use a loop, that exits when we find the range.
Since there's no filtering step, we have to add logic to look ahead in the next range. If there's no next, or if its starting value is bigger than searched value, we know we are in the searched range.

let myresult:String? = {
    for (index, tup) in enumerate(tuples) {
        if tup.0 <= search && (index + 1 == tuples.count || tuples[index + 1].0 > search) {
            return tup.1
        }
    }
    return nil
}()

println("found: \(myresult)") // found: Optional("range starts:4.0 ends: 4.375")

Talking about indices and look-ahead, here is a similar approach using filter (just demonstrative purpose - would not use it):
let val2:String? = Array(enumerate(tuples)).filter { (index:Int, element) -> Bool in
    return element.0 <= search && (index + 1 == tuples.count || tuples[index + 1].0 > search)
}.first?.1.1


println("found: \(val2)") // found: Optional("range starts:4.0 ends: 4.375")


So is there a way in which we use a functional construct with the performance of for loop?
We need something similar to a find function. This is an example of a find function:
(this is btw a nice to have in array extension)

func find<T>(arr:Array<T>, pred:(element:T)->Bool) -> T? {
    for i in 0..<arr.count {
        let element =  arr[i]
        
        if pred(element: element) {
            return element
        }
    }
    return nil
}

In our current case we need that the predicate, besides of the current element, considers also the next one (note nextElement is optional - when we are examining the last element, there's no next element), so we create a customized version of find:

func findWithNextElement<T>(arr:Array<T>, pred:(element:T, nextElement:T?)->Bool) -> T? {
    for i in 0..<arr.count {
        let element =  arr[i]
        let nextElement:T? = i + 1 < arr.count ? arr[i + 1] : nil
        
        if pred(element: element, nextElement: nextElement) {
            return element
        }
    }
    return nil
}

We would call it like this:

let val4:String? = findWithNextElement(tuples, { (element, nextElement:(Float, String)?) -> Bool in
    return (element.0 <= search) && (nextElement?.0 > search ?? true)
})?.1


println("found: \(val4)") // found: Optional("range starts:4.0 ends: 4.375")

Here is everything in a gist, which you can copy paste in a playground. This is much nicer to follow looking at the results pane on the right, and doing live changes. Have fun!

Donnerstag, 24. Juli 2014

Scene Kit dragging / picking demo for OS X / iOS

I just published this little demo of Scene Kit, where we can drag around a 3d model and select individual parts. For OS X and iOS using Swift.




The code in probably self explanatory (if not, I'm sorry...). The 3d program needs to give each object a name, which we use to identify what we picked - in the case of this example, we use it to show the label at the bottom "Right foot" etc. The model has to be exported to .dae.

In Blender the name of the object is here:





Code:

OS X:
https://github.com/i-schuetz/scene_kit_pick

iOS:
https://github.com/i-schuetz/scene_kit_pick_ios

The iOS version is laggy, at least in the simulator, don't think it's related with the code or my super complex 3d model ;). It might be a bug of the beta.

Donnerstag, 3. Juli 2014

Items drag & drop iOS exercise

This is a little exercise I did to practice gesture recognizers, collection view, and snapping effect effect using UIDynamicAnimator (iOS 7).
We can drag and drop views from the bottom selector to top view. The views can be clicked to see more info. When view is dragged to invalid place it snaps back. Placed views can be removed by dragging back to the bottom.
This can be useful for e.g. placing furniture in a room, dressing a person, etc.
It needs refactoring, right now everything is in a view controller.


Code