HealthKit for iOS8: Part 4

iOS 8 HealthKit Santiapps Marcio Valenzuela
iOS 8 HealthKit Santiapps Marcio Valenzuela
iOS 8 HealthKit

Ok so the Journal view controller was quite simple.  Let’s take another quick break by looking at an even simpler view controller, the FoodPicker:

import Foundation

import UIKit

import HealthKit

class FoodPickerViewController: UITableViewController {

var selectedFoodItem: FoodItem?

let FoodPickerViewControllerTableViewCellIdentifier:NSString = "cell"

let FoodPickerViewControllerUnwindSegueIdentifier:NSString = "FoodPickerViewControllerUnwindSegueIdentifier"

var foodItems: NSArray = NSArray()

var energyFormatter: NSEnergyFormatter {

var energyFormatter: NSEnergyFormatter?

var onceToken: dispatch_once_t = 0

dispatch_once(&onceToken, {

energyFormatter = NSEnergyFormatter()

energyFormatter?.unitStyle = NSFormattingUnitStyle.Long

energyFormatter?.forFoodEnergyUse = true

energyFormatter?.numberFormatter.maximumFractionDigits = 2

})

return energyFormatter!

}

var  healthStore:HKHealthStore?

}

Here we are looking at imports, subclassing UITableViewController and property declarations.

Our first property is selectedFoodItem, which will be set to whatever value the user selects from this tableview as an item that he or she consumed.  Then we have 2 identifiers, one for our tableviewcell and another for our unwind segue.  Remember to set both in the storyboard.  To set the cell identifier you must select the cell in the tableview and for the unwind segue you must select the segue from the “Add” button in Journal to the FoodPicker.  Then we create an array to store the hard coded values of our FoodItems.  Ideally you might want to pull this data from a web service.

Notice we use the NSEnergyFormatter here again.  You could also just create a class for this and access it globally.  Finally we add our health store variable.

Now let’s look at our viewDidLoad method:

override func viewDidLoad() {

super.viewDidLoad()

self.foodItems = [FoodItem(name: "Wheat Bagel", joules:240000.0),

FoodItem(name: "Bran with Raisins", joules:190000.0),

FoodItem(name: "Regular Instant Coffee", joules:1000.0),

FoodItem(name: "Banana", joules:439320.0),

FoodItem(name: "Cranberry Bagel", joules:416000.0),

FoodItem(name: "Oatmeal", joules:150000.0),

FoodItem(name: "Fruits Salad", joules:60000.0),

FoodItem(name: "Fried Sea Bass", joules:200000.0),

FoodItem(name: "Chips", joules:190000.0),

FoodItem(name: "Chicken Taco", joules:170000.0) ]

}

Nothing special here, just hardcoding some FoodItems into our array.  So now our tableview methods:

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

return self.foodItems.count

}

override func tableView(tableView: UITableView?, cellForRowAtIndexPath indexPath: NSIndexPath?) -> UITableViewCell {

let cell: UITableViewCell = self.tableView.dequeueReusableCellWithIdentifier(FoodPickerViewControllerTableViewCellIdentifier, forIndexPath:indexPath!) as UITableViewCell

var foodItem: FoodItem = self.foodItems[indexPath!.row] as FoodItem

cell.textLabel.text = foodItem.name

cell.detailTextLabel?.text = energyFormatter.stringFromJoules(foodItem.joules)

return cell;

}

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

NSLog("performing unwind segue from FOODPICKER!")

if (segue.identifier == FoodPickerViewControllerUnwindSegueIdentifier) {

var indexPathForSelectedRow: NSIndexPath = self.tableView.indexPathForSelectedRow()!

self.selectedFoodItem = self.foodItems[indexPathForSelectedRow.row] as? FoodItem

}

}

There, now that’s a nice breather.   We set our rows according to the number of items in the array, set our cell values in the same way we did before.  And in our prepareForSegue method, we check our identifier and then set our own selectedFoodItem property from whatever the user selected.

