CongenialApps

Teen Programming iOS Applications – By Faisal Syed


Dictionaries in Swift

By definition, a dictionary stores associations between keys and values of the same type in a collection with no defined order.

Verbose form of a dictionary object: Dictionary<Key,Value>

Short hand form: [key:value]

Here are a couple examples:

var nameOfNumbers = [Int:String]() //creates empty dictionary

nameOfNumbers[3] = "three" //assigns the value "three" to the key "3"

You can also initialize a dictionary literal to write one or more key-value pairs as a dictionary collection. Ex:

var identities: [String:Int] = ["Faisal":18, "Bob":32, "Sally":26]

In the above example, our “identities” dictionary is initialized with 3 key-value pairs.

 

To access the amount of items in your dictionary, you would use the “x.count” subscript syntax. You can also check if your dictionary is empty by using the “x.isEmpty” subscript syntax as well.

When updating a key-value entry in your dictionary object, you would use the: updateValue(_:forKey:) method. This method will return the original value right after the update, so you can see how your dictionary is changing and also be able to see how your dictionary is updating. It should also be noted that this method returns an optional, so be sure to value bind your way to your desired value instead of force unwrapping.

Iterating Over a Dictionary

for (name,age) in identities

{

    print("\(name) : \(age)")

}

You can also iterate through a dictionary to retrieve their keys or values. This can be achieved by using the “x.keys” or “x.values” subscript syntax. Here are some examples:

for names in identities.keys

{

    print(names)

}

for ages in identities.values

{

    print(ages)

}

In addition to the updateValueForKey method to add an object to a dictionary, you are also capable of using the removeValueForKey method which returns the old value it removed if the key for it exists. If not, then it returns nil. Just like the updateForKey method, removeValueForKey() returns an optional.

Lastly, we’re going to take a look at how to empty a dictionary. This can be achieved quite simply by using square brackets like so:

identities = [:] //0 keys and 0 values/pairs

 

No Comments

Protocols in Swift

Protocol: blueprint of methods and properties, and can be adopted by classes, structs, and enums.

Quick Example:

protocol Location

{

    var address: String {get set}

}

struct Person: Location

{

    var address:String

}

let Faisal = Person(address:"5 Nutcracker Street")

In the above example, we created a protocol called “Location” that requires an address of type String. We then created a struct called “Person” that conforms to our protocol as notated by the semi-colon.

Also, protocols serve as the backbone for delegates. They do this by saying, “Look. If you want to conform to me, you’ll have to write “x” methods and declare “y” variables.” Just like how we inherit from other classes, we want to use the semi-colon when we want a class, struct, or enum to conform to a protocol.

When comparing different values in swift, we use a variety of protocols that you may have heard of before. They include:

  • Equatable
  • Comparable
  • Printable

Protocols can also serve as types for a variable or constant for arrays and dictionaries. For example:

protocol Edible

{

    var nameOfFood:String {get set}

    func eat(amtOfFood amtOfFood:Int)

}

class Food:Edible

{

    var nameOfFood:String = "Sandwhich"

    func eat(amtOfFood amtOfFood: Int)

    {

      print("We're eating \(amtOfFood) of sandwhiches")

    }

}

func eatTheFood(foodItem:Edible)

{

    foodItem.eat(amtOfFood: 10)

}

var newFood = Food()

print(eatTheFood(newFood))

 

It should also be noted that protocols can inhere from each other. When they do, add their requirements on top of each other. You can also try something protocol composition, which is when you make a type adopt multiple protocols at once. Here’s an example:

protocol <OneProtocol, AnotherProtocol>

 

 

No Comments

Arrays in Swift

What are arrays? To put it simply, they allow you to store objects in a list to use later. In Swift, these objects must be all the same type, however you can bypass this by creating an array of type “AnyObject”. When you use “AnyObject”, you’re using a protocol which creates an instance of any type of object. It’s pretty self explanatory to be honest.

Here’s an example of a basic array:

var myArray = [Int]()

If we wanted to be more explicit and tell Swift that we are be going to make an array of type Int we would declare the line above like so:

