Tag Archives: objective-c

This Old App: Models in the Playgrounds

Back a few months ago, an  app of mine  was removed from the App Store for being too old and not updated enough. In this series of articles I’ll document what I did on rebuilding and improving the app. In our first installment I analyzed the changes necessary. In this second installment,  I’ll start making the model.

I think in Model-View-Controller or MVC. If you are not familiar with MVC, I suggest you take a look at my video in LinkedInLearning on MVC and delegates. In short, a common programming practice is to break an application into three parts: the model, the View and the controller. The model is the code that processes data. The view is the user interface.  We don’t let the view and model interact with each other. Instead we use a controller to coordinate between the two.  This way we can change one while affecting the other two minimally.

While I might get some ideas for the view in my planning stages, I tend to start  coding with the model. In one sense the controller and view are window dressing for the model, where your data is. Views and controllers are the presentation and interaction with that model.

I’ll make a confession here: I hate working on the model. It the most tedious type of programming in my mind. It has none of the glamor or action of views or controllers.  It is just data, and I’m not much of a data person. As such I’ll give you a warning that this is a bit dry, but there’s a lot there to look at, and in the case of  RunCalc, some interesting problems that drove me up the wall the first time I wrote this code.

What’s in the Old Model

Experience in mobile applications has changed me, and the model in the original code was a reminder of this.  Written in Objective-C, The model for version 1.0 was a case of putting all the eggs in one basket.  I did everything in one model.  The original model had four properties to calculate running statistics:

  • Distance
  •  Time
  •  Pace
  • Speed

I added speed to handle treadmill settings, though it is measuring the same thing as pace: How fast the runner is going.

There are four core  methods which derive pace, speed, time and distance.  Basically you can derive each like this:

distance = pace * time

time = distance / pace

pace = time / distance

speed = distance / time

My measurements were seconds for time measurements, which I would format as strings in HH:MM:SS format for display. Distance was in miles. It was easy for me to calculate test cases in miles. I had conversion methods to metric measurements for miles and kilometers.  This meant that I had pace seconds per mile and speed as mile per second, which would have some more conversion to compute it to minutes per mile and miles per hour and kilometers per hour. Metric pace was in kilometers per seconds for some unknown reason that isn’t in my original notes. I think it was laziness.

This was the basics of the model, but there were a few more features that got added to it, The first and most important was the “locking” mechanism. There is a subtle problem with using the formulas above. Suppose you change pace. What do you update, distance or time? If you update both, then your numbers are wrong because things get updated on top of each other, and you can’t change all your settings. For changes in the calculator, what you need is to lock either distance or time in place and only compute one of them when you change pace. I did this with an enumeration in the early version to keep track of what I locked.

The last part of the model was running totals for the splits. It meant I had another set of four properties with totals for distance and time. There were two more for average pace and speed.

Building the new model : Properties and Units

The original had a lot of rounding errors and strange calculations due to switching between kilometers and Imperial measurements. Unlike other measurements systems, there will be a lot of switching between units, particularly in distance, and I really didn’t think this out well the first time. Long distance running uses different distance measurements at the drop of a hat. There are 5K, 8K, 10K, and 15k races. But there are half marathons at 13.1 Miles and full marathons at 26.2 miles. This and other measurements gave me the following measurements:

  • Distance
    • Meters
    • Kilometers
    • Miles
  • Time
    • Seconds
    • Minutes:Seconds
    • Hours:Minutes:Seconds
  • Pace/Speed
    • Meters per second
    • Minutes per mile
    • Minutes per Kilometer
    • Kilometers per hour
    • Miles per hour

Instead of computing in the units I have displayed, I kept with two standard units, meters and seconds, and converted everything else from them. These units match units found in other API’s such as CoreMotion, if I ever decide to interface this with other apps or API’s.

Pace and speed are different ways of describing the same thing, so I made them the same with one measure: Meters per Second.  Everything else  is a conversion.

Derivation Functions and Locking

The derivation function problem the first time took me a month to come up with the enumeration solution. For some reason I could nt wrap my head around the initial problem of handling that many variables.  Version 2.0 will use a different solution the model. There are six methods that change the model, two for each of the three properties. Each one changed one of the two other properties For example for distance:

func distance(changedBy pace:Double) {
    self.distance = distance(pace: pace, time:self.time)
}
func distance(changedBy time:Double) {
    let newDistance = distance(pace: self.pace, time:time )
    self.distance = newDistance
}

The Model and Conversions

I built the model as described into two models. One, RunStats for the model described above and one RunStatsIntervals for a collection of RunsStats objects and calculations for finding summations of the collection data. It was here I ran into my problem: The summations would need their own conversions, which were a repeat of the conversions above.

Here’s where object-oriented programming gets its biggest strength: I made up three classes PaceStat, TimeStat, and DistanceStat, that had the conversions. IN stead of using Doubles in my RunStats class I used these three classes. I went one step more and made constructors that would work in any unit I wanted, making the result the correct unit.  For example here’s distance:

public class DistanceStat{
// Basic unit is meters
// you can use meters, kilometers or miles for this stat
private var distanceStat:Double = 0.0 //private variable so you must use the setters and getters.
//Constructors
public init (){
    self.distanceStat = 0.0
}

public init(meters:Double){
   self.distanceStat = meters
}

public init(kilometers:Double){
    distance(kilometers:Double)
}

public init(miles:Double){
    distance(miles:miles)
}

// getters distance
public func miles()->Double{
    return distanceStat / 1609.34 
}

public func meters()->Double{
    return distanceStat
}

public func kilometers()->Double{
    return distanceStat / 1000.0
}

//Setters
public func distance(meters:Double){
    distanceStat = meters
}

public func distance(miles:Double){
    distanceStat = miles * 1609.34
}

public func distance(kilometers:Double){
    distanceStat = kilometers * 1000.0
}

}

Now to specify a 8K distance, I can say

let newDistance = DistanceStat(kilometers:8.0)

and return that as miles.

print( newDistance.miles())