Ok so you’ve had 2 easy classes to rest.  Now let’s get into the longest one, Part 5.

Swift Closures Quick Reference: Part 2

Let’s analyze some useful applications of closures in everyday code!

Ok so let’s take a look at a real life function that uses a closure.  A typical closure is a completion handler.  A completion handler is a parameter, just like any other, that is passed into a function as a closure.  When that code gets executed, the completion handler gets filled.  Then your function will use the value of that completion handler to do something useful.

Here are some typical uses of closures in API’s.  The typical one is UIView.animateWithDuration.  Open Xcode and start writing UIView.anim… and it will autocomplete for you with this:

UIView.animateWithDuration(<duration: NSTimeInterval>, animations: <() -> Void() -> Void>)

This is telling you that the animateWithDuration takes 2 parameters:

duration which is an NSInterval type called duration &

animations which is a closure type which takes void parameters and returns void.  Remember, animations is just another variable we are passing in, so its separated with a comma from duration.

If you hit enter over the duration parameter, you can write in whatever you want.  If you then tab, it moves over to the ()->Void parameter.  Hit enter again.  The closure turns into this format:

{ () -> Void in
<#code#>
}

Where the { } define your closure and you can see the closure takes () and returns -> () as well.  Except that in this case the final () after -> are replaced by the keyword Void.  Then we get our keyword to transition from the ending ->() in a function to our actual function or closure code which will be enclosed in { }.

In the end you might end up with something like this:

UIView.animateWithDuration(1, 
animations: {() in redBox.alpha = 0 }, 
completion:{(Bool) in println("red box has faded out") })

which is interpreted as:

The function animateWithDuration says: “The value for the duration parameter is 1 second.  The value for animation is a closure of block of code enclosed by { }.  Finally the value for completion is also a closure enclosed by a second { }.”

The animation closure says: “I take no parameters and return void and my code is = in = change the redBox’s alpha to 0.

The completion closure says: “I takes a Bool parameter and returns void and my code is = in = print the message.”

So we are passing those 2 blocks of code to be executed into the function as parameters.

It basically translates to this:

UIView.animateWithDuration(duration: NSTimeInterval, 
 animations: (() -> Void)?, 
 completion: ((Bool) -> Void)?)

Where are you can see, 3 parameters out of which 2 are closures.  Both closures return void but the second one takes a Bool.

So what does it mean?  Well, it says:

1. Here is how much the duration is going to last

2. Here is the animation you will perform inside of the { }.  That requires no parameters and returns nothing.

3. Oh and btw, here is another block of code { } but take a Bool and only execute { } if the Bool is true.  The Bool is set to true when the animation passed in has already finished.

Let’s take a quick look at some closures you’ll find in Apple API’s:

1.  This passes in the dispatch queue as parameter 1 and a closure to downloadData as parameter 2.

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), {
self.downloadDataForRegisteredObjects(true, toDelete:false)
})

2.  This function called performBlockAndWait passes in a closure without parameters and with Void and the code to be executed PLUS another function called executeFetchRequest.

CoreDataController.sharedDataController.backgroundManagedObjectContext?.performBlockAndWait({ () -> Void in
var error:NSError?
var results:NSArray
CoreDataController.sharedDataController.backgroundManagedObjectContext?.executeFetchRequest(request, error:&error)
if ((results.lastObject) != nil)   {
date = (results.lastObject as NSArray).valueForKey("updatedAt") as? NSDate
}
}) 

3.  This assigns a function return to a variable.  That function is GET() and it receives a className parameter, a parameters parameter and a success completion block parameter.  That success completion block parameter is a closure that takes an operation and a response and returns void.  It is called when the operation was successful and writes the operation’s response to disk. If the operation fails, it logs the error.