var myArray:Array<Int> = Array<Int>()

 

Earlier we discussed how we could create arrays that store different types of objects, and here is how we would go about doing that:

var myAcceptingArray: Array<AnyObject> = Array<AnyObject>()

myAcceptingArray.append([1,2,3,4,5])

myAcceptingArray.append("Hello")

print(myAcceptingArray)

The console would return “1,2,3,4,5 Hello”, and would not give us any errors. If you noticed, we used something called “append” in the second and third lines of our code. “Append” pretty much means addObject if you remember that from Objective-C.

What if I told you that there was a much simpler way of declaring an array that could hold many different types of variables by using objects in Swift from Objective-C. Here’s how you do it:

var myArray:NSArray = [1, "hi", Float(4)]

As you can see from above, we put an integer, string, and float into one array. As expected, we received no errors from the console.

If you’re familiar with Objective-C, you’ll know that there are two types of arrays. NSMutableArray and NSArray. The difference between these two is that one is changeable and the other on isn’t. In Swift, we simply use “var” when creating an array to make it mutable, and “let” when we don’t want the content of our array to change.

Inserting and Removing Objects in Arrays

To insert an element at the beginning of an array, you’re going to want to use “insert” and “atIndex”. The first word is adding an object and “atIndex” is telling Swift where to add the object in your array’s sequence. Here’s a quick example:

var numbers = [1,2,3]

numbers.insert(0, atIndex:0)

Now if we print “numbers” it will return: 01,2,3. This is because we added the number “0” to the index of 0, which is always the first one in any array.

There are two ways to go about removing items in an array. You can use the removeLast() function to remove the last object in your array, and you can also use “removeAtIndex” to be more precise about which object you want to remove.

var people = ["Henry", "Bob", "Sarah"]

people.removeAtIndex(1)

The second line of code will remove “Bob” since he’s at the 1st index. Henry is at 0 and Sarah is at 2.

Iterating Over an Array

When you iterate through an array, you’re getting each object from it from beginning to end. Here is an example on how to iterate through a basic array:

var peopleArray = ["Henry", "Bob", "Sarah"]

for names in peopleArray

{

    print(names) //This will return "Henry", "Bob" and "Sarah"

}

To get the current index to teach the objects in your array, you can use the “enumerate()” function like so:

for (i, names) in peopleArray.enumerate()

{

print("The index /(i) has the person /(names)")

}

The console will return the index of either 0,1,2 and the names “Henry, Bob and Sarah”.

To create an array that is pre-populated with data, you may use the “repeatedValue” parameter:

var exampleArray = [Int](count: 5, repeatedValue:1) //This will return: 1,1,1,1,1

Lastly, to empty an array you use the “[]”. Here’s a quick example:

myArray = [] //This code will empty myArray
No Comments

Functions in Swift

Functions are typically comprised of three things: the name of the function, its parameter(s), and a return type. 

Here’s an example of a function written in Swift

func yourFuncName (paramName: paramType) ->returnType

{

    //Do something here

}

Here is how you would call your function “yourFuncName”:

yourFuncName()

Now let’s create a legitimate function which returns the sum of two integers:

fun add(x: Int, y:Int) ->Int

{

    return x + y

}

let theSum = add(12, y:14)

print ("\(theSum)") //This will print 26

So let’s break down the function above. We gave it a name of “add”. That’s the first component. We then gave it two parameters  called “x” and “y” and set the parameter types to integers. That covers the second component. For our third and final component of our function, we gave it a return type of “Int”. In the body of our function, we told it to return the value of the sum of our integers. So in our next line of code where we create the constant called “theSum”, we pass in the integers “12” and “14” to our function. Our “add” function sets “x” equal to “12” and “y” equal to “14”. It then goes about it’s arithmetic process and returns the value of “26”, which we printed out in our last line of code.

We talked about how parameters are one of the key components to a function, so let’s go over different types of parameters.

Default Parameter Values:

If a parameter has been declared with a default value, then it will also be an external parameter. External parameters provide better readability when passing in values into a function.

Here is an example of incorporating default parameters in a function:

func countAnimals (numberOfAnimals numAnimals:Int, nameOfAnimal: String = "Dog") ->String

{

    return String(numAnimals) + nameOfAnimal

}

let farm = countAnimals(numberOfAnimals:6)

print("\(farm)")

We create a function called “countAnimals” and give it two parameters: The first one of being type int, and the second one being of type String. We want to the function to return type string, so obviously we are going to convert our integer in the function. We did so by doing String(numAnimals). After that we created a constant, and passed in the numberOfAnimals value. Notice how we didn’t have to pass in the nameOfAnimal value. Since we are using a default parameter, we default to “Dog” every single time unless we include that parameter and change it to “Chicken” or “Cow”.

Variadic Parameters

These types of parameters permit you to pass as MANY parameters into a function as you’d like. To implement an unlimited amount of parameters, you need to use an ellipses which is three individual period: (…).

Here’s an example:

fun average(digits digits:Int...) ->

{

    var total = 0

    for x in digits

    {

        total +=x

    }

    return total /digits.count

}

The function above will give us an average of all the numbers passed into this function. This gives us the opportunity to create variables/constants like this:

let firstAverage = average(digits: 2,4) //returns 3

let secondAverage = average(digits:3,6,9) //return 6

As you can see, we could pass as many numbers as we’d like, and our function would return the average.

In-Out Parameters:

In-Out parameters allow you to pass a variable from outside the scope of a function and change it directly inside the scope of it. You are able to take a reference into the function’s scope and send it back out again.

Here’s an example of an inout parameter type function:

fun increaseNum(inout num num:Int, increaser:Int = 2)

{

    num =+increaser

}

var total = 0

increaseNum(num:&total) //this returns 2

Based on how we passed our “total” variable into our “increaseNum” function, you can see that we added a “&” sign before it. This is because when passing variables into a function with in-out parameters, you must include this sign.

 

 

 

 

 

No Comments

Value Types and Reference Types in Swift

Let’s define these terms:

Value Types: Each instance keeps a unique copy of its data, and is usually defined as a struct, enum, or tuple.

Reference Types: Instances share a single copy of the data, and the type is usually defined as a class.

Now let’s create a struct to show you how value types operate:

struct myStruct

{

var value:Int = 10

}

var a = myStruct()

var b = a

a.value = 16

print("\(a.value), \(b.value)")

While only being 8 lines of code, quite a few things are going on over here. Firstly, we create a struct called “myStruct”. As defined earlier, structs are a value type, which means that their copies will create an independent instance. Inside our struct we create an integer variable (also a value type) and set it equal to 10. In the following line, we create an instance of myStruct and call it “a”. After that, we create a variable called “b” and copy a’s value into b. At the current moment, the value of b.value is 10. In the next line we change the value of “a” to 16. This will not change the value of “b”, and this is because these objects are pointing towards their own memory storage.

Here is an example of a Reference Type using a class:

class Animal

{

var animalType:String = "Dog"

}

var animal1 = Animal()

var animal2 = animal1

animal1.animalType = "Cat"

print("\(animal1.animalType), \(animal2.animalType)")

This code looks very similar to our struct above. Here we create a class called “Animal” and give it a string property called “animalType” and set it equal to “Dog”. In the next line we create an instance of “Animal” called “animal1”. In the next line we create another variable called “animal2”, and copy the value from animal1 to animal2. The next line in which we alter the value for animal1.animalType DOES effect animal2.valueType. Why? When copying a reference type, you create a shared instance. What that means is that both animal1 and animal2 are pointing towards the same memory storage, hence the word “shared”. Therefore, their properties will be the same according to whichever one got updated the latest.

When you copy a reference type (i.e. a class), you create a shared instance. This means that after you copy your variable to another, they will both retrieve their value from a single instance of the data. So when you alter the value of the second variable, it will affect the first one. I know this sounds repeated, but more often than not, different ways of defining this process can prove to be beneficial to most.