I do the same with pace and time. With the pace, time, and distance stat in their own classes, I can use them anywhere and get the conversions I need anywhere.  With that I can make summation functions.  I’ll total the distance and the time, and use them to get an average pace for my summation data. That summation data can be in any of the units I have for that type.

I built the model not in the app, but in a separate playground. Playgrounds, especially for models offer an excellent way of looking at all your code and making the debugging process easier.  I can type them in on either my Mac or my iPad and check how every part works, finding errors as I go.  I did for example find an error in my  conversion formulas, and was able to find and fix it from the playground.

In the next installment we’ll add the model to the old Xcode project, get more than a few errors and start hooking up some user interfaces for testing.

Converting Objective C to Swift : The Circular Picker View Example

Screenshot 2015-03-01 14.59.10Swift is a new language. Objective C is not. Sometimes you have some Objective C code and want to make it into Swift code. I had a case of that this week when a reader asked me about continuous picker view wheels. If you are familiar with the date picker it goes from 0 to 59 and then loops back to 0, making a continuous wheel. The UIPickerView does not have this ability. When asked, I did not know how to do this. The reader found some code in Objective C that did that. I did a little web searching and I did find a solution. Of course it was in Objective C, not Swift.

I’ve wanted to write a piece on converting from Objective C to Swift for a while. I didn’t have a good example to use. This makes a really good example. We’ll discuss some things you should know and try an example of converting a method for a UIPickerView from Objective C into Swift.

Header Files and Scope

Objective C uses two files for a class, unlike Swift’s single file for a class. A primary reason for this is sharing.  Some data is shared in a class, some isn’t. We refer to how much something shares as its scope. Scope rules are very different between the two languages. One of those two files in Objective C is a header file or .h file. The .h file has information that is public in scope. A public scope allows sharing. Anything private and not shared gets declared in the other file, the  implementation file. Implementation files have  a .m extension. The .h file includes properties, methods target-actions, outlets, and often protocols for delegates. It is in the header file that you find most of the class definition. The header file has no code though: it is only declarations. You will repeat all your methods and target actions in the implementation file when you write the code for it.

In the code I found the header looks like this:

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController<uipickerviewdatasource,uipickerviewdelegate>
@property (weak, nonatomic) IBOutlet UIPickerView *myPicker;
@property  NSInteger maxRows;

@end

In the header file, you will find a series of tags beginning with @. You’ll find on each property a @property tag. These will be the public properties. We have one of these as an outlet to our picker view:

@property (weak, nonatomic) IBOutlet UIPickerView *myPicker;

Let’s dissect this outlet from a Swift perspective. @property (weak, nonatomic) IBOutlet sets an outlet with a weak variable. Since Swift has an even more automatic version of Automatic Reference Counting(ARC) than Objective C, we ignore the nonatomic part. Next we have the class of the identifier, UIPickerView. Finally, we have the identifier for the property *myPicker. the asterisk (*) means  this is a pointer, which is true of most object identifiers in Objective C. Pointers in Objective C can have nil values,. It’s a good idea to their Swift equivalent an optional value.

This translates in Swift to

@IBOutlet weak var myPicker: UIPickerView!

If you never saw the difference between the two languages, you might begin to see why Swift is so speedy for coding. The outlet is merely @IBOutlet. We have a weak variable so next we have weak var. Next comes the identifier myPicker with the class UIPickerView as an optional.
Swift encourages assignment of values to variables and constants at declaration. Objective C does not. In Objective C, you declare in one place and assign in another. Often the assignment happens in the viewDidLoad method of your .m file. When reading Objective C code declarations, keep the viewDidLoad handy. For example our .h file has this line:

  @property  NSInteger maxRows;

in the .m file we have this in viewDidLoad:

self.maxRows = 10;

For all properties, Objective C requires the self identifier. These two lines equal the one line in Swift.:

let maxRows = 10

Which assigns maxRows equal to an Int of 10 and sets the type to Int. Of course this also makes this a constant, which is not the case in Objective C.

There is also an @interface tag in the .h file. Our properties and any public methods are found between this tag and the @end tag.

@interface ViewController : UIViewController<uipickerviewdatasource,uipickerviewdelegate>
…
@end

The @interface tag tells us the identifier of this class, and its superclass. In this app it is UIViewController. In angle brackets after the superclass is a list of adopted protocols. In our case we adopted the picker view data source and delegate. Again Swift simplifies this to essentially one line — and a bracket

class ViewController:UIViewController,UIPickerViewDataSource,UIPickerDelegate{
}

We have two @interface tags in any Objective-C class. The second is in the .m file, and lists private properties. For example we have this:

@interface ViewController ()
    @property NSInteger maxElements;
@end

Swift simplifies this to a mere keyword: private. The viewDidload  method tells us to set this to 10,000. Given that information we get this:

 private let maxElements = 10000

Putting that all together, we can take the header file, plus  the @interface and the viewDidLoad in the implementation file to translate them into Swift:

import UIKit
class ViewController:UIViewController,UIPickerDataSource,UIPickerDelegate{
    let maxRows = 10
    private let maxElements = 10000
    @IBOutlet weak var myPicker:UIPickerView
}

The Meat of the Matter: The Implementation File

Let’s look at the implementation file now and figure out what it is doing. I’ll assume you know about UIPickerView and its delegates.  If you don’t, read this first. The Objective C file is this:

#import "ViewController.h"

@interface ViewController ()
    @property NSInteger maxElements;
@end

@implementation ViewController

#pragma mark delegates and data source

- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView{
    return 1;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component{
    return self.maxElements;
}

- (NSString *)pickerView:(UIPickerView *)pickerView
             titleForRow:(NSInteger)row
            forComponent:(NSInteger)component{
    NSString *myString;
    NSInteger myRow = row % self.maxRows;
    myString = [NSString stringWithFormat:@"%li",(long)myRow];
    return myString;
}

#pragma mark life cycle
- (void)viewDidLoad {
    [super viewDidLoad];
    self.maxElements = 10000;
    self.maxRows = 10;
    self.myPicker.delegate = self;
    self.myPicker.dataSource = self;
    [self.myPicker selectRow:self.maxElements / 2  inComponent:0 animated:NO];
}

@end

If you have never worked in Objective C before, your biggest challenge is how they put stuff backwards from Swift, C++, Java or most any other language.

Objective C bases its syntax on an older language, Smalltalk. It was a Smalltalk demonstration that inspired Steve Jobs to come up with the Macintosh in the early 1980’s. Both Smalltalk and Objective C look at objects very literally. You state what your object is and then what you want to do with it. You enclose that in square brackets. For example we have

[super viewDidLoad];

which runs the superview’s viewDidLoad. Swift writes that as a function

super.viewDidLoad()

Since this is a picker view, we need to add two data source methods to tell us about our data and one delegate method. Let’s look at one of those methods:

- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView{
    return 1;
}

This implements one of our two required data source methods. We have one component in our picker view, so we return 1. The minus sign at the beginning of the method declaration tells the compiler and developer that this is an instance method. If it was a plus it would be a class method. Next,  the return type is in parentheses, followed by the method identifier. If there are parameters, the parameter list follows. In Swift that looks like this:

func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}

The syntax is very different between the two, but the same information is there. The next data source method works the same, returning a value for the number of rows in the picker, which in this case is a lot.

- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component{
return self.maxElements;
}

We use maxElements to set this size, which we know is 10,000 rows. Why do we need that many rows? The answer lies in the delegate method, titleForRow:

- (NSString *)pickerView:(UIPickerView *)pickerView
             titleForRow:(NSInteger)row
            forComponent:(NSInteger)component{
    NSInteger myRow = row % self.maxRows;
    NSString *myString = [NSString stringWithFormat:@"%li",(long)myRow];
    return myString;
}

The declaration tells us we return a string, and have the parameters of the picker view, the row and the component. The code declares an NSInteger, called myRow which is the modulo of row and maxRows. We take this new value, convert it to a NSString, and then return the string. Unlike properties, in methods we can declare and assign at the same time. However, we need to declare the type when we do.

What does this do? The method takes a massive set of numbers and has a row in that set of 10,000. It takes the remainder of row divided by maxRows. That remainder will repeat between 0 and maxrows - 1.  In effect, the picker repeats between 0 and 9 in our case. If the number for maxElements is big enough, it is unlikely that we will run out of numbers for repetition. Since these are integers, you’ve used a small amount of memory to do this.

You can write the method like this in Swift:

    func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {
        let myRow = row % maxRows
        let myString = String(format: "%i", myRow)
        return myString
    }

We returned the string as an optional. When converting from Objective-C to Swift, anything that is a pointer is best converted as an optional.

But we are not done yet. The Objective C code still has the viewDidload method.

- (void)viewDidLoad {
[super viewDidLoad];
self.maxElements = 10000;
self.maxRows = 10;
self.myPicker.delegate = self;
self.myPicker.dataSource = self;
[self.myPicker selectRow:self.maxElements / 2 inComponent:0 animated:NO];
}

The viewDidload method does not need to assign initial values in Swift. That happens when we declare a value. Objective C requires you to explicitly say where something is with self, while Swift is better at guessing. We can get rid of the first two assignments, and get rid of all the self references, though you can leave them there if you wish. The last line of the method makes a call to myPicker and selects a specific row in the picker: 5,000. This way if we roll up or down we will get a repeat. All this in Swift looks like this:

override func viewDidLoad() {
        super.viewDidLoad()
        myPicker.dataSource = self
        myPicker.delegate = self
        myPicker.selectRow(maxElements / 2, inComponent: 0, animated: false)
    }

Our Swift file looks like this now:


import UIKit

class ViewController: UIViewController,UIPickerViewDataSource,UIPickerViewDelegate {
    //MARK: Properties
    let maxRows = 10
    private let maxElements = 10000

    //MARK: Outlets
    @IBOutlet weak var myPicker: UIPickerView!
    func platypus(){
        //doesn't do much

    }
    //MARK: Delegates and DataSources
    func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
        return 1
    }
    func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        return maxElements
    }
    func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {
        let myRow = row % maxRows
        let myString = String(format: "%i", myRow)
        return myString
    }

    //MARK: Life cycle
    override func viewDidLoad() {
        super.viewDidLoad()
        myPicker.dataSource = self
        myPicker.delegate = self
        myPicker.selectRow(maxElements / 2, inComponent: 0, animated: false)
        platypus()
    }

}

If you’d like to try this code out, make a new single view project. Drag a Picker View  and a label out on to the storyboard. Make it look like this:

Screenshot 2015-03-01 13.56.14

Copy the code above into the ViewController.swift file of your project.

Using the assistant editor, control-drag from the picker to the myPicker outlet. Control-drag from the I want coffee!! label to the Assistant editor. Name the new outlet statusLabel.

Build and run:

 

Screenshot 2015-03-01 14.08.54

 

Using Text Arrays

Not everyone will want the row number. Most likely, you will want something else listed in your picker view. If you want to use text, set up an array like this:

private let coffee = ["Coffee","Latte","Mocha","Machiatto","Frappucino","Espresso","Red Eye","Black Eye","Espresso","Irish Coffee"]

Change the pickerView:titleForRow: to this.

func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {
        let myRow = row % coffee.count
        //let myRow = row % maxRows
        //let myString = String(format: "%i", myRow)
        let myString = coffee[myRow]
        return myString
    }

We take the repeating row and use that for the index to the array. Build and run:

 

Screenshot 2015-03-01 14.09.28

 

Returning Values

To get a value from a selected wheel, we use the modulo again. This time in the didSelectRow delegate method. Add this to the code:

func pickerView(pickerView: UIPickerView,didSelectRow row: Int,inComponent component: Int){
        let myRow = row % coffee.count
        let myString = coffee[myRow]
        statusLabel.text = "I love " + myString + "s"
    }

Build and run:

Screenshot 2015-03-02 07.54.18

You can add one more line. For most simple cases it isn’t necessary if you have plenty of space to spin, but there may be times you need to limit your space, or prevent running out of space. You can add this or something like it to didSelectRow:

pickerView.selectRow((maxElements / 2) + row, inComponent: 0, animated:false)

I’d leave maxElements at 10000, and this means maxElements/2 is 5000. Since 5000 a number ending in 0,  we can position the picker back at the middle plus offset of myRow. Whenever the wheel stops, we are back a the middle. Note if maxElements/2 does not divide evenly to 0, you might run into problems and need a little more complicated math.

This is the basics of building a repeating picker view. It also illustrates some of the important issues you need to watch if converting between old Objective-C and Swift. These are not the only issues. Apple has an  e-book on the subject of using Objective-C and Swift, and it is worth the time reading.

The Whole Objective – C Code

//
//  ViewController.h
//  InfinitePicker
//
//  Created by Steven Lipton on 2/28/15.
//  Copyright (c) 2015 MakeAppPie.Com. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController<uipickerviewdatasource,uipickerviewdelegate>
@property (weak, nonatomic) IBOutlet UIPickerView *myPicker;
@property  NSInteger maxRows;

@end
//
//  ViewController.m
//  InfinitePicker
//
//  Created by Steven Lipton on 2/28/15.
//  Copyright (c) 2015 MakeAppPie.Com. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()
    @property NSInteger maxElements;
@end

@implementation ViewController

#pragma mark delegates and data source

- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView{
    return 1;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component{
    return self.maxElements;
}

- (NSString *)pickerView:(UIPickerView *)pickerView
             titleForRow:(NSInteger)row
            forComponent:(NSInteger)component{
    NSString *myString;
    NSInteger myRow = row % self.maxRows;
    myString = [NSString stringWithFormat:@"%li",(long)myRow];
    return myString;
}

#pragma mark life cycle
- (void)viewDidLoad {
    [super viewDidLoad];
    self.maxElements = 10000;
    self.maxRows = 10;
    self.myPicker.delegate = self;
    self.myPicker.dataSource = self;
    [self.myPicker selectRow:self.maxElements / 2  inComponent:0 animated:NO];
}

@end

The Whole Swift Code

//
//  ViewController.swift
//
//  Created by Steven Lipton on 2/28/15.
//  Copyright (c) 2015 MakeAppPie.Com. All rights reserved.
//

import UIKit

class ViewController: UIViewController,UIPickerViewDataSource,UIPickerViewDelegate {
    //MARK: Properties
    let maxRows = 100
    private let maxElements = 10000
    private let coffee = ["Coffee","Latte","Mocha","Machiatto","Frappucino","Espresso","Red Eye","Black Eye","Espresso","Irish Coffee"]

    //MARK: Outlets
    @IBOutlet weak var myPicker: UIPickerView!
    @IBOutlet weak var statusLabel: UILabel!

    //MARK: Delegates and DataSources
    func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
        return 1
    }
    func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        return maxElements
    }
    func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {
        //let myRow = row % maxRows
        //let myString = String(format: "%i", myRow)
        let myRow = row % coffee.count
        let myString = coffee[myRow]
        return myString
    }

    func pickerView(pickerView: UIPickerView,didSelectRow row: Int,inComponent component: Int){
        let myRow = row % coffee.count
        let myString = coffee[myRow]
        statusLabel.text = "I love " + myString + "s"
        //if you want to use less elements in maxElements
        // or prevent ever running to the end of the list in your pickerview
        //you can set yourself back to the middle. It is not necessary for most cases.
        pickerView.selectRow((maxElements / 2) + row, inComponent: 0, animated:false)
    }

    //MARK: Life cycle
    override func viewDidLoad() {
        super.viewDidLoad()
        myPicker.dataSource = self
        myPicker.delegate = self
        myPicker.selectRow(maxElements / 2, inComponent: 0, animated: false)
    }

}

Living Without Storyboards or Interface Builder: Grids and a Grid Class

Using Grids

As Steve Jobs liked to say… “Oh, and one more thing more thing.”
In my last post Living without Storyboards or Interface Builder, I mentioned scribbling on a piece of paper.

IMG_4295

I do that often, but it is helpful to go one step further: use a preset grid.

The web building world, at least the graphic designers there, love these things. Here’s two examples one for a iPhone 4 and 5;

iphone 4 grid iphone 5 grid

The white areas are content, the color areas are space called padding between the content. I then use them to plot our elements on a screen. I can for example plot something out like I have at the right. iphone 4 grid with buttonsI get to know exactly where everything is and everything aligns perfectly.

So let’s think this out:

Grids are can be thought of as cells. This is the way web development Tkinter and other systems thinks of content. Both CSS and Tkinter thinks of padding as an internal margin of the cell, margins are external to the object.

Programming Grids

Usually I’m trying to translate from Xcode to Python, but this post is a reverse situation. Tkinter can take my paper grids and translate them into code relatively easy with .grid method. If working in Interface builder, this is a small problem. Using auto layout , one can make sense of a grid, if one is careful. Get into Objective-C and Xcode with some programmatic UIViews, and you are stuck with some very messy CGRect frames. I really want something more like Tkinter’s .grid()method. I want to draw a 6×9 grid with 10 point padding on paper and say something equivalent to

.grid(row =6, column = 0, rowspan = 3 columnspan =4)

With that code I get the button on any device in the same spot, stretched correctly for the device.

So I made a class for Objective-C to do exactly that. Let’s look at it.Screenshot 2014-04-24 07.21.20

Let’s start with the illustration of a content cell that is 168px by 168px. Of the 168px, we take 12pixels on each side as padding, leaving us with 144px for actual content. This math works for paints as well a pixels, so it works for setting up a class to calculate the size of a cell anywhere.

There are the following possibilities for making a grid:

  • A completely flexible grid: give a number of columns and rows in the grid. Scale the dimensions so all cells fit in the grid. This will be rectangles, not squares. It will always fit a complete grid in the view.
  • A row grid of squares : Given the number of rows,  calculate a grid size based on squares of that size. You may have to crop squares on the bottom.
  • A column grid of squares: Given the number of columns, calculate a grid based on squares of that size. Again you may have partial squares on one side.