var operation: AFHTTPRequestOperation = self.GET("classes/\(className)", parameters: parameters, success: { (operation, response) -> Void in
// success code...
if response.isKindOfClass(NSDictionary) {
self.writeJSONResponse(response, className:className as NSString)
}
}, failure: { (operation, error) -> Void in
// failure code...
NSLog("Request for class %@ failed with error: \(className), \(error)")
}) 

4.  This assigns the function result to a variable as well.  It calls the batchOfRequestOperations method and passes it an operationsArray and a progressBlock and a completion block but in this case you can’t see the “completion” name of that last parameter.  Sometimes when you start writing out a function name and it takes a closure as a parameter and its the last one, you don’t have to name it? Why?

var batchOperations: NSArray = AFURLConnectionOperation.batchOfRequestOperations(operationsArray,
          progressBlock: { (finishedOps:UInt, totalOps:UInt) -> Void in
                    NSLog("%lu of %lu complete", finishedOps, totalOps)
})  { (op) -> Void in
                    if (!toDelete) {
                              self.processJSONDataRecordsIntoCoreData()
                    } else {
                             self.processJSONDataRecordsForDeletion()
                   }
}

I guess its because it’s the last parameter in the method call.

Next we take a look at writing our own closures.

Swift Closures Quick Reference: Part 1

Blocks/Closures are confusing!  They’re confusing because its a bit abstract.  Most tutorials cover how a block is declared and used.

Sometimes blocks or closures can me even more confusing…

A block is a bunch of code wrapped up in a {}.

You can 2 either of 2 things with them:

A.  You can assign that block of code to a variable. (this is where completionHandlers, also a confusing concept, fit in)

B.  You can use that block of code directly

Let’s take a look at assigning it to something.  No doubt you have seen a construct like:

var someName = “Mars”

or

var hisAge = 39

This would be considered hardcoding that value to the variable.

Now surely you have seen a function that does something more practical such as calculate or do something in order to return a value.  In the case of someName, well, we could fetch it from a list of users in a web service database.  In the case of hisAge we could calculate it.  Either process would occur in a function.  So we could instead of hardcoding a value, say:

var someName = getHisName()

or

var hisAge = getHisAge()

Well what we are doing here is actually ‘passing a block of code’ to a variable already.  Sorta.  We could somehow imagine that:

var hisAge = getHisAge() { //all the code inside getHisAge function }

which translates to:

var hisAge = { //all the code inside getHisAge function }

Ok, so that’s more or less what a block or closure is.

Where it gets weird, or complicated but just because of the way it looks is when they are passed to functions. You could go ahead and say something like:

func thisIsSomeFunction () -> () { //code }

which is a function that doesn’t take parameters and returns nothing.  Let’s give it a parameter:

func thisIsSomeFunction (aParameter:pType) -> () { //code }

This takes aParameter of pType.  Now replace that parameter with hisAge:

func thisIsSomeFunction (hisAge) -> () { //code}

Now let’s replace hisAge for what it stands for (which is { //all the code inside getHisAge function } )

func thisIsSomeFunction (  () -> () ) -> () { //code}

where () -> () stands for whatever hisAge is equal to, which is the getHisAge function…

Of course the getHisAge function must at least return something, an age, which would typically be an Int:

func thisIsSomeFunction (  () -> (Int) ) -> () { //code }

It would be wise to calculate someone’s age using at least his date of birth, so:

func thisIsSomeFunction (  (NSDate) -> (Int) ) -> () { //code }

Ok so our getHisAge function is in blue and it is passed into this new function.  Now it would be nice to pass in the original getHisAge code which would fit somewhere in here:

func thisIsSomeFunction (  (NSDate) -> (Int) {//getHisAge code} ) -> () { //code }

So for this purpose we have the keyword “in”:

func thisIsSomeFunction (  (NSDate) -> (Int) in {//getHisAge code} ) -> () { //code }

Hope you enjoyed it.  See you in the next part!