Now let’s dive into what classes and structures have in common: (This is from the iOS Developer Library)

  • Define properties to store values
  • Define methods to provide functionality
  • Define subscripts to provide access to their values using subscript syntax
  • Define initializers to set up their initial state
  • Ability to expand their functionality beyond default implementation
  • conform to protocols to provide standard functionality

It should also be noted that assigning a variable/constant to a class instance, only increases the reference count to the underlying value. This applies to functions, which are also reference types.

Variables and Constants in Regards to Value/Reference Types:

Changing the value of properties in classes and structs isn’t an issue when it comes to variables, but constants work differently. When using a constant, your reference must remain constant. Similarly when working with value types, your value must remain constant.

In simpler terms: When using a class, you can mutate the properties of variables and constants with a hassle. However when working with a struct, you may not change the value of a property of a constant. You will have to change them to variables.

 

No Comments

For Loops and Structs vs. Classes

For loops grant us the ability to run code multiple times. There two types of for loops that we use in everyday programming:

  1. For-condition-increment loops: run code until the condition is met. With this type, you are able to increment a counter which will have the loop execute until the counter reaches a certain value.
  2. For-In loops: this type of loop is associated with fast enumeration. You can use this to iterate numbers in a range.

Example of a for-condition-increment loop:

for i = 0; i < 10; i++

{

    print("Hi there")

}

The console will return “Hi there” for a total of 10 times.

Here is an example of a for-in loop:

class Shoe {}

var shoes = [Shoe]()

for i in 1...4

{

    shoes.append(Shoe())

}

print("We have \(shoes.count) shoes!")

We do many things in the above code, so I’ll break it down. First we create a class called Shoe. We then create an array called shoes. In the loop, we state that for every time the code executes, we add an object to our array. So the console will say that we have 4 shoes.

Here is a type of declaration where we use type inference to assume that each object in an array of type [Shoe] will be a Shoe:

for shoe in shoes

{

    //Do stuff here

}

And here is how we declare it as type “Shoe” explicitly:

for shoe:Shoe in shoes

{

    //Do something here

}

Let’s consider the following:

struct Person
{

    var health:Int = 1

}

var person1 = Person()

var person2 = person1

person2.health = 2

If we run this code, the value of person1.health will be 1 and the value of person2.health will be 2. This is because structures in Swift are value types. Classes instead are reference types. If this were a class, then both objects would have their “health” property value equal to “2”. Remember, structures are copied by value rather than reference.

 

 

 

No Comments

Tuples, Typealias, and Writing Loops with Ranges

By definition, tuples are a compound type in swift. This means that they group multiple values into one value. Think of tuples as like an email. We create one draft that has many parameters such as the sender, subject, message body, and attachments. All of these components make up a single email.

Here’s an example of a tuple in Swift:

let emailDraft = ( to: "MyBoss", subject: "I'm Sick", body: "Sorry Boss, but I'm feeling under the weather")

Now we can use one of the indexes to grab a single property from our constant named “emailDraft”. If we try to get the object “emailDraft.subject”, the console will return the following string: “I’m Sick”.

There are ways in which you can decompose tuples, which means to turn a tuple into multiple variables to get control of each individual value.

The following is an example of decomposing a tuple:

let(emailSender, emailSubject, emailBody) = emailDraft

The objects above will receive values according to their index.

 

It should also be noted that tuples give functions multiple return values, and below is an example of just that:

func getEmail(email:String) -> (sender:string, subject:string, body:string)

{

    return(sender:"Bob", subject:"Urgent News", body:"I just opened up a can of soda with my feet!")

}

let emailDraft = getEmail("compose")

 

Typealias: this is simply a shortcut to get on already existing type by giving it an alternate name. For my next example, I’m going to give the type “String” a typealias of “Message”.

typealias Message = String

var randomVar:Message = "Hello There"

print(randomVar)

The console will return: "Hello There"

In the above code, we simply created a substitute name for the type “String”. For now this seems like a waste of time, but typealiases prove to be quite useful in more advanced swift development by making code much cleaner to read.

 

Let’s see how we can write this loop with ranges:

for var i = 0; i < 10; i++