There are other possibilities  to make a grid. For the two which leave partial squares, we could add the partial square to the margin.

I’ll do the first case here. The others I’ll leave to others or I’ll do them later.

Coding Grids

What I’m calling the margin is  either an external margin of the cell, or a padding of the superview of the cell, which contains the view we want to position. We will set a public property for the padding

@property CGFloat padding;

If we think of margins as a padding of a superview, with one method we can do two steps with one method. Given a frame of a certain size, we find the space we can put content into due to the padding. This work for our margins too.

//makes a frame given a size and padding.
-(CGRect)makeContentRectFromSize:(CGSize)size {
    CGRect frame;
    frame.size.width = size.width  -  (2 * self.padding);
    frame.size.height = size.height - (2 * self.padding);
    frame.origin.x = self.padding;
    frame.origin.y = self.padding;
    return frame;
}

Once we know that, we can set the size of the grid. We’ll use manually set grids not automatically proportional like .grid(). I really debate about the how to name properties for column and row size of the grid. I could make this a CGSize, or two separate values. I started with separate properties to parallel Tkinter, and I’ll probably make some convenience methods later to accept CGSize as well. We have as public methods in our .h:

@property int totalRows;
@property int totalColumns;

Next we figure out the size of the cell by finding the usable area in a frame, and dividing it up to get a height and width for a cell.

-(CGSize)cellSize{
    CGRect frame = [self makeContentRectFromSize: self.viewFrame.size];
    CGSize cellFrameSize;
    cellFrameSize.width = frame.size.width/self.totalColumns;
    cellFrameSize.height = frame.size.height/self.totalRows;
    return cellFrameSize;
}

We’ll need a few more public properties: row and column origin and size:

@property int row;
@property int column;
@property int rowspan;
@property int columnspan;

We can now use everything to make a frame to put our content. First find the origin position of the CGRect in the coordinate system of its parent. We need to put a few things together:

  • The size of the cell times its row or column location,
  • A bit more for its padding
  • A bit more for the margin

For the size we have two parts:

  • The size of the cell times the span of the cell
  • Remove a bit for the padding.

We now use those parts to write the following method:

 
-(CGRect)gridLayoutRect{
//step 1 - find the size of the space inside the margin
    contentFrame = [self makeContentRectFromSize:self.viewFrame.size];
//step 2 - find the size of the cell
    CGSize cellFrameSize = [self cellSize];
//Step 3 - find the coordinates of the origin taking into account padding and margin
    subviewFrame.origin.x = (cellFrameSize.width * self.column) + self.padding + contentFrame.origin.x; 
    subviewFrame.origin.y = (cellFrameSize.height * self.row) + self.padding + contentFrame.origin.y; 
//Step4 - find the size of the rect
    subviewFrame.size.height = cellFrameSize.height * self.rowspan - self.padding;
    subviewFrame.size.width = cellFrameSize.width * self.columnspan - self.padding;
//Step 5 — return it
    return subviewFrame;
}

I made a few overrides for this method which will help in its use:

-(CGRect)gridLayoutRect:(CGPoint)origin size:(CGSize)size{
    self.row = origin.y;
    self.column = origin.x;
    self.columnspan = size.width;
    self.rowspan = size.height;
    return [self gridLayoutRect];
}

-(CGRect)gridLayoutRect:(CGRect)grid{
    self.row = grid.origin.y;
    self.column = grid.origin.x;
    self.columnspan = grid.size.width;
    self.rowspan = grid.size.height;
    return [self gridLayoutRect];
}

We need some initializers as well:

-(void) initWithFrame:(CGRect)frame rows:(int)totalRows columns:(int)totalColumns{
    _viewFrame = frame;
    _totalRows = totalRows;
    _totalColumns = totalColumns;
//set some default values
    _rowspan =1;
    _columnspan =1;
    _padding = 10;
    _row = 0;
    _column = 0;
    
}

-(void) initWithFrame:(CGRect)frame{
    _viewFrame = frame;
//set some default values
    _totalRows = 6;
    _totalColumns  = 9;
    _rowspan =1;
    _columnspan =1;
    _padding = 10;
    _row = 0;
    _column = 0;

}

Import that into the view controller and initialize the object in ViewDidLoad.

Using our Class

Now I can use this like this in a text field for our power panel:

//make the  TIME text field
    timeText = [[UITextField alloc]initWithFrame:[myGridLayout gridLayoutRectRow:1 column:2 rowSpan:1 columnspan:2]];
    timeText.placeholder = @"00";
    [self.view addSubview:timeText];

One cool use is to make a quick series of buttons:

    //make a series of buttons with a for loop
    for(int i=0;i<5;i++){
        //make the button
        UIButton *seriesButton=[UIButton buttonWithType:UIButtonTypeSystem];
        
        //set the grid location
        myGridLayout.row = 3;
        myGridLayout.column = i;
        myGridLayout.columnspan = 1;
        myGridLayout.rowspan = 1;
        seriesButton.frame = [myGridLayout gridLayoutRect];
        
        //properties for the button
        seriesButton.backgroundColor = [UIColor blueColor ];
        [seriesButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
        [seriesButton setTitle:[NSString stringWithFormat:@"%i",i] forState:UIControlStateNormal];
        //set the target action.
        [seriesButton addTarget:self action:@selector(sequenceButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
        //add to the view
        [self.view addSubview:seriesButton];
    }

When we put everything together, build and run we get this:
iOS Simulator Screen shot Apr 25, 2014, 4.12.03 PM

Using Selectors for UIButtons and Other Things

There is one line here which needs comment.

 [seriesButton addTarget:self action:@selector(sequenceButtonPressed:) forControlEvents:UIControlEventTouchUpInside];

The selector uses SquenceButtonPressed: that points to this method:

-(void)sequenceButtonPressed:(UIButton *)sender{
timeText.text = sender.titleLabel.text;
}

I didn’t point it out before but thought I might now. You do not spell out the parameter in the selector. But you do put a colon to tell the system it is there. So just like a target action for IB, you can set up target actions (or use ones that already exist) that refer to their button.

There is a lot that can be done with this, but this is a basic framework for setting up grids in Xcode. While IB would seem to make this unnecessary, there are places it becomes very important. I already mentioned UIImagePickerController’s camera overlay. One I haven’t talked about here in any detail is the lack of IB for Sprite Kit. There are no buttons in Sprite kit, but there are time buttons are very necessary. That issue we’ll take up in an upcoming installment of the SlippyFlippy Challenge.

The full code can be found at : https://github.com/MakeAppPie/SGNoStoryBoardGrid

SlippyFlippy 1.1: Adding a Fading-in and out Label with Background in SpriteKit

icon2_120Today we have a bug to deal with in SlippyFlippyPenguin. There are a two reports of when a user selects the hard skill level  the game  immediately goes to game over. I cannot find anything that is different in the code to account for this except user error. I think the user error is users not realizing how fast they have to take controls in the hard mode. The penguin drops to the bottom, and ends the game before they can react. I’ve had more reports from a lot other users that is a user problem.  It is the speed that flippy drops after pressing the button that gets them. The  game is not clear about Slippy touching the sides or about what you are to do — and all of that  happens fast.

So here is what I’m going to do.

  • Add directions as messages that appear and disappear.
  • Add a countdown timer before starting

I’ll  implement this in two stages. Lets’ start with placing a message on the screen. What we need to do is flash a string on the screen, then make it disappear.

-(void)flashMessage:(NSString *)message atPosition:(CGPoint)position duration:(NSTimeInterval)duration{
//a method to make a sprite for a flash message at a certain position on the screen
//to be used for instructions

//make a label that is invisible
     SKLabelNode *flashLabel = [SKLabelNode labelNodeWithFontNamed:@"MarkerFelt-Wide"];
     flashLabel.position = position;
     flashLabel.fontSize = 17;
     flashLabel.fontColor = [SKColor blackColor];
     flashLabel.text = message;
     flashLabel.alpha =0;
     flashLabel.zPosition = 100;
     [self addChild:flashLabel];
//make an animation sequence to flash in and out the label
     SKAction *flashAction = [SKAction sequence:@[
           [SKAction fadeInWithDuration:duration/3.0],
           [SKAction waitForDuration:duration],
           [SKAction fadeOutWithDuration:duration/3.0]
]];
// run the sequence then delete the label
[flashLabel runAction:flashAction completion:^{[flashLabel removeFromParent];}];

}

Pretty straightforward code, and the comments make clear each of our steps:

  • Make a label node
  • Set its properties, and make it invisible
  • Make an action that fades in the label, shows it, then fades it out
  • Run the action, then remove the sprite.

Couple of items to note here: it’s important to set the z-height to 100, so the messages are not obscured by anything in the game. A new method for me  was runAction:completion: which here immediately removes the node when the animation is done. I think this will be a good practice, and will be a modification to what I actually did in the SlippyFlippy challenge when I write about it shortly.

We implement that method in the touchesBegan: code when we select our difficulty level;

else if (CGRectContainsPoint(hardRect, location)){
                //   NSLog(@" Hard TOUCH!!");
                [self flashMessage:@"Avoid the sides" atPosition:CGPointMake(CGRectGetMidX(self.frame), CGRectGetMaxY(self.frame)*0.1) duration:3];
                [self flashMessage:@"Avoid the sides" atPosition:CGPointMake(CGRectGetMidX(self.frame), CGRectGetMaxY(self.frame)*0.8) duration:3];
                [self flashMessage:@"Tap the screen to move Penguin" atPosition:CGPointMake(CGRectGetMidX(self.frame), CGRectGetMaxY(self.frame)*0.65) duration:1];
                [myLabel removeFromParent];
                [[self childNodeWithName:@"easy button"] removeFromParent];
                [[self childNodeWithName:@"hard button"] removeFromParent];
               
Notice I keep everything a relative position, a percentage of the full screen. This helps with the screen size fragmentation problem, and keeps everything proportional. 

We end up with this: iOS Simulator Screen shot Apr 1, 2014, 7.39.46 PM

This is good, but it needs a background to stand out more. So I made two more nodes: a SKNode as a container, and a SKSpriteNode as a background. I’ll put the label and the Sprite into the node and then animate the node. Note I had to set the label’s verticalAlignmentMode to center from its default baseline alignment. Otherwise our positioning is on the baseline of the text, and fails to align with the background.

 
-(void)flashMessage:(NSString *)message atPosition:(CGPoint)position duration:(NSTimeInterval)duration{
//a method to make a sprite for a flash message at a certain position on the screen
//to be used for instructions

//make a label
     SKLabelNode *flashLabel = [SKLabelNode labelNodeWithFontNamed:@"MarkerFelt-Wide"];
     flashLabel.verticalAlignmentMode = SKLabelVerticalAlignmentModeCenter;
     flashLabel.fontSize = 17;
     flashLabel.fontColor = [SKColor whiteColor];
     flashLabel.text = message;


//make a background based on the size of the label
     CGSize mySize = flashLabel.frame.size;
     mySize.height *=1.5;
     mySize.width *= 1.2;
     SKSpriteNode *background = [SKSpriteNode spriteNodeWithColor:[UIColor redColor] size:mySize];

//make a container node
     SKNode *flashLabelNode = [SKNode node];
     flashLabelNode.position = position;
     flashLabelNode.zPosition = 100;
     flashLabelNode.alpha = 0;
     flashLabelNode.name = @"flashLabelNode";
//add the node tree together
     [flashLabelNode addChild:background];
     [flashLabelNode addChild:flashLabel];
     [self addChild:flashLabelNode];

//make an animation sequence to flash in and out the label
     SKAction *flashAction = [SKAction sequence:@[
          [SKAction fadeInWithDuration:duration/3.0],
          [SKAction waitForDuration:duration],
          [SKAction fadeOutWithDuration:duration/3.0]

     ]];
// run the sequence then delete the label
     [flashLabelNode runAction:flashAction completion:^{[flashLabelNode removeFromParent];}];

}

So our steps here are:

  • Make the SKLabelNode
  •  Make a background slightly bigger than the label’s size with a SKSpriteNode.
  • Make a SKNode as a container, then add the label and sprite to the node.
  • Make the action, though this time directed at the SKNode instead of the SKLabelNode
  • Perform the action, then remove the node.

iOS Simulator Screen shot Apr 1, 2014, 7.38.04 PMThis works but it leaves a bit of a problem. I don’t get rid of the labels when I need to. In a game over situation, the labels are still there, but I don’t want them there. I need to remove the labels completely at a game over state.

Lets remove all flash labels in one purge using the enumerateChildNodesWIthname:usingBlock: method

-(void)removeAllFlashMessages{

     [self enumerateChildNodesWithName:@"flashLabelNode" usingBlock:^(SKNode *node, BOOL *stop) {
          [node removeAllActions];
          [node removeFromParent];
     }];
}

iOS Simulator Screen shot Apr 1, 2014, 7.38.13 PMThat works great. I might want to identify the labels so I can get rid of them at events, but I’ll do that later.

Next time,  we will do the countdown timer.

from Apple to Raspberry Pi: Making Classes in Python

appleberryObjective-C and Python are similar when it comes to defining new classes, but be careful with their differences. In Objective-C we would define a class with two files: a header and an implementation file. In the header we would declare properties like this

@interface PDPythonStuff : NSObject
     @property int a;
     @property int b;
@end

And possibly public methods

@interface PDPythonStuff : NSObject

     @property int a;
     @property int b;

     +(int)myFunction:(int)a b:(int)b;
     -(int)montyFunction:(int)a b:(int)b;
     -(int)montyFunction;
@end

In the implementation file we would have the code for the methods

@implementation PDPythonStuff

+(int)myFunction:(int)a b:(int)b{
    return a+b*b;
}

-(int)montyFunction:(int)a b:(int)b{
    return a+b*b;
}
-(int)montyFunction{
    return self.a+self.b*self.b;
}

@end

Finally we import the class into another class we are working with, such as a ViewController subclass

#import "PDMontyPython.h"

We would set up a property of the subclass for our instance

@interface PDViewController ()

    @property PDPythonStuff *montyPython;

@end

Allocate space and initialize the instance

    PDPythonStuff *montyPython = [[PDPythonStuff alloc]init];

We are now free to use it. A very simple example would be this which executes with the press of a button:

@implementation PDViewController{

}
- (IBAction)myButtonPressed:(UIButton *)sender {
    //calling the class method
    NSLog(@"myFunction PDPythonStuff = %i",[PDPythonStuff myFunction:5 b:25]);

    //initialize an instance
    PDPythonStuff *montyPython = [[PDPythonStuff alloc]init];
    //the method with parameters
    NSLog(@"myFunction montyPython = %i",[montyPython montyFunction:5 b:25]);

    //set the properties
    montyPython.a=5;
    montyPython.b=25;

    //the method using properties
    NSLog(@"myFunction montyFunction = %i",[montyPython montyFunction]);

}

@end

Xcode does a lot to make the class without our working for it. There are no constructors, setters or getters that need implementation, like Java or C++. Prior to XCode 4.4, you did need the @synthesize, but even that isn’t necessary anymore. It’s all automatic or not needed. Granted, you can make you own setters and getters, but it isn’t mandatory.

Python’s class definitions are quite interesting in that context:

#Objects_01
class PDPythonStuff:
    def __init__(self,a,b):
        self.a=a;
        self.b=b;
    def myFunction(self,a,b):
        return a + b*b

    def montyFunction(self):
        return self.a + self.b * self.b

# test implementation of the class
c=PDPythonStuff(5,25)
print('my Function =',c.myFunction(5,25))
print('my Function =',c.myFunction(4,25))
print('my Function =',c.montyFunction())
c.a = 4
print('my Function =',c.montyFunction())

Like defining functions, Python is super simple in defining classes. We don’t need to define what is public or private, or what is a class or instance method. With all those definitions missing, our code is a lot smaller. We start with a class operator name, then have a series of functions in the class. The first function among them __init__ is very important. As we saw above, Objective-C does have an init method, and can set beginning values for the instance. In Python __init__ is the constructor for the class. We do not have a header .h file in Python like Objective-C to declare what our properties are. Therefore we must declare their existence somewhere and the best place is in __init__.

Add the following function to the class:

    def montyFunctionToo(self):
        return self.a + self.d *self.d

Now add under the other print functions

print('my Function =',c.montyFunctionToo())

Save and run. You will get a error:
AttributeError: 'PDPythonStuff' object has no attribute 'd'

Nowhere did we define a what I would call a property in XCode, or attribute in Pythonspeak, called d. Python is angry at us for that. In the __init__ add:

self.d = 10

Save and run again, and things will work fine again. You do not have to put the initial value in the parameter list.

Note the first parameter in each def here is self. It is mandatory for methods of a class to have self as the first parameter in the definition. So we have

def myFunction(self,a,b):
        return a + b*b

We do not need self when we call the method:

print('my Function =',c.myFunction(4,25))

Note the def for a  function that has no parameters still has self.

  def montyFunction(self):
        return self.a + self.b * self.b
...
print('my Function =',c.montyFunction())

Now that we can make some classes, we can start to use them in Python. We’ll discuss more about classes and some cautions about them in our next entry.

The Slippy Flippy Dare: How to Use Basic Physics in Sprite Kit

In the last installment of this series I showed two kinds of animation: SKAction and using the update: method from frame animation. The third major type of animation is using the physics engine.

A physics engine takes the mathematical laws of physics and adds them to the scene. It removes the developer from the math involved. It also adds collision detection, and the physics of collisions. In short, your sprite can work in the scene the same way real objects work in the real word.

To start let’s make sure everyone is in the same place.  If you have not done so, open a Sprite kit template in Xcode. If you have followed along, open your code.

Modify your code  so it should look like this:

-(id)initWithSize:(CGSize)size {
if (self = [super initWithSize:size]) {
/* Setup your scene here */

self.backgroundColor = [SKColor colorWithRed:0.15 green:0.15 blue:0.3 alpha:1.0];

/* Make a penguin */

//Initialize a sprite with a texture from a file.
SKSpriteNode *penguin = [SKSpriteNode spriteNodeWithImageNamed:@"gray penguin";];
penguin.position = CGPointMake(0, 0);
penguin.name = @"penguin";
SKAction *movePenguin = [SKAction moveTo:CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame)) duration:2.0];
[penguin runAction:movePenguin];

[self addChild:penguin];

}
return self;
}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
/* Called when a touch begins */

for (UITouch *touch in touches) {
/* commented out code */

}
}

-(void)update:(CFTimeInterval)currentTime {
/* Called before each frame is rendered */
CGPoint position = [[self childNodeWithName:@&quot;penguin&quot;] position];
if (++position.y &amp;lt;= CGRectGetMidY(self.frame)){
[[self childNodeWithName:@"penguin";] setPosition:CGPointMake(++position.x, ++position.y) ];
}

}

gray penguinIf you are starting with new code, download the penguin graphic to your computer, name it gray penguin.png and drag it into the file list in Xcode. This includes cleaning out most of the original template code. There will be a warning in the touchesBegan: method. We will come back to that very shortly.

Physics turns on and off for individual sprites. Add the following code just below the penguin.name assignment:

penguin.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:penguin.frame.size];
penguin.physicsBody.affectedByGravity = NO;