{

    print("Hi There"

}

We have two options here: We can either used the closed operator, or the half open operator. The closed operator will produce all the integers from the range we give it, and the half open one will do the same thing except commit the final integer.

The loop with ranges can be seen here:

Closed Operator Version:

for _ in 0...10

{

    print("Hi There")

}

Half-Open Operator Version:

for _ in 0.. <11

{

    print("Hi There")

}

Both of the loops above will produce the integers 0-10, the only discrepancy is that they are written differently with two different uses of range operators.

 

 

No Comments

Optionals in Swift

After developing my latest apps in Swift, I decided that it was about time that I sat down and learned the language in depth. Compared to Objective-C, coding in Swift is much more efficient and clean. The topic I will be discussing today is the use of optionals.

In any project that is coded in swift, you will come across many variables that end in a “?”. This quotation mark signals the use of an optional value. An optional in swift means that the variable either has something in it, or it is nil. That way, if your variable sometimes requires being nil in your program’s execution, you’ll come across less errors than you would in Objective-C.

 

Here is an example of a string optional:

 

var optionalString:String? = “Hello World”

 

If you printed this string, you would get the following response from the console:

 

Optional(“Hello World”)

 

In order to get the raw value from your optional, you must “unwrap” it. One method of doing this is by value binding. This is the process in which you test to see if your variable is/isn’t nil.

 

Here is an example of value binding in action:

 

var containsObject:String? = “Hi I’m an object”

if let letter = containsObject

{

“There is an object: \(containsObject)”

}

else

{

“There is no object…”

}

 

In the above code, we create an optional variable in the first line. We set it to a simple string called “Hi I’m an object”. In the next line we are creating a constant called “letter” as shown by us using “let”. We are assigning our variable to this constant. If our variable contains something, we get the “There is an object” message returned in the console. If not, then we’ll get the “There is no object…” instead.

 

The next method of unwrapping an optional is called “force unwrapping”. If you are certain that your variable contains something, then you would add an “!”. Be careful when doing this, for if your optional is nil and you force unwrap it with an “!”, you will throw a fatal error and your whole project will crash. So use it wisely!

Here is an example of force unwrapping:

 

var optionalString:String? = “Hello World”

print(optionalString!)

 

The console will simple return:

 

“Hello World”

instead of

Optional(“Hello World”)

since you unwrapped it.

 

That wraps up the basics of optionals in Swift. To learn more, stay tuned to my upcoming blogs!

No Comments

New WatchKit App: MyCurrencyConversion

In order to regain my confidence in developing WatchKit applications, I decided it was time to code a simple currency converter application for the WatchKit and other iOS devices. In spite of my recent failures with WatchKit apps, I knew that I had to pursue this technology if I wanted to advance to higher level coding.

The main page of my app consists of a segmented control. In my ViewController.swift file, I have declared three global variables:

var theactiveCurrency = 0

var thecurrencies = [“GBP”, “EUR”, “JPY”, “CAD”]

var thecurrencyConversions = [0.7, 0.8, 0.9,1.5]

 

Then for my segmentedControl method, I used them like so:

 

@IBAction func theCurrencyChooser(sender: AnyObject) {

 

 

theactiveCurrency = segmentedControl.selectedSegmentIndex

 

theCurrencyLabel.text = (thecurrencies[theactiveCurrency])

 

 

 

 

}

 

I set my active currency to the selected item from my segmented control. That first line of code truly is self explanatory. The second line of code up there is basically stating that the text properly of my label should be equal to the active currency in my array of currencies.

The next part of my code has to do the parsing XML. I noticed that parsing XML is quite similar to the way I used to parse JSON, so this wasn’t too high of a learning curve for me. However, swift makes the code look much cleaner than objective-c. Props to you, Apple.

 

In my viewDidLoad method, I have the following code to parse the XML that I got from a Yahoo Web Service which contains the XML data for currency conversions.

override func viewDidLoad() {

super.viewDidLoad()

// Do any additional setup after loading the view, typically from a nib.

 

 

 

let url = NSURL(string: “http://finance.yahoo.com/webservice/v1/symbols/allcurrencies/quote”)

 

let task = NSURLSession.sharedSession().dataTaskWithURL(url!, completionHandler: { (data, response, error) -> Void in

 

if error == nil

{

println(NSString(data: data, encoding: NSUTF8StringEncoding))

var xmlParser = NSXMLParser()

xmlParser = NSXMLParser(data: data)

xmlParser.delegate = self

xmlParser.parse()

 

println(thecurrencyConversions)

 

}

 

else

{

println(error)

}

 

})

 

 

task.resume()

 

convertButton.layer.borderColor = UIColor.greenColor().CGColor

}

 

I store my url in a string, and then pass it on in my NSURLSession object. I name this object “task”, and I would like this object to return data from the url, any errors, and a response. After doing so, I check to see the data is nil with my if/else statement. I don’t want to be displaying any data that contains nothing in it! So I state that if the data is nil, then let us parse the XML, and store the data in an array called “currencyConversions”

After doing so, I had to add 2 delegate methods that comes with parsing XML. The first one deals with the element name:

func parser(parser: NSXMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [NSObject : AnyObject]) {

 

element = elementName

if attributeDict[“name”] != nil{

 

nameAttribute = attributeDict[“name”] as! String

}

 

else {

nameAttribute = “”

}

}

 

Again, I use my trusty if/else statement to check the value of the “name” field. If there is indeed an object stored there, I will store the value in my string object named “nameAttribute”. If there is nothing there, I assign an empty string value to nameAttribute.

 

My next delegate method is the foundCharacters method. This is where I loop through the array to find my desired currency.

func parser(parser: NSXMLParser, foundCharacters string: String?) {

 

if element == “field” && nameAttribute == “name” {

 

 

for (index, currency) in enumerate(thecurrencies)

{

 

if string == “USD/” + currency {

 

getCurrency = index

}

 

}

 

}

 

if element == “field” && nameAttribute == “price” && getCurrency != -1 {

 

println(string)

 

thecurrencyConversions[getCurrency] = NSString(string:string!).doubleValue

 

getCurrency = -1

 

}

}

 

This is kind of like levels in video games where your game has 3 levels, but 9 different possible outcomes. You want to find the 3 correct levels to beat the game. You take a step into the first level, and then you check if you are in the right area. If so, you proceed to the next level and so on. I basically used if/else statements to check if the names and currencies matched. I used -1 and 1 for my BOOLEAN values to decide whether it was found or not.

 

That was all the code for my main view controller. The next part pertains to the detail view controller.

I set up a few IBOutlets and whatnot for my labels and slider. I did that like so:

@IBOutlet var amountSlider: UISlider!

 

@IBOutlet var dollarsLabel: UILabel!

 

@IBOutlet var conversionAmount: UILabel!

 

@IBOutlet var currencyLabel: UILabel!

 

For my slider, I created an IBAction so that I can implement some code when the slider is activated.

@IBAction func adjustAmount(sender: UISlider)

{

 

var numberOfDollars = Int(sender.value * 20)

 

dollarsLabel.text = (“\(numberOfDollars) USD equals…”)

conversionAmount.text = (“\(Double(numberOfDollars) * thecurrencyConversions[theactiveCurrency])”)

 

 

}

 

This code is basic arithmetic. I take the number of dollars variable and multiply it by the currency conversion variable. I then convert this to a string which I store in the text property of my ConversionAmount label.

 

In my viewDidLoad, I simply refresh all the data.

currencyLabel.text = (thecurrencies[theactiveCurrency])

 

dollarsLabel.text = (“1 USD Equals”)

 

conversionAmount.text = (“\(thecurrencyConversions[theactiveCurrency])”)

 

amountSlider.setValue(0.05, animated: false)

The first line ensures that I’m on the correct currency. The rest of the lines of code are pretty self explanatory. Keep in mind that the reason I have access to these variables even though I did not declare them on this file is because I made them global variables in my original ViewController.swift file.

That’s all there was to it!

No Comments

New iPhone/Watchkit App: RunTracker

Known for making many health based apps, I’ve returned yet again to push another lifestyle-app into the iTunes Store. This app has taken a total of 2 days to develop for the iPhone, and I am currently working on transferring it to WatchKit as well.

This app has many features which I shall break down:

  • Tracks how far you’ve run and how fast
  • Stores a table of past runs
  • Grants the user badges based on distance accomplishments

The hardest part to code in this app was all the math related components. For example, I had to code algorithms which would convert kilometers to meters and meters to miles. I then took this calculation and converted it into a String to display to the user. I accomplished this like so:

+ (NSString *)stringifyDistance:(float)meters {

 

float unitDivider;

NSString *unitName;

 

// metric

if (isMetric) {

 

unitName = @”km”;

 

// to get from meters to kilometers divide by this

unitDivider = metersInKM;

 

// U.S.

} else {

 

unitName = @”mi”;

 

// to get from meters to miles divide by this

unitDivider = metersInMile;

}

 

return [NSString stringWithFormat:@”%.2f %@”, (meters / unitDivider), unitName];

}

 

As you can tell, the “+” sign before my method indicated that this indeed is a class method. The way I use this method is that I pass in the parameter “meters” somewhere in my code, and it takes that value through this entire method and converts it into miles and kilometers. I had all the conversion variables laid out at the top of my mile (ie. 1000m = 1 kilometer). Most of this code is self explanatory, for someone who has never written a line of code should get the general idea of what the method above is trying to execute.

 

I also had to create an algorithm that would convert my time units into a string. I did that like so:

+ (NSString *)stringifySecondCount:(int)seconds usingLongFormat:(BOOL)longFormat {

 

int remainingSeconds = seconds;

 

int hours = remainingSeconds / 3600;

 

remainingSeconds = remainingSeconds – hours * 3600;

 

int minutes = remainingSeconds / 60;

 

remainingSeconds = remainingSeconds – minutes * 60;

 

if (longFormat) {

if (hours > 0) {

return [NSString stringWithFormat:@”%ihr %imin %isec”, hours, minutes, remainingSeconds];

 

} else if (minutes > 0) {

return [NSString stringWithFormat:@”%imin %isec”, minutes, remainingSeconds];

 

} else {

return [NSString stringWithFormat:@”%isec”, remainingSeconds];

}

} else {

if (hours > 0) {

return [NSString stringWithFormat:@”%02i:%02i:%02i”, hours, minutes, remainingSeconds];

 

} else if (minutes > 0) {

return [NSString stringWithFormat:@”%02i:%02i”, minutes, remainingSeconds];

 

} else {

return [NSString stringWithFormat:@”00:%02i”, remainingSeconds];

}

}

}

 

The above method is all the time conversion code, and also is utilized as the app’s timer for when the user is running. The time and the CLLocationManager object will both start to execute as soon as the user starts the run (taps on the “start” button).

 

My last algorithm was the hardest. This one dealt with tracking the user’s pace. We all know that Distance = rate*time, and this equation is the basis for how the following code works. We can derive rate by simply dividing time from both sides. I managed to put that into code with the method below.

 

+ (NSString *)stringifyAvgPaceFromDist:(float)meters overTime:(int)seconds

{

if (seconds == 0 || meters == 0) {

return @”0″;

}

 

float avgPaceSecMeters = seconds / meters;

 

float unitMultiplier;

NSString *unitName;

 

// metric

if (isMetric) {

 

unitName = @”min/km”;

 

// to get from meters to kilometers divide by this

unitMultiplier = metersInKM;

 

// U.S.

} else {

 

unitName = @”min/mi”;

 

// to get from meters to miles divide by this

unitMultiplier = metersInMile;

}

 

int paceMin = (int) ((avgPaceSecMeters * unitMultiplier) / 60);

int paceSec = (int) (avgPaceSecMeters * unitMultiplier – (paceMin*60));

 

return [NSString stringWithFormat:@”%i:%02i %@”, paceMin, paceSec, unitName];

}

The very last line of code takes all the integer related data and converts it into a neat string.

 

That’s only my math related code. I also had to work with MapKit and CoreData, but I’ll post the code for that in the future.

 

Happy Coding!

No Comments
Rss Feeds