Line 1 turns on the physics engine. All sprites have a property which holds a SKPhysicsBody object. We initialize that object with a class method bodyWithRectangleOfSize: and give the size of the penguin.

By default, gravity is on. To start we turn off gravity, so the penguin’s SKAction can execute in peace. Build and run the code and the penguin should move to the middle of the screen. Change the affectedByGravity to YES and run again. You see Slippy fighting gravity to get to the middle and then falling off the screen. Set affectedByGravity back to NO.
in touchesBegan:, change the for loop with the code:

for (UITouch *touch in touches) {
        
        [[[self childNodeWithName:@"penguin";] physicsBody] setAffectedByGravity:YES];
    }

Build and run. The penguin moves to the center. When the player touches the screen anywhere, we will turn the gravity on. Slippy then falls off the screen. However, we really don’t want Slippy falling off and out of sight. To solve this,  give the visible scene a physics body. In initWithSize: add the following under the self.background assignment:

//a physics body to prevent the penguin from going off the screen.
        self.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:self.frame];

Here we used a different type of physics body, an edge loop. This builds a collision body that is only a line instead of a solid body, so the penguin is now trapped inside the frame. Edge loops, unlike bodies, are not affected by gravity by default. Try building and running with this change. Slippy now falls to the bottom of the screen, and bounces into the left corner.

The default gravity is earth normal. Add this code just above the comment for the code you just entered.

self.physicsWorld.gravity = CGVectorMake(0.0, -9.8); //-9.8 Earth normal gravity

On the scene we set up a physicsWorld which gives some environmental properties to physics. If you run this, you will see no change. The -9.8 is earth normal gravity, a value known in physics as g.  Over at The Physics Classroom,  they discuss the value of g.  Included there is a table for g for different planets. If Slippy was on Mars, g becomes 3.75.  We set gravity to pull down by putting a negative sign in front of it. Change the -9.8 or earth normal to -3.75. Now Slippy falls as if he is on Mars. In the real game, the penguin is on a tilting ice sheet and we are looking at the sheet from above. Gravity is much less than 9.8, and I ended up deciding on -7.0 for my gravity. Note if I put 7.0 for gravity, slippy would fall up. In the real game, I multiply the gravity by -1 to change the sign periodically, flipping gravity for a bit more of a challenge.

We don’t want Slippy to fall so we need some way of making him move up. What we need to do is give our penguin a push. The  applyImpulse: method does this by pushing the penguin with a specified force in the x and y directions. Change the code in touchesBegan: to the following:

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    /* Called when a touch begins */
    
    if ([touches count]>0) {
        SKNode *penguin =[self childNodeWithName:@"penguin";];
        if (penguin.physicsBody.affectedByGravity){
            //[penguin.physicsBody applyImpulse:CGVectorMake(0, 0)];
            [penguin.physicsBody applyImpulse:CGVectorMake(0, 7)];
        } else{
            penguin.physicsBody.affectedByGravity = YES;
        }
    }
}

Figuring the position of our touch on the screen is necessary for many games , and the template has code to handle that case . For our game touching anywhere is good. We only need to know if there are any touches. We changed from the fast enumenration for loop of the template whihc list touches to an if...else statement that looks for any touch.

To reference the penguin easier, we created a SKNode and assigned a pointer to the object. We then check if gravity is on. If it is, we are in game mode. If not, we are in game over/start mode. In game mode we use a method applyImpulse and applied an impulse of 7 in the upward direction. Run this and you find no real change. Change 7 to 30 and see what happens. If you tap very quickly you can move the penguin up a little bit.

We are trying to play volleyball with a dumbell.  Slippy is too heavy or too dense. We need to change his mass or density. I’ll change his density to 0.1. In touchesBegan: change the else block to:

} else{
            penguin.physicsBody.affectedByGravity = YES;
            penguin.physicsBody.density = 0.1;
        }

Now run and tap the screen. Pretty much this is  Flappy Bird’s animation behavior. One more line makes the graphics just a bit better. Remove the comment from the second applyImpulse. This stops motion before applying then new impulse.

That is some the basics of physics engines.  We will explore more of physics engines and collisions, but first we need an obstacle to crash into. That will be our next installment.

From Apple to Raspberry Pi: While Loops

appleberry
In Xcode, both in Objective-C and C, we have the while loop.

int number = 5;
while (number > 0){
    NSLog(@"The number is %i",number--);
}

The python equivalent is also while Since we already understand the block, know sometimes as a suite in Python, while loops in  Python are very simple to use.

number = 5
while number > 0:
    number = number -1
    print ('The number is ', number)

We can use break in a loop to break execution. This is a valid loop if we need to test at the end of the loop

number = 5
while True:
    number = number -1
    print ('The number is ', number)
    if number < 0:
